Most of the time you let elements sit in the normal flow. But sometimes you need to place something exactly — a badge on a card, a menu that sticks to the top as you scroll, a button pinned to the corner. That's what the position property is for. It has five values, and they trip up a lot of people, so we'll go slowly.
1static and relative
static— the default. The element sits in the normal flow;top/lefthave no effect. You rarely write it.relative— the element stays in the flow (its original space is kept) but you can nudge it from where it would normally be usingtop,right,bottom,left.
.badge {
position: relative;
top: -8px; /* nudge up 8px */
left: 10px; /* nudge right 10px */
}relative: it becomes the anchor for any absolute children — which is the secret to the next part.staticis the default — normal flow, andtop/leftare ignored.relativekeeps the element's space but lets you nudge it withtop/right/bottom/left.- A
relativeelement becomes the positioning anchor forabsolutechildren.
2absolute, fixed and sticky
absolute— removed from the flow (it takes no space) and placed relative to its nearest positioned ancestor (one withrelative/absolute/fixed). Perfect for a badge in the corner of a card: set the card toposition: relativeand the badge toposition: absolute; top: 8px; right: 8px.fixed— pinned to the browser window. It stays put even as you scroll — used for sticky headers, chat buttons, cookie bars.sticky— a hybrid: the element scrolls normally until it reaches a set point (e.g.top: 0), then sticks there. Great for section headings that pin to the top as you read past them.
Layering with z-index
When positioned elements overlap, z-index decides what's on top — a higher number wins. It only works on positioned elements (not static ones).
absolute on a child but forgetting to set relative on the parent. Without a positioned ancestor, the element jumps to the whole page instead of staying inside its card.absoluteremoves the element from flow and places it relative to its nearest positioned ancestor.fixedpins to the browser window (stays during scroll);stickyscrolls then sticks at a set point.z-indexcontrols stacking order on positioned elements — higher is on top.- Gotcha: give the parent
position: relativeor an absolute child escapes to the whole page.
3Watch position in action
Switch the position value and drag the offsets to see how each one behaves. Watch the key difference: with static the offsets do nothing; with relative the box is nudged from its normal spot; with absolute it's lifted out of the flow and placed against the parent.
staticignorestop/leftentirely.relativenudges the box from where it would normally sit.absoluteremoves it from flow and positions it against the parent.
★ Practical: pin and nudge
In any playground:
- Build a card and pin a small badge to its top-right with
absolute(rememberposition: relativeon the card). - Nudge an element a few pixels with
position: relativeandtop/left. - Make a header
position: sticky; top: 0and scroll to see it stick. - Use
z-indexto put one overlapping box above another.
Ready to test yourself?
Take the short quiz. Score 60% or more to mark this lesson complete.
Start the quiz →💡 Log in to save your progress and earn the certificate.