The five positions
| position | Leaves flow? | Offset with top/left…? | Use |
|---|---|---|---|
static | No (default) | No | Normal flow |
relative | No (stays in flow) | Yes, nudges visually | Containing block for absolute |
absolute | Yes (removed) | Yes, against nearest positioned ancestor | Tooltips, modals |
fixed | Yes | Yes, against viewport | Fixed header, overlay |
sticky | No until scroll | Sticky when parent scrolls | Sticky headers, TOC |
Relative: the anchor
This text doesn't move. Relative keeps its flow space.
.card { position: relative; top: 6px; left: 12px; } /* visual nudge only */
Absolute: positioned against nearest non-static ancestor
Without position: relative on parent, the badge would pin to viewport.
.parent { position: relative; } /* creates containing block */
.badge { position: absolute; top: 8px; right: 8px; }
Fixed: glued to viewport
Fixed would stay while you scroll. I can't demo that in a box, but here's the code:
.topbar { position: fixed; top: 0; left: 0; right: 0; height: 48px; z-index: 100; }
Sticky: the best of both
Line 1, keep scrolling
Line 2
Line 3
Line 4, header sticks to top
Line 5
Line 6
Line 7
Line 8, header stays until parent ends
.toc { position: sticky; top: 0; } /* sticks when you would scroll past it */
sticky needs a scroll container and won't work if any ancestor has overflow: hidden.z-index & stacking context
z-index only works on positioned elements (relative/absolute/fixed/sticky). Higher number means on top, at least within the same stacking context.
.a { position: absolute; z-index: 1; }
.b { position: absolute; z-index: 2; } /* on top within same parent */
position + z-index, but also opacity < 1, transform, filter. A child with z-index: 9999 can't escape its parent's stacking context. If parent is z-index: 1, that 9999 is only "9999 within 1". Keep z-index flat: e.g., 10, 20, 30 for layers.Use cases
Tooltip
.wrap { position: relative; display: inline-block; }
.tip { position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); }
Modal (uses fixed + inset + margin auto from Module 7)
.overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.4); display: grid; place-items: center; }
.modal { width: 400px; max-width: 90vw; background: #fff; }
Float, just so you recognize it
float: left was the old layout hack before flex/grid. You'll see it in legacy code. It wraps text around images and needs clearfix hacks. Don't use it for layout. Use flex/grid.
- Build a page with a sticky header (
position: sticky; top: 0). - Add a button that shows a modal: overlay (
fixed; inset: 0) + card (margin: autoorplace-items: center). - Give overlay
z-index: 10, modalz-index: 11. Try breaking by wrapping modal inside a low z-index parent and see what happens to stacking context.