Boxes and positioning
Positioning
Use relative, absolute, fixed, and sticky positioning while understanding containing blocks and removal from normal flow.
The position property takes an element out of normal flow and places it somewhere else. With the offset properties, top, right, bottom, left, or the logical inset-* versions, it’s how you build badges, sticky headers, and overlays.
The default is static, where offsets do nothing. The other four values each change the rules:
relative: the element keeps its spot in the flow, then moves visually by the offsets.absolute: the element leaves the flow. Other content acts as if it doesn’t exist, and the offsets place it against its containing block.fixed: like absolute, but against the viewport, so it stays put when you scroll.sticky: the element flows normally until you scroll it to the offset, then it sticks inside its scroll container.
Absolute and the containing block
The question with absolute is always: positioned relative to what? The answer is the nearest ancestor with a position other than static. If there is none, it’s the page itself.
Here is a “New” badge in the corner of a card:
.card { position: relative; }
.badge {
position: absolute;
inset-block-start: 0.5rem;
inset-inline-end: 0.5rem;
}
position: relative on the card, with no offsets, changes nothing visually. It just makes the card the badge’s containing block. Remove that line and the badge flies off to the top right corner of the page. That’s the most common positioning bug: forgetting to position the parent.
Sticky needs two things
position: sticky fails silently more than any other value. Two things must be true.
First, it needs an offset on the axis you want to stick. position: sticky alone does nothing. Add top: 0.
Second, it sticks within its nearest scrolling ancestor. If any ancestor has overflow: hidden, auto, or scroll, that ancestor is the scroll container, even with no visible scrollbar. The header then sticks inside that box instead of the page, so it looks like sticky isn’t working. Walk up the tree in DevTools and look for overflow.
One more trap: an ancestor with a transform also becomes a containing block, even for fixed elements. A fixed modal inside a transformed panel scrolls away with it.
Use it for small things
Positioning is for things that sit on top of other content: a badge, a dropdown, a close button. Don’t build page layout with it. Absolute boxes don’t push anything around, so when text grows they overlap whatever is underneath. Flexbox and Grid are the layout tools, and they’re up next.
Try it on the course page. Add a span.badge to the first card with the rule above. Remove position: relative from .card and watch where the badge goes. Then wrap the card in a div with overflow: hidden and make the badge sticky. Each change moves the reference box.
Lesson completed