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