The CSS position property
The CSS position property sets how an element is placed. static is the default (normal flow). relative nudges an element from where it would sit. absolute places it against the nearest positioned ancestor. fixed pins it to the viewport. sticky behaves like relative until you scroll past it, then sticks — perfect for headers.
Overview
The position property decides whether an element stays in the normal document flow or gets lifted out and placed somewhere specific. It works hand in hand with the top, right, bottom and left offsets, which only take effect once you move away from the default.
By default everything is static — it simply flows in source order, and the offset properties do nothing. relative keeps the element in flow but lets you shift it visually, and (this is the part people miss) it turns the element into a positioning context for any absolutely-positioned children. absolute pulls an element out of flow entirely and positions it against the nearest ancestor that is itself positioned — which is why a relative parent and an absolute child is such a common pairing.
fixed is like absolute but anchored to the viewport, so it stays in place as the page scrolls — think cookie bars and floating buttons. sticky is the newest and the most quietly useful: it acts relative until the element hits a threshold you set (say top: 0), then it sticks there while the rest of the page scrolls past. No JavaScript required.
Syntax
selector {
position: value;
/* then offset with: */
top: 0;
left: 0;
}
/* e.g. a sticky header */
.header {
position: sticky;
top: 0;
}
Values
The position property accepts the values below. Every property also accepts the CSS-wide keywords inherit, initial, revert and unset.
| Value | Description |
|---|---|
static |
The default. The element sits in normal flow and the offset properties are ignored. |
relative |
Stays in flow but can be nudged with top/left/etc., and becomes the reference for absolute children. |
absolute |
Removed from flow and positioned against the nearest positioned ancestor. |
fixed |
Removed from flow and positioned against the viewport, so it stays put while you scroll. |
sticky |
Acts relative until you scroll past a set threshold, then sticks in place. |
Example
<style>
.frame {
position: relative;
background: #eef2ff;
height: 110px;
border-radius: 10px;
font: 14px system-ui, sans-serif;
}
.pin {
position: absolute;
top: 10px;
right: 10px;
background: #1c7ce9;
color: #fff;
padding: 5px 10px;
border-radius: 999px;
font-weight: 600;
}
</style>
<div class="frame">
<span class="pin">Top right</span>
A relative parent with an absolute badge anchored to its corner.
</div>
Best practices
- Set
position: relativeon a parent before placing anabsolutechild, so the child anchors to that parent and not some distant ancestor. - Prefer
stickyover JavaScript scroll listeners for headers and sidebars — it is smoother, simpler and runs on the compositor. - Use
positionfor overlays and badges, not for page layout. For the overall structure, flex and grid are the right tools. - When you stack positioned elements, control the order deliberately with z-index rather than relying on source order.
Frequently asked questions
What is the difference between absolute and relative positioning?
relative keeps the element in normal flow and offsets it from where it would naturally sit. absolute removes it from flow and positions it against the nearest positioned ancestor.How do I make a sticky header in CSS?
position: sticky and top: 0. It scrolls with the page until it reaches the top of the viewport, then stays pinned there.Why is my absolutely positioned element in the wrong place?
position: relative to the parent you actually want it measured against.What is the difference between fixed and sticky?
fixed is always anchored to the viewport. sticky stays in normal flow and only pins once you scroll past its threshold, then releases again when its container scrolls away.