DevPrep
  • Interview Prep
  • Projects
  • Resources
  • Pricing
  • About Us
Submit Question
DevPrep
  • Pricing
  • About Us
Submit Question
  1. Home
  2. Articles
  3. Frontend Engineering
  4. CSS Position Property — How static, relative, absolute, fixed, and sticky Actually Work
XLinkedInReddit
MediumFrontend Engineering

CSS Position Property — How static, relative, absolute, fixed, and sticky Actually Work

D
DevPrep Team
February 9, 2026·3 min read·0
Table of Contents
  • All 5 Position Values
  • 1. position: static (Default)
  • 2. position: relative
  • 3. position: absolute
  • 4. position: fixed
  • 5. position: sticky
  • Common Gotchas in Production
  • Gotcha 1: Sticky Not Working
  • Gotcha 2: Fixed Inside Transform
  • Gotcha 3: Z-Index Stacking Context
  • Best Practices

Written by Rahul · Frontend Engineer at Google · Updated 2025

CSS positioning is one of those things that seems simple until you actually need to position something. I've been writing CSS for 8+ years and I still occasionally have to think about which position value to use. Here's the definitive guide.

All 5 Position Values

1. position: static (Default)

Every element is static by default. It flows in normal document order. top, right, bottom, left, and z-index have NO effect.

/* This does absolutely nothing */
.element {
  position: static;
  top: 50px; /* Ignored! */
  z-index: 999; /* Ignored! */
}

2. position: relative

The element stays in normal flow but can be offset from its original position. The space it originally occupied is preserved.

.badge {
  position: relative;
  top: -10px;  /* Moves UP 10px from original position */
  left: 5px;   /* Moves RIGHT 5px from original position */
}

/* Common use: creating a positioning context for absolute children */
.card {
  position: relative; /* This is the key! */
}
.card .badge {
  position: absolute;
  top: -8px;
  right: -8px;
}

3. position: absolute

The element is removed from normal flow. It positions relative to its nearest positioned ancestor (an ancestor with position other than static). If none exists, it uses the viewport.

/* Notification badge on an icon */
.icon-wrapper {
  position: relative; /* Creates positioning context */
  display: inline-block;
}

.notification-dot {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 8px;
  height: 8px;
  background: red;
  border-radius: 50%;
}

/* Modal overlay */
.modal-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  /* Or: inset: 0; (shorthand) */
  background: rgba(0, 0, 0, 0.5);
}

4. position: fixed

Like absolute, but positions relative to the viewport. It doesn't move when the page scrolls.

/* Sticky header */
.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  background: white;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

/* Don't forget to add padding to body! */
body {
  padding-top: 64px; /* Height of navbar */
}

/* Back to top button */
.back-to-top {
  position: fixed;
  bottom: 20px;
  right: 20px;
}

/* Cookie banner */
.cookie-banner {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
}

5. position: sticky

A hybrid of relative and fixed. It's relative until a scroll threshold is met, then becomes fixed. You must specify at least one of top, right, bottom, or left.

/* Sticky table headers */
.table thead th {
  position: sticky;
  top: 0;
  background: white;
  z-index: 10;
}

/* Sticky sidebar */
.sidebar {
  position: sticky;
  top: 80px; /* Below fixed navbar */
  height: fit-content;
}

/* Section headers that stick during scroll */
.section-header {
  position: sticky;
  top: 0;
  background: var(--background);
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}

Common Gotchas in Production

Gotcha 1: Sticky Not Working

/* ❌ Sticky won't work if any ancestor has overflow: hidden */
.parent {
  overflow: hidden; /* This kills sticky! */
}
.child {
  position: sticky; /* Won't stick */
  top: 0;
}

/* ❌ Also won't work without a threshold */
.element {
  position: sticky; /* Missing top/bottom/left/right! */
}

/* ✅ Fix: Remove overflow:hidden from ancestors OR restructure HTML */

Gotcha 2: Fixed Inside Transform

/* ❌ Fixed element inside a transformed parent doesn't work as expected */
.parent {
  transform: translateX(0); /* Creates new containing block! */
}
.child {
  position: fixed; /* Now fixed relative to .parent, not viewport! */
  top: 0;
}

/* This also applies to: filter, perspective, will-change, contain */

Gotcha 3: Z-Index Stacking Context

/* positioned elements create stacking contexts */
.modal {
  position: fixed;
  z-index: 9999;
}
.dropdown {
  position: absolute;
  z-index: 99999; /* Won't appear above modal if it's inside a lower stacking context */
}

Best Practices

  1. Use sticky for headers/sidebars — it's cleaner than scroll event listeners
  2. Always set position: relative on parent when using absolute on children
  3. Use inset: 0 shorthand instead of top: 0; right: 0; bottom: 0; left: 0
  4. Add body padding when using fixed headers to prevent content overlap
  5. Avoid fixed positioning on mobile — it behaves poorly with virtual keyboards

Related Articles

MediumFrontend Engineering

System Design #12: Design a Multi-Step Form Wizard

7 min read
MediumFrontend Engineering

Mastering Senior-Level JavaScript Interview Concepts

2 min read
MediumFrontend Engineering

System Design #9: Design a Collaborative Text Editor

9 min read

Comments (0)

Sign in to leave a comment.

No comments yet. Be the first to comment.

Table of Contents

  • All 5 Position Values
  • 1. position: static (Default)
  • 2. position: relative
  • 3. position: absolute
  • 4. position: fixed
  • 5. position: sticky
  • Common Gotchas in Production
  • Gotcha 1: Sticky Not Working
  • Gotcha 2: Fixed Inside Transform
  • Gotcha 3: Z-Index Stacking Context
  • Best Practices

Series

View all Frontend Engineering articles →

Practice

  • JavaScript
  • DSA
  • Machine Coding
  • System Design

Resources

  • Learning Tracks
  • Articles
  • Roadmaps
  • Compare Concepts
  • Glossary
  • Developer Tools
  • All Questions

Company

  • About
  • Pricing

Legal

  • Privacy Policy
  • Terms of Service
DevPrep

© 2026 DevPrep. All rights reserved.