CSS Positioning
The position property changes how an element sits in the page flow. The default, static, means the element flows normally from top to bottom. Change the value and you can make an element overlap its neighbors, stick to the top of the screen, or hover over other content.
When you set position: relative, the element stays in the flow but you can nudge it with top, left, right, or bottom offsets from its normal spot. position: absolute removes the element from the flow entirely and pins it to its containing block, which is the nearest ancestor with a position other than static. If no ancestor qualifies, that block is the page itself.
That last part causes the most confusion. An absolutely positioned badge with no positioned parent ends up at the corner of the page, not the corner of its card. The classic fix is position: relative on the parent. Fixed pins to the viewport, so the element stays on screen while you scroll. Sticky is a hybrid: it scrolls normally until it reaches a threshold, then it sticks.
The containing block
An absolutely positioned element anchors to its containing block: the nearest ancestor whose position is not static. If none exists, the containing block is the initial page. That is why a badge inside a plain card flies to the corner of the window. Give the card position: relative and it becomes the anchor. Relative keeps the card in the flow, so it moves nothing, and absolute anchors to it.
.card {
position: relative; /* becomes the anchor for absolute children */
}
.badge {
position: absolute;
top: 8px;
right: 8px;
}
Fixed versus sticky
position: fixed pins an element to the viewport, so it stays on screen while the page scrolls. position: sticky is different: the element scrolls normally until it reaches a threshold you set with top, then it locks in place. Fixed is for chat buttons and cookie notices. Sticky is for section headers and nav bars that should stay visible while their section is on screen.
.chat-button {
position: fixed;
bottom: 20px;
right: 20px;
}
.sticky-nav {
position: sticky;
top: 0;
}
Stacking with z-index
Positioned elements paint above static ones, and z-index orders positioned elements among themselves. A higher z-index sits on top. Two rules to remember: z-index does nothing on static elements, and negative z-index can push an element behind its parent background. For overlays, keep the overlay high, like z-index: 100, and the rest of the page out of the way.
.modal {
position: fixed;
z-index: 100; /* only works because position is not static */
}
Syntax
.badge {
position: absolute;
top: 10px;
right: 10px;
}
.parent {
position: relative;
}
absolute Without Relative Parent Flies to Page Corner
An absolute element anchors to nearest positioned ancestor — without position:relative on parent, it flies to page corner.
.card{position:relative} .badge{position:absolute; top:8px; right:8px}
Good to know
- Static is the default; everything flows normally.
- Absolute anchors to the nearest positioned ancestor.
- Without a positioned parent, absolute refers to the page.
- Fixed stays on screen while scrolling; sticky waits for a threshold.