Tailwind CSS Handbook v4.3

Position

Static, relative, absolute, fixed and sticky positioning in Tailwind — plus inset utilities, containing blocks, and the patterns that actually come up.

Positioning takes an element out of normal flow, or gives its children a reference point. Two utilities do most of the work: relative on a parent and absolute on a child.

Overview#

Loading preview…

Reference#

UtilityBehaviour
staticDefault. In flow; top/right/bottom/left are ignored
relativeIn flow, but offsettable — and becomes a containing block for absolute children
absoluteOut of flow, positioned against the nearest positioned ancestor
fixedOut of flow, positioned against the viewport
stickyIn flow until it hits a threshold, then sticks

Inset utilities#

UtilityCSS
top-4 right-4 bottom-4 left-4Individual offsets
inset-4All four sides
inset-x-4 / inset-y-4Horizontal / vertical pairs
inset-0Fill the containing block
-top-2Negative offset — pull outside the box
top-1/250% of the containing block
start-4 / end-4Logical, direction-aware

v4.2 Logical insets inset-s-*, inset-e-*, inset-bs-* and inset-be-* map to inset-inline-start, inset-inline-end, inset-block-start and inset-block-end.

The containing block rule#

absolute positions against the nearest ancestor that is not static. If there is none, it positions against the initial containing block — usually the page.

HTML
<!-- ❌ The badge escapes to the page corner -->
<div class="border p-4">
  <span class="absolute top-0 right-0">New</span>
</div>

<!-- ✅ relative gives the badge a reference -->
<div class="relative border p-4">
  <span class="absolute top-0 right-0">New</span>
</div>

Common patterns#

Centring absolutely#

HTML
<div class="relative h-40">
  <div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">Centred</div>
</div>

top-1/2 moves the element's top edge to the midpoint; the negative translate pulls it back by half its own size. If you control the layout, flex items-center justify-center is simpler.

Overlay on an image#

Loading preview…

inset-0 is the idiomatic way to make an overlay fill its parent.

Notification badge#

Loading preview…

Negative insets (-top-1 -right-1) let the badge overhang the button.

HTML
<header class="sticky top-0 z-40 border-b border-gray-200 bg-white/85 backdrop-blur">
  …
</header>

sticky needs three things to work:

  1. A threshold — top-0 alone is not enough; you must specify at least one offset.
  2. A scrolling ancestor that is taller than the sticky element.
  3. No overflow: hidden / auto on an ancestor between the element and the scroll container.

Sticky table header#

HTML
<div class="max-h-72 overflow-y-auto rounded-lg border border-gray-200">
  <table class="w-full text-sm">
    <thead class="sticky top-0 bg-gray-50">…</thead>
    <tbody>…</tbody>
  </table>
</div>

Here the scroll container is the wrapper, and the header sticks inside it.

Fixed action button#

HTML
<button class="fixed right-6 bottom-6 z-50 rounded-full bg-indigo-600 p-4 text-white shadow-lg hover:bg-indigo-500">
  <span class="sr-only">New message</span>
  …
</button>

Sticky vs fixed#

stickyfixed
Occupies space in flowYesNo
Positioned againstNearest scrolling ancestorViewport (usually)
Scrolls awayYes, once its parent has passedNo
Needs an offsetYesYes, in practice
Right forSection headers, table heads, sidebarsModals, toasts, FABs

Advanced example: a sticky sidebar#

HTML
<div class="mx-auto flex max-w-6xl gap-8 px-6">
  <main class="min-w-0 flex-1">…long content…</main>
  <aside class="hidden w-64 shrink-0 lg:block">
    <div class="sticky top-24 space-y-2">
      <p class="text-xs font-semibold tracking-wide text-gray-500 uppercase">On this page</p>
      <nav class="space-y-1 text-sm">…</nav>
    </div>
  </aside>
</div>

The sticky element is the inner div. Making the <aside> itself sticky would not work, because it is only as tall as its content.

Common mistakes#

  • absolute with no positioned ancestor. Add relative to the intended parent.
  • sticky without an offset. sticky alone does nothing; it needs top-0 or similar.
  • overflow-hidden on an ancestor of a sticky element. Silently breaks it.
  • fixed inside a transformed ancestor. It becomes fixed to that ancestor, not the viewport.
  • Stacking issues from missing z-index. Positioned elements create stacking contexts — see Overflow & Layering.
  • Forgetting that absolute shrinks to fit. An absolutely positioned element sizes to its content unless you set a width or opposing insets (inset-x-0).