Skip to main content

CSS Positioning - static, relative, absolute, fixed, sticky

Answer

The position property controls how an element is positioned in the document flow and how it responds to offset properties (top, right, bottom, left).

Position Types Overview

Comparison Table

PropertyIn Flow?Positioned ToResponds to OffsetsScrolls With Page
static✅ YesN/A❌ No✅ Yes
relative✅ YesOriginal position✅ Yes✅ Yes
absolute❌ NoNearest positioned ancestor✅ Yes✅ Yes
fixed❌ NoViewport✅ Yes❌ No
sticky✅ Yes*Container then viewport✅ YesHybrid

position: static (Default)

.static {
position: static; /* Default - no need to declare */
top: 20px; /* ❌ Ignored */
left: 20px; /* ❌ Ignored */
}

position: relative

.relative-box {
position: relative;
top: 20px; /* Moves DOWN 20px from original position */
left: 30px; /* Moves RIGHT 30px from original position */
/* Original space is preserved in document flow */
}

Use cases:

  • Small adjustments without breaking layout
  • Creating positioning context for absolute children

position: absolute

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

.absolute-child {
position: absolute;
top: 0;
right: 0;
/* Positions to top-right of .parent */
}

Key behavior:

  • Removed from document flow (other elements ignore it)
  • Positions relative to nearest ancestor with position other than static
  • If no positioned ancestor, positions to <html>
/* Center absolutely positioned element */
.centered-absolute {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

position: fixed

.fixed-header {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
/* Always at top of viewport, doesn't scroll */
}

.back-to-top {
position: fixed;
bottom: 20px;
right: 20px;
/* Always visible in corner */
}

position: sticky

.sticky-header {
position: sticky;
top: 0;
background: white;
/* Scrolls normally until it reaches top */
/* Then sticks at top */
}

/* Common pattern: Table header */
thead th {
position: sticky;
top: 0;
background: white;
}

Sticky requirements:

  • Must specify at least one offset (top, bottom, left, right)
  • Parent cannot have overflow: hidden
  • Sticks within its container bounds
/* Sticky sidebar */
.sidebar {
position: sticky;
top: 100px; /* Sticks 100px from top */
height: fit-content;
}

Stacking Context (z-index)

/* z-index only works on positioned elements */
.behind {
position: relative;
z-index: 1;
}

.in-front {
position: relative;
z-index: 2;
}

/* Creates new stacking context */
.new-context {
position: relative;
z-index: 0; /* or any value */
/* Children's z-index is scoped to this container */
}

Practical Examples

Overlay/Modal

.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
}

.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 1001;
}
.dropdown {
position: relative;
}

.dropdown-menu {
position: absolute;
top: 100%;
left: 0;
min-width: 200px;
display: none;
}

.dropdown:hover .dropdown-menu {
display: block;
}

Badge on Icon

.icon-wrapper {
position: relative;
display: inline-block;
}

.notification-badge {
position: absolute;
top: -5px;
right: -5px;
background: red;
color: white;
border-radius: 50%;
padding: 2px 6px;
font-size: 12px;
}

Common Mistakes

/* ❌ Forgot positioned parent */
.parent {
/* no position */
}
.child {
position: absolute;
/* Will position to viewport, not parent! */
}

/* ✅ Add position to parent */
.parent {
position: relative;
}

/* ❌ z-index on static element */
.static-element {
z-index: 100; /* Ignored! */
}

/* ✅ Add position first */
.positioned-element {
position: relative;
z-index: 100;
}

Key Points

  • static: Default, ignores offsets
  • relative: In flow, offset from original spot
  • absolute: Out of flow, positions to nearest positioned ancestor
  • fixed: Out of flow, positions to viewport, doesn't scroll
  • sticky: In flow until threshold, then fixed-like behavior
  • z-index only works on positioned elements