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
| Property | In Flow? | Positioned To | Responds to Offsets | Scrolls With Page |
|---|---|---|---|---|
static | ✅ Yes | N/A | ❌ No | ✅ Yes |
relative | ✅ Yes | Original position | ✅ Yes | ✅ Yes |
absolute | ❌ No | Nearest positioned ancestor | ✅ Yes | ✅ Yes |
fixed | ❌ No | Viewport | ✅ Yes | ❌ No |
sticky | ✅ Yes* | Container then viewport | ✅ Yes | Hybrid |
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
positionother thanstatic - 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 Menu
.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 offsetsrelative: In flow, offset from original spotabsolute: Out of flow, positions to nearest positioned ancestorfixed: Out of flow, positions to viewport, doesn't scrollsticky: In flow until threshold, then fixed-like behaviorz-indexonly works on positioned elements