Quick rule: static (default),
relative (nudges itself), absolute (to
nearest positioned ancestor), fixed (to viewport),
sticky (sticks inside scroll area). Use
top/right/bottom/left or shorthand inset to
offset. z-index controls overlap when positioned.
Static vs Relative
static = default. Offsets are ignored. relative = element keeps its original space, then visually shifts by offsets.
left:30px; top:10px)
.relative-demo{ position: relative; left: 30px; top: 10px; }
Notice how B moved visually but its original space is still reserved, so C does not slide under B.
Absolute (nearest positioned ancestor)
Absolute elements are taken out of flow and positioned relative to the
padding box of the
nearest ancestor that is not position: static
(or an ancestor that creates a containing block via
transform, etc.). If none, they use the initial
containing block (page).
.container{ position: relative; }
.badge{ position: absolute; top:10px; right:10px; }
.pin{ position: absolute; bottom:10px; left:10px; }
.fill{ position: absolute; inset: 0; }
Always set position: relative on the parent you want to
anchor to.
Absolute Centering
Classic trick: place top/left at 50% and pull back by half its own
size using transform: translate(-50%,-50%).
.parent{ position: relative; }
.child{ position: absolute; top:50%; left:50%; transform: translate(-50%, -50%); }
Fixed (relative to viewport)
fixed elements are taken out of flow and pinned to the viewport. They don’t move when you scroll. Note: a transformed ancestor can capture a fixed element as its containing block in browsers.
Scroll the page and the red button will stay put.
.fab{ position: fixed; right: 18px; bottom: 18px; }
Sticky (hybrid of relative + fixed)
sticky starts as relative. When you scroll
past the offset (top/bottom etc.), it
behaves like fixed but only inside its
nearest scrollable ancestor.
Content line 1
Content line 2
Content line 3
Content line 4
Content line 5
Content line 6
Content line 7
Content line 8
Content line 9
Content line 10
Content line 11
Content line 12
.scrollbox{ max-height:260px; overflow:auto; }
.sticky-tab{ position: sticky; top: 0; }
Sticky works within the element’s scroll container. If a parent has
overflow set (auto/scroll/hidden), that parent becomes
the sticky boundary.
z-index & Stacking Contexts
z-index controls overlap
when elements are in the same stacking context. Positioned
elements (non-static) participate; certain properties like
opacity < 1 or transform create a
new stacking context that isolates children.
context
.a{ position:absolute; z-index:1; }
.b{ position:absolute; z-index:2; }
.c{ position:absolute; z-index:3; }
.context .scoped{ transform: translateZ(0); /* new stacking context */ }
-
Higher
z-indexwins only among siblings in the same context. -
New contexts are created by: positioned elements with
z-indexnotauto,transform,opacity<1,filter,will-change, etc.
Offsets: top/right/bottom/left & the inset shorthand
Offsets apply to positioned elements (relative/absolute/fixed/sticky). Use logical shorthands too.
/* physical */
.box{ top: 10px; right: 12px; bottom: 14px; left: 16px; }
/* shorthand */
.box{ inset: 10px 12px 14px 16px; } /* TRBL */
.box{ inset: 0; } /* fill parent */
/* logical (writing‑mode aware) */
.box{ inset-inline-start: 1rem; inset-block-end: 2rem; }
Tip: inset: 0 + position:absolute makes an
element fill its positioned parent (great for overlays).
Cheat‑Sheet (When to use what?)
- relative: nudge an element without affecting layout of others (bad for major layouts).
-
absolute: badges, tooltips, popovers anchored to a
parent you control (
position:relativeon parent). - fixed: sticky headers/footers, floating action buttons, modals pinned to viewport.
- sticky: section headers that stick inside a scrolling container.
- z-index: order layers; remember stacking contexts can isolate children.
Gotchas & Pro Tips
-
For absolute, if it doesn’t align as expected,
ensure the correct ancestor has
position:relativeor a transform to become the containing block. -
fixed may act like absolute inside a transformed
ancestor (common with animated wrappers). Prefer placing fixed
elements near
<body>. -
sticky needs an offset (e.g.,
top:0) and respects the bounds of the nearest scrollable ancestor. - z-index: larger numbers don’t escape stacking contexts. Move the element outside or create a higher context.