Tailwind CSS Handbook v4.3

Overflow & Layering

Control clipping and scrolling with overflow-*, and manage what sits on top with z-index, isolation and stacking contexts.

Two problems that show up together: what happens when content is too big for its box, and what happens when boxes overlap.

Overflow#

UtilityBehaviour
overflow-autoScrollbars only when needed
overflow-scrollScrollbars always reserved
overflow-hiddenClip, no scrolling
overflow-clipClip, and disable programmatic scrolling too
overflow-visibleDefault — content spills out
overflow-x-auto / overflow-y-autoPer-axis
Loading preview…

Overflow's side effects#

overflow does more than clip. Setting anything other than visible:

  • Creates a block formatting context — floats are contained, margins stop collapsing.
  • Makes the element a scroll container, which breaks position: sticky on descendants.
  • Clips absolutely positioned children, even ones intended to escape.

Rounded corners need clipping#

HTML
<div class="overflow-hidden rounded-xl border border-gray-200">
  <img class="w-full" src="…" alt="">
</div>

Without overflow-hidden the image's square corners poke through the rounded border.

Scroll behaviour#

UtilityPurpose
scroll-smoothAnimate programmatic scrolling
overscroll-containStop scroll chaining to the page
snap-x / snap-mandatory + snap-startScroll snapping
scroll-mt-*Offset for anchor targets under a sticky header
HTML
<div class="flex snap-x snap-mandatory gap-4 overflow-x-auto pb-4">
  <div class="w-64 shrink-0 snap-start rounded-lg bg-gray-100 p-4">Slide 1</div>
  <div class="w-64 shrink-0 snap-start rounded-lg bg-gray-100 p-4">Slide 2</div>
</div>

Scrollbar styling#

v4.3 First-party scrollbar utilities.

UtilityCSS
scrollbar-auto / scrollbar-thin / scrollbar-nonescrollbar-width
scrollbar-thumb-*Thumb colour
scrollbar-track-*Track colour
scrollbar-gutter-auto / -stable / -bothscrollbar-gutter
HTML
<div class="scrollbar-thin scrollbar-thumb-sky-700 scrollbar-track-sky-100 h-48 overflow-auto">
  …
</div>

scrollbar-gutter-stable reserves space for the scrollbar so content does not shift when it appears — worth knowing for dialogs and dynamic lists.

Layering#

z-index#

UtilityValue
z-0 z-10 z-20 z-30 z-40 z-50Positive steps
z-autoDefault
-z-10Negative
z-[999]Arbitrary

z-index only applies to positioned elements (relative, absolute, fixed, sticky) and to flex/grid children.

Stacking contexts#

A stacking context is a self-contained layer. Children can never escape it, no matter how high their z-index.

A new stacking context is created by:

  • position other than static with a z-index other than auto
  • opacity less than 1 — including opacity-95
  • transform, filter, backdrop-filter, perspective
  • isolate (isolation: isolate)
  • will-change on any of the above properties
  • mix-blend-mode other than normal
HTML
<!-- The child's z-50 cannot beat the sibling's z-10,
     because the parent's opacity-90 traps it. -->
<div class="relative opacity-90">
  <div class="absolute z-50">Trapped</div>
</div>
<div class="relative z-10">Always on top</div>

isolate#

isolate creates a stacking context deliberately, so a component's internal layering cannot leak out or be interfered with.

HTML
<article class="isolate relative rounded-xl">
  <div class="absolute inset-0 -z-10 bg-gradient-to-br from-indigo-500 to-purple-600"></div>
  <div class="p-6 text-white">Content sits above the gradient.</div>
</article>

Without isolate, -z-10 would push the gradient behind the page background rather than behind the card's content.

A z-index scale worth adopting#

Fixed numbers scattered through a codebase drift. Name them:

CSS
@theme {
  --z-dropdown: 10;
  --z-sticky: 20;
  --z-header: 30;
  --z-overlay: 40;
  --z-modal: 50;
  --z-toast: 60;
}
HTML
<div class="z-(--z-modal)">…</div>

Common patterns#

Truncating text#

HTML
<!-- Single line -->
<p class="truncate">A very long single line…</p>

<!-- Fixed number of lines -->
<p class="line-clamp-3">Three lines, then an ellipsis…</p>

Inside a flex item, both need min-w-0 on the item — see Flexbox.

Horizontally scrollable table#

HTML
<div class="overflow-x-auto rounded-lg border border-gray-200">
  <table class="w-full min-w-3xl text-sm">…</table>
</div>

min-w-* on the table forces the wrapper to scroll rather than squashing columns.

Locking body scroll behind a modal#

HTML
<body class="has-[dialog[open]]:overflow-hidden">

Common mistakes#

  • z-index on a static element. Add relative.
  • Fighting stacking contexts with bigger numbers. z-[9999] cannot escape a parent context. Find the ancestor instead.
  • overflow-hidden on a wrapper containing a dropdown. The menu gets clipped; use overflow-visible or portal the menu.
  • overflow-auto on the sticky element's ancestor. Breaks sticky silently.
  • overflow-hidden where overflow-clip is meant. overflow-clip clips without creating a scroll container, so it does not break sticky descendants — often the better choice for purely decorative clipping.