CSS Position: Mastering the Document Flow
The `position` property dictates how an element sits within the page layout. Misunderstanding it is the root cause of 90% of CSS layout frustrations.
Default State: Static
Every element defaults to position: static;. In this state, the element adheres to the normal document flow. Properties like top, right, bottom, left, and z-index have absolutely zero effect on a statically positioned element.
Gentle Nudges: Relative
position: relative; keeps the element in the normal document flow but unlocks the ability to use offsets (top, left, etc.) and z-index.
Crucially: When you offset a relative element, it leaves behind a "ghost" space where it originally was. Surrounding elements do not shift to fill the void. It is also the primary way to create a Containing Block for absolute children.
Breaking Free: Absolute
position: absolute; completely removes the element from the document flow. Other elements behave as if the absolute element no longer exists.
It positions itself relative to its closest positioned ancestor (any parent with a position other than static). If it can't find one, it anchors itself to the entire document body.
Viewport Anchors: Fixed & Sticky
- Fixed: Removed from flow, anchored strictly to the browser viewport. Perfect for persistent navbars or "Back to Top" buttons.
- Sticky: A hybrid. It sits in normal flow (like relative) until a scroll threshold is met (e.g.,
top: 0), at which point it "sticks" to the screen like fixed positioning, but only within the bounds of its parent container.
❓ Frequently Asked Questions
Why is my z-index not working?
`z-index` only works on elements that have a position value other than `static` (relative, absolute, fixed, or sticky). Also, be aware of Stacking Contexts: a child element's z-index cannot exceed its parent's stacking context.
Why is my absolute element flying out of its container?
Because you forgot to give the container position: relative;! An absolute element looks up the DOM tree for a "positioned ancestor". If the container is static, the absolute element ignores it and keeps looking until it hits the body.
