📍 CSS Intermediate

Position

⏱ 1 hr3 topicsLive playground
🎯 By the end: You can nudge elements with relative, place them freely with absolute, pin them with fixed or sticky, and understand how positioning contexts work.

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/left have 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 using top, right, bottom, left.
.badge {
  position: relative;
  top: -8px;   /* nudge up 8px */
  left: 10px;  /* nudge right 10px */
}
A key extra power of relative: it becomes the anchor for any absolute children — which is the secret to the next part.
Key points
  • static is the default — normal flow, and top/left are ignored.
  • relative keeps the element's space but lets you nudge it with top/right/bottom/left.
  • A relative element becomes the positioning anchor for absolute children.

2absolute, fixed and sticky

  • absolute — removed from the flow (it takes no space) and placed relative to its nearest positioned ancestor (one with relative/absolute/fixed). Perfect for a badge in the corner of a card: set the card to position: relative and the badge to position: 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).

The classic mistake: setting 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.
A badge with absolute positioning
HTML
CSS
Live preview
What's happening: The card is position:relative, so the absolutely-positioned badge is placed relative to the card's corner (top:8px right:8px). Remove position:relative from .card and the badge jumps to the page corner instead — the classic gotcha.
Key points
  • absolute removes the element from flow and places it relative to its nearest positioned ancestor.
  • fixed pins to the browser window (stays during scroll); sticky scrolls then sticks at a set point.
  • z-index controls stacking order on positioned elements — higher is on top.
  • Gotcha: give the parent position: relative or 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.

Position visualizer — change the dropdown
parent · position: relative
box
Key points
  • static ignores top/left entirely.
  • relative nudges the box from where it would normally sit.
  • absolute removes it from flow and positions it against the parent.

★ Practical: pin and nudge

In any playground:

  1. Build a card and pin a small badge to its top-right with absolute (remember position: relative on the card).
  2. Nudge an element a few pixels with position: relative and top/left.
  3. Make a header position: sticky; top: 0 and scroll to see it stick.
  4. Use z-index to 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.