HTML & CSS6 min read

CSS Position Property Explained

Understand CSS positioning — static, relative, absolute, fixed, and sticky. Learn when to use each type with visual examples and practical patterns.

csspositionlayoutfundamentals

CSS Position Property Explained

The position property controls how an element is placed in the document. It's one of the most misunderstood CSS properties — but once you get it, a lot of layouts suddenly make sense.

The Five Position Values

static (Default)

Every element is position: static by default. It flows normally in the document.

.element {
  position: static; /* default — you never need to write this */
}

top, right, bottom, left, and z-index have no effect on static elements.

relative

The element stays in its normal position, but you can nudge it with top/right/bottom/left:

.element {
  position: relative;
  top: 10px;   /* moves down 10px from where it would be */
  left: 20px;  /* moves right 20px from where it would be */
}

Key point: The element's original space in the layout is preserved. Other elements don't move.

Most common use: As a positioning context for absolute children.

absolute

The element is removed from the normal flow and positioned relative to its nearest positioned ancestor (any ancestor with position other than static):

.parent {
  position: relative; /* creates positioning context */
}

.child {
  position: absolute;
  top: 0;
  right: 0; /* child sits in parent's top-right corner */
}

If no positioned ancestor exists, it positions relative to the <body>.

Common uses:

  • Badges/labels on cards
  • Dropdown menus
  • Tooltips
  • Overlay elements

fixed

Like absolute, but positioned relative to the viewport. It stays in place when you scroll:

.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
}

Common uses:

  • Fixed navigation bars
  • Floating action buttons
  • Cookie consent banners
  • Chat widgets

sticky

A hybrid of relative and fixed. The element is relative until it reaches a scroll threshold, then becomes fixed:

.section-header {
  position: sticky;
  top: 0; /* sticks when scrolled to top of viewport */
}

Important: Sticky elements need a scrolling container and a threshold (top, bottom, etc.) to work.

Common uses:

  • Table headers that stay visible while scrolling
  • Section headers in long lists
  • Sidebar that sticks on scroll

Positioning Context

Understanding positioning context is crucial:

  1. absolute elements look for the nearest ancestor with position: relative, absolute, fixed, or sticky
  2. If none is found, they use the document body
  3. relative on a parent creates a positioning context without moving the parent
/* Pattern: parent is relative, child is absolute */
.card {
  position: relative;
}

.card .badge {
  position: absolute;
  top: -8px;
  right: -8px;
}

z-index — Stacking Order

z-index only works on positioned elements (not static):

.dropdown {
  position: absolute;
  z-index: 10; /* above normal content */
}

.modal-overlay {
  position: fixed;
  z-index: 100; /* above dropdown */
}

.modal {
  position: fixed;
  z-index: 101; /* above overlay */
}

Stacking Context

A new stacking context is created by:

  • position: relative/absolute/fixed with z-index set
  • opacity less than 1
  • transform, filter, perspective

Elements are stacked within their own context. A z-index: 9999 inside one context can't beat a z-index: 1 in a higher context.

Common Patterns

Centering with Absolute Position

.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

This centers the element both horizontally and vertically within its positioned parent.

Full-Screen Overlay

.overlay {
  position: fixed;
  inset: 0; /* same as top: 0; right: 0; bottom: 0; left: 0 */
  background: rgba(0, 0, 0, 0.5);
  z-index: 50;
}

Badge on a Card

.card {
  position: relative;
}

.badge {
  position: absolute;
  top: -6px;
  right: -6px;
  background: red;
  color: white;
  border-radius: 50%;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
}

Sticky Table Header

table thead th {
  position: sticky;
  top: 0;
  background: white;
  z-index: 1;
}

Quick Reference

PositionIn Flow?Positioned ByScrolls With
staticYesN/ADocument
relativeYesSelfDocument
absoluteNoNearest positioned ancestorPositioned ancestor
fixedNoViewportNothing (stays put)
stickyYes → NoSelf + scroll thresholdUntil threshold

Key Takeaways

  1. Use relative on parents to create positioning context for absolute children
  2. absolute removes from flow; relative keeps in flow
  3. fixed stays visible during scroll — use for navbars and modals
  4. sticky is the best of both worlds — use for table headers and section titles
  5. z-index only works on positioned elements
  6. Use inset: 0 as shorthand for top: 0; right: 0; bottom: 0; left: 0

🚀 Practice What You Learned

Apply these concepts with hands-on coding challenges: