The CSS position property controls how an element is placed in a document — and it is one of the most misunderstood parts of CSS. Master it, and layout problems like overlapping elements, sticky headers, and floating buttons suddenly become easy.
This guide explains all five values — static, relative, absolute, fixed, and sticky — with clear examples and the rules that decide where an element actually lands.
What Is the CSS position Property?
The position property defines how an element is positioned in the page flow and whether the offset properties (top, right, bottom, left) have any effect. There are five values:
- static — the default; the element follows normal document flow.
- relative — positioned relative to its normal spot.
- absolute — removed from flow and positioned against the nearest positioned ancestor.
- fixed — positioned against the viewport; stays put when scrolling.
- sticky — toggles between relative and fixed based on scroll position.
position: static (the default)
Every element is static by default. It sits in normal flow, and the offset properties have no effect.
.box {
position: static;
top: 50px; /* ignored — has no effect on static elements */
}position: relative
A relative element stays in normal flow, but you can nudge it from its original position using the offset properties. Importantly, the space it originally occupied is preserved.
.box {
position: relative;
top: 20px; /* moves 20px down from where it would normally be */
left: 10px; /* moves 10px to the right */
}The most common use of relative is not to move an element at all, but to create a positioning context for an absolute child (explained next).
position: absolute
An absolute element is removed from normal flow (other elements ignore it) and positioned relative to its nearest positioned ancestor — the closest parent with a position other than static. If none exists, it positions against the page (the initial containing block).
.parent {
position: relative; /* becomes the positioning context */
}
.child {
position: absolute;
top: 0;
right: 0; /* pins the child to the parent's top-right corner */
}This parent-relative / child-absolute pattern is the foundation for badges, dropdowns, tooltips, and overlay close buttons.
position: fixed
A fixed element is positioned against the viewport and does not move when the page scrolls. It is perfect for sticky navigation bars, back-to-top buttons, and cookie banners.
.navbar {
position: fixed;
top: 0;
left: 0;
width: 100%; /* stays at the top while the user scrolls */
}position: sticky
A sticky element behaves like relative until it reaches a scroll threshold you define, then "sticks" like fixed. It is ideal for section headings and table headers that should stay visible while scrolling their section.
.section-title {
position: sticky;
top: 0; /* sticks once it hits the top of the viewport */
}Gotcha: sticky positioning fails silently if a parent has overflow: hidden or overflow: auto, or if you forget to set a threshold like top.
The Offset Properties: top, right, bottom, left
These four properties define where a positioned element sits. They do nothing on static elements, move relative elements from their natural spot, and anchor absolute/fixed/sticky elements to their reference box.
z-index and Stacking Context
When positioned elements overlap, z-index decides which one appears on top — higher values sit above lower ones. It only works on positioned elements (anything other than static).
.modal {
position: fixed;
z-index: 1000; /* sits above normal content */
}relative vs absolute: Quick Comparison
| Behaviour | relative | absolute |
|---|---|---|
| Stays in normal flow | Yes | No (removed) |
| Original space preserved | Yes | No |
| Positioned against | Its own normal position | Nearest positioned ancestor |
| Common use | Create positioning context | Overlays, badges, tooltips |
Common Positioning Problems and Fixes
- Absolute element jumps to the page corner — its parent has no position: relative. Add it to the intended container.
- sticky not working — a parent has overflow: hidden, or you forgot top.
- z-index ignored — the element is still static; give it a position value first.
- Fixed element overlaps content — add padding/margin to the body equal to the fixed element's height.
Frequently Asked Questions
What is the default position value in CSS?
Every element is position: static by default, meaning it follows normal document flow and ignores the offset properties.
What's the difference between absolute and fixed?
Both are removed from flow, but absolute positions against the nearest positioned ancestor and scrolls with the page, while fixed positions against the viewport and stays in place when scrolling.
Why isn't my position: sticky working?
The most common causes are a parent with overflow: hidden/auto, a missing threshold (top, bottom, etc.), or the element being the only child with no room to scroll.
Does z-index work without position?
No. z-index only applies to positioned elements — anything with a position other than static.
Conclusion
CSS positioning comes down to five values and one key rule: absolute children position against the nearest positioned ancestor. Remember that relative creates context, fixed anchors to the viewport, and sticky blends the two — and most layout headaches disappear.
About Muhaymin Bin Mehmood
Front-end Developer skilled in the MERN stack, experienced in web and mobile development. Proficient in React.js, Node.js, and Express.js, with a focus on client interactions, sales support, and high-performance applications.

