Skip to content

CSS Positioning Mechanism: Precisely Control Element Position on the Page ​

Imagine you're arranging a stage. Most actors enter in sequence according to the script, which is the normal process. But sometimes, you need an actor to stand in a specific position - maybe slightly offset from where they should originally stand, maybe relative to a fixed position on the stage, or they might even need to "float" above the stage. CSS's positioning mechanism is such a system that lets you precisely control element positions on the page.

Understanding Document Flow and Positioning ​

Before learning positioning, we need to understand a fundamental concept: Document Flow.

Document flow is like a flowing river, HTML elements are like boats in the river. By default, all boats line up in sequence, flowing downstream one after another. Block elements occupy an entire row (like large boats), Inline elements squeeze together (like small boats). This natural, orderly arrangement is the "normal document flow".

When we use the position property, it's like installing special devices on certain boats, allowing them to leave this river and move to other places. Some boats only slightly deviate from their original position, some boats completely leave the river.

Static: Default Document Flow Positioning ​

position: static is the default positioning method for all elements. This value means the element is in the normal document flow, following standard layout rules.

css
.normal-element {
  position: static; /* Default value, usually no need to set explicitly */
}

Elements with static positioning have several characteristics:

  • Arranged according to normal document flow
  • top, right, bottom, left position properties have no effect on it
  • z-index is also ineffective

In actual development, we rarely actively set position: static because this is the default value. But sometimes we need to override previously set positioning, then using position: static can return the element to normal document flow.

css
.element {
  position: absolute; /* Previously set to absolute positioning */
}

/* Restore normal flow in a media query */
@media (max-width: 768px) {
  .element {
    position: static; /* Restore normal flow on mobile */
  }
}

Relative: Relative Positioning ​

Relative positioning is like giving an actor a hint: "You still stand according to the script position, but move a little to the left." The element offsets relative to its original position, but importantly, its original space is still reserved.

Core Characteristics of Relative ​

html
<div class="container">
  <div class="box">Box 1</div>
  <div class="box relative-box">Box 2 (relative positioning)</div>
  <div class="box">Box 3</div>
</div>
css
.box {
  width: 200px;
  height: 100px;
  background-color: #e3f2fd;
  margin: 10px;
}

.relative-box {
  position: relative;
  top: 20px; /* Move down 20px relative to original position */
  left: 30px; /* Move right 30px relative to original position */
  background-color: #ffeb3b;
}

In this example, Box 2 will move down 20px and right 30px, but its original position (between Box 1 and Box 3) is still reserved. Box 3 won't move up to fill the space.

This is like an actor on stage who slightly moved position, but their original "standing position" is still there, other actors won't occupy this position.

Meaning of Position Properties ​

For relative positioning, the meaning of position properties is relative to the element's original position:

css
.element {
  position: relative;
  top: 10px; /* Move down 10px relative to original position */
  right: 20px; /* Move left 20px relative to original position */
  bottom: 15px; /* Move up 15px relative to original position */
  left: 25px; /* Move right 25px relative to original position */
}

Note there's an easily confused point here: top: 10px is not "10px from the top", but "move down 10px from original position". Similarly, right: 20px is "move left 20px from original position".

If you set opposite positions simultaneously (like setting both top and bottom), usually top will take effect, bottom will be ignored. In the horizontal direction, left has higher priority than right.

Practical Applications of Relative ​

1. Fine-tune element position

Sometimes the layout is basically complete, but an element needs to be adjusted by a few pixels, using relative positioning is the simplest method:

css
.icon {
  position: relative;
  top: 2px; /* Let the icon move down a bit to align with text */
}

2. Serving as reference for absolute positioning

This is the most common use of relative positioning. When we want an absolutely positioned element to position relative to a specific parent element, we need to set position: relative on the parent element:

css
.card {
  position: relative; /* Become positioning reference for child elements */
  padding: 20px;
}

.badge {
  position: absolute; /* Position relative to .card */
  top: 10px;
  right: 10px;
}

In this scenario, we set position: relative on the parent element, but don't set any position properties (don't set top, right, etc.), so the parent element itself won't move, but can serve as positioning reference for child elements.

3. Set stacking order

Relatively positioned elements can use z-index, which is very useful when you need to adjust element stacking order:

css
.overlay-trigger {
  position: relative;
  z-index: 10; /* Ensure this element is above other elements */
}

Absolute: Absolute Positioning ​

Absolute positioning is like putting flying devices on actors, making them completely leave the stage's normal process and be able to float to any position on the stage.

Core Characteristics of Absolute ​

When an element is set to position: absolute, the following happens:

  1. Completely removed from document flow: The element no longer occupies its original space, elements behind will move up to fill
  2. Positioned relative to positioned ancestor element: The element will be positioned relative to the nearest positioned (position is not static) ancestor element
  3. If there's no positioned ancestor: The element will be positioned relative to the initial containing block (usually the <html> element)
html
<div class="container">
  <div class="box">Box 1</div>
  <div class="box absolute-box">Box 2 (absolute positioning)</div>
  <div class="box">Box 3</div>
</div>
css
.box {
  width: 200px;
  height: 100px;
  background-color: #e3f2fd;
  margin: 10px;
}

.absolute-box {
  position: absolute;
  top: 50px;
  left: 100px;
  background-color: #f44336;
  color: white;
}

In this example, Box 2 will completely leave document flow, Box 3 will move up to Box 2's original position. Box 2 will be positioned relative to the nearest positioned ancestor element (if .container has no positioning set, it will be relative to <body> or <html>), positioned 50px from top and 100px from left.

Positioning Context Search Rules ​

"Positioning context" is the key concept for understanding absolute positioning. Absolutely positioned elements will search upward for the nearest positioned ancestor element as reference.

Search rules are:

  1. Start from parent element, search upward
  2. If parent element's position is relative, absolute, fixed or sticky, stop searching, use this element as reference
  3. If parent element's position is static (or not set), continue searching upward
  4. If search reaches <html> and still hasn't found, use initial containing block as reference

Let's look at an actual example:

html
<div class="grandparent">
  <div class="parent">
    <div class="child">Who am I positioned relative to?</div>
  </div>
</div>

Scenario 1: Parent element has positioning

css
.parent {
  position: relative; /* Has positioning */
  background-color: #e3f2fd;
  padding: 40px;
}

.child {
  position: absolute;
  top: 10px;
  left: 10px;
  background-color: #ff9800;
}

.child will be positioned relative to .parent, 10px from .parent's top and left edges.

Scenario 2: Parent element has no positioning, grandparent element has positioning

css
.grandparent {
  position: relative; /* Grandparent element has positioning */
  background-color: #f5f5f5;
  padding: 50px;
}

.parent {
  /* No positioning */
  background-color: #e3f2fd;
  padding: 40px;
}

.child {
  position: absolute;
  top: 10px;
  left: 10px;
}

Since .parent has no positioning, .child will search upward, find .grandparent, and position relative to it.

Scenario 3: None have positioning

css
/* All ancestor elements have no positioning set */
.child {
  position: absolute;
  top: 10px;
  left: 10px;
}

.child will be positioned relative to the <html> element, 10px from the browser window's top and left edges.

Absolute Positioning Dimension Behavior ​

Absolutely positioned elements have some special dimension behaviors:

1. Default width determined by content

Unlike block elements which default to filling the parent container, absolutely positioned elements' default width is determined by content:

css
.absolute-element {
  position: absolute;
  /* Width determined by content, won't automatically fill */
  background-color: #4caf50;
  padding: 10px;
}

2. Can control dimensions through four position properties

This is a very useful technique:

css
.fullsize-overlay {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  /* No need to set width and height, element will automatically fill positioning context */
  background-color: rgba(0, 0, 0, 0.5);
}

By setting all four position properties to 0 simultaneously, the element will automatically fill the entire positioning context.

Practical Applications of Absolute Positioning ​

1. Modal/Popup

html
<div class="modal">
  <div class="modal-overlay"></div>
  <div class="modal-content">
    <h2>Modal Title</h2>
    <p>This is modal content...</p>
    <button class="close-btn">×</button>
  </div>
</div>
css
.modal {
  position: fixed; /* Parent container fixed positioning, convenient for child element positioning */
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1000;
}

.modal-overlay {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.5);
}

.modal-content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%); /* Centering technique */
  background-color: white;
  padding: 30px;
  border-radius: 8px;
  max-width: 500px;
}

.close-btn {
  position: absolute;
  top: 15px;
  right: 15px;
  background: none;
  border: none;
  font-size: 24px;
  cursor: pointer;
}

2. Corner Badge

html
<div class="notification-icon">
  <img src="bell.svg" alt="Notifications" />
  <span class="badge">5</span>
</div>
css
.notification-icon {
  position: relative; /* Become positioning reference */
  display: inline-block;
}

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

3. Dropdown Menu

html
<div class="dropdown">
  <button class="dropdown-trigger">Dropdown</button>
  <div class="dropdown-menu">
    <a href="#">Option 1</a>
    <a href="#">Option 2</a>
    <a href="#">Option 3</a>
  </div>
</div>
css
.dropdown {
  position: relative;
  display: inline-block;
}

.dropdown-menu {
  position: absolute;
  top: 100%; /* Right below trigger button */
  left: 0;
  min-width: 200px;
  background-color: white;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  border-radius: 4px;
  display: none; /* Hidden by default */
  z-index: 100;
}

.dropdown:hover .dropdown-menu {
  display: block; /* Show on hover */
}

.dropdown-menu a {
  display: block;
  padding: 10px 15px;
  color: #333;
  text-decoration: none;
}

.dropdown-menu a:hover {
  background-color: #f5f5f5;
}

4. Tooltip

html
<span class="tooltip-wrapper">
  Hover here
  <span class="tooltip">This is tooltip text</span>
</span>
css
.tooltip-wrapper {
  position: relative;
  cursor: help;
  border-bottom: 1px dotted #999;
}

.tooltip {
  position: absolute;
  bottom: 100%; /* Above the trigger element */
  left: 50%;
  transform: translateX(-50%);
  background-color: #333;
  color: white;
  padding: 8px 12px;
  border-radius: 4px;
  font-size: 14px;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s, visibility 0.3s;
}

.tooltip::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: #333; /* Small triangle */
}

.tooltip-wrapper:hover .tooltip {
  opacity: 1;
  visibility: visible;
}

Fixed: Fixed Positioning ​

Fixed positioning is like pinning an element to a certain position on the browser window, no matter how the page scrolls, the element remains at a fixed position in the viewport.

Core Characteristics of Fixed ​

css
.fixed-header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  background-color: #1976d2;
  color: white;
  padding: 15px;
  z-index: 1000;
}

Fixed positioned elements:

  • Completely removed from document flow
  • Positioned relative to browser viewport
  • Not affected by page scrolling
  • Always stays at fixed position in viewport

Difference Between Fixed and Absolute ​

Although both are removed from document flow, the positioning reference is different:

  • Absolute: Relative to nearest positioned ancestor element
  • Fixed: Always relative to browser viewport
html
<div class="scrollable-container" style="height: 2000px;">
  <div class="absolute-element">Absolute positioning</div>
  <div class="fixed-element">Fixed positioning</div>
</div>
css
.scrollable-container {
  position: relative;
}

.absolute-element {
  position: absolute;
  top: 100px;
  left: 50px;
  /* Will scroll with page */
}

.fixed-element {
  position: fixed;
  top: 100px;
  right: 50px;
  /* Won't scroll with page, always at fixed position in viewport */
}

Practical Applications of Fixed ​

1. Fixed Navigation Bar

css
.navbar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  background-color: white;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  z-index: 1000;
  /* Mobile may need to set padding-top for body to avoid content being covered */
}

body {
  padding-top: 60px; /* Navbar height */
}

2. Back to Top Button

html
<button class="back-to-top" id="backToTop">↑</button>
css
.back-to-top {
  position: fixed;
  bottom: 30px;
  right: 30px;
  width: 50px;
  height: 50px;
  background-color: #2196f3;
  color: white;
  border: none;
  border-radius: 50%;
  font-size: 24px;
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s, visibility 0.3s;
  z-index: 999;
}

.back-to-top.visible {
  opacity: 1;
  visibility: visible;
}
javascript
const backToTop = document.getElementById("backToTop");

window.addEventListener("scroll", () => {
  if (window.scrollY > 300) {
    backToTop.classList.add("visible");
  } else {
    backToTop.classList.remove("visible");
  }
});

backToTop.addEventListener("click", () => {
  window.scrollTo({ top: 0, behavior: "smooth" });
});

3. Sidebar Toolbar

css
.sidebar-tools {
  position: fixed;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  background-color: white;
  padding: 10px;
  box-shadow: -2px 0 10px rgba(0, 0, 0, 0.1);
  border-radius: 8px 0 0 8px;
}

.tool-btn {
  display: block;
  width: 50px;
  height: 50px;
  margin: 10px 0;
  border: none;
  background-color: #f5f5f5;
  cursor: pointer;
  border-radius: 4px;
}

4. Fixed Layout (Admin Backend)

html
<div class="admin-layout">
  <header class="admin-header">Top Navigation</header>
  <aside class="admin-sidebar">Sidebar</aside>
  <main class="admin-content">Main content area</main>
</div>
css
.admin-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 60px;
  background-color: #1976d2;
  z-index: 1000;
}

.admin-sidebar {
  position: fixed;
  top: 60px;
  left: 0;
  bottom: 0;
  width: 250px;
  background-color: #263238;
  overflow-y: auto;
  z-index: 999;
}

.admin-content {
  margin-top: 60px;
  margin-left: 250px;
  padding: 30px;
  min-height: calc(100vh - 60px);
}

Sticky: Sticky Positioning ​

Sticky positioning is a hybrid of relative and fixed positioning. The element behaves as relative positioning before reaching a certain threshold, and becomes fixed positioning after reaching the threshold.

How Sticky Works ​

Imagine a sticky note: when you flip through a book, the sticky note moves with the page (relative positioning), but when it reaches the top of the book, it "sticks" there (fixed positioning), until you flip past this page.

css
.sticky-header {
  position: sticky;
  top: 0; /* Sticky threshold: start fixing when 0px from top */
  background-color: white;
  padding: 15px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  z-index: 10;
}

Understanding Sticky Positioning Reference: Scrolling Ancestor ​

This is the most crucial concept for understanding sticky: sticky elements position relative to their nearest "scrolling ancestor".

What is a scrolling ancestor?

A scrolling ancestor is the first ancestor element from the sticky element upward that meets the following conditions:

  • Has overflow: auto, overflow: scroll, overflow: hidden set (any value other than visible)
  • And this element actually produces scrolling (has scrollbar or content overflow)

If no such ancestor is found, the sticky element positions relative to the viewport.

Sticky Trigger Conditions ​

Condition 1: Must set threshold

css
.sticky-element {
  position: sticky;
  top: 20px; /* Must set top/right/bottom/left */
}

Condition 2: Must have scrolling space

Scenario A: Directly in scrolling container (✅ Recommended)

html
<div class="scrollable-container">
  <div class="sticky-item">I will stick</div>
  <div class="content">Very long content...</div>
</div>
css
.scrollable-container {
  height: 400px;
  overflow-y: auto; /* This is the scrolling container */
}

.sticky-item {
  position: sticky;
  top: 0; /* Position relative to .scrollable-container */
}

✅ Works normally: .scrollable-container is the sticky element's "scrolling ancestor".

Scenario B: Intermediate overflow wrapper (❌ Common trap)

html
<div class="scrollable-container">
  <div class="wrapper">
    <div class="sticky-item">I won't stick properly!</div>
  </div>
  <div class="content">Very long content...</div>
</div>
css
.scrollable-container {
  height: 400px;
  overflow-y: auto; /* Outer scrolling container */
}

.wrapper {
  overflow: hidden; /* ❌ Problem here! */
}

.sticky-item {
  position: sticky;
  top: 0;
}

Why does it "fail"?

  1. Browser searches upward from .sticky-item for "scrolling ancestor"
  2. First finds .wrapper, it has overflow: hidden
  3. Browser considers .wrapper as scrolling ancestor
  4. But .wrapper itself doesn't scroll (height determined by content)
  5. No scrolling, sticky won't trigger

Actually sticky didn't fail, it just positioned relative to the wrong container.

Scenario C: Intermediate normal wrapper (✅ Correct)

html
<div class="scrollable-container">
  <div class="wrapper">
    <div class="sticky-item">I will stick</div>
  </div>
  <div class="content">Very long content...</div>
</div>
css
.scrollable-container {
  height: 400px;
  overflow-y: auto;
}

.wrapper {
  /* Don't set overflow, or set to visible */
  padding: 20px;
}

.sticky-item {
  position: sticky;
  top: 0;
}

✅ Works normally: Browser skips .wrapper, finds .scrollable-container.

Condition 3: Sticky element only sticks within its containing block range

html
<section class="section">
  <h2 class="sticky-title">Section 1 Title</h2>
  <p>Section 1 content...</p>
</section>
<section class="section">
  <h2 class="sticky-title">Section 2 Title</h2>
  <p>Section 2 content...</p>
</section>
css
.sticky-title {
  position: sticky;
  top: 0;
  background-color: #f5f5f5;
  /* Only sticks within respective .section range */
}

When scrolling to section 2, section 1's title will be pushed out of the viewport, section 2's title starts to stick.

Sticky Debugging Techniques ​

When sticky doesn't work, troubleshoot following these steps:

Step 1: Check threshold

css
/* ❌ No threshold */
.sticky {
  position: sticky;
}

/* ✅ Has threshold */
.sticky {
  position: sticky;
  top: 0;
}

Step 2: Check scrolling ancestor (Most important!)

Use browser developer tools:

  1. Select sticky element
  2. Check each ancestor element's overflow value upward
  3. Find the first element with overflow not visible
  4. Confirm if this element can actually scroll
  5. If this element is not your expected scrolling container, remove its overflow

Step 3: Use minimum test

html
<!DOCTYPE html>
<html>
  <head>
    <style>
      body {
        height: 2000px;
      }
      .sticky {
        position: sticky;
        top: 0;
        background: yellow;
        padding: 10px;
      }
    </style>
  </head>
  <body>
    <div class="sticky">I should stick</div>
    <p>Scroll down...</p>
  </body>
</html>

If this simplest example works, gradually add your actual structure to find the problem.

Practical Applications of Sticky ​

1. Fixed Table Headers

html
<table class="data-table">
  <thead>
    <tr class="sticky-header">
      <th>Name</th>
      <th>Age</th>
      <th>City</th>
    </tr>
  </thead>
  <tbody>
    <!-- 100 rows of data -->
  </tbody>
</table>
css
.data-table {
  width: 100%;
  border-collapse: collapse;
}

.sticky-header {
  position: sticky;
  top: 0;
  background-color: #1976d2;
  color: white;
  z-index: 10;
}

.sticky-header th {
  padding: 15px;
  text-align: left;
}

2. Section Titles

css
.chapter-title {
  position: sticky;
  top: 0;
  background-color: #f5f5f5;
  padding: 15px;
  margin: 0 -15px; /* Extend to container edges */
  border-bottom: 2px solid #e0e0e0;
  z-index: 5;
}

3. Sidebar Navigation

html
<div class="content-wrapper">
  <aside class="sidebar">
    <nav class="sticky-nav">
      <a href="#section1">Section 1</a>
      <a href="#section2">Section 2</a>
      <a href="#section3">Section 3</a>
    </nav>
  </aside>
  <main class="main-content">
    <!-- Content -->
  </main>
</div>
css
.content-wrapper {
  display: flex;
  gap: 30px;
}

.sidebar {
  flex: 0 0 250px;
}

.sticky-nav {
  position: sticky;
  top: 20px; /* Start fixing when 20px from top */
}

.main-content {
  flex: 1;
}

Common Reasons Why Sticky Doesn't Work ​

Problem 1: No threshold set

css
/* ❌ Won't work */
.element {
  position: sticky;
  /* Missing top/right/bottom/left */
}

/* ✅ Correct */
.element {
  position: sticky;
  top: 0;
}

Problem 2: Parent container height not enough

css
/* ❌ Sticky element cannot scroll */
.parent {
  height: 200px; /* Height too small */
}

.sticky-child {
  height: 150px;
  position: sticky;
  top: 0;
}

If sticky element height is close to parent container height, there's no scrolling space, sticky won't trigger.

Problem 3: Parent container has overflow set

css
/* ❌ Sticky fails */
.parent {
  overflow: hidden;
}

/* ✅ Remove overflow or set on ancestor element */
.grandparent {
  overflow: hidden;
}

.parent {
  /* Don't set overflow */
}

Z-Index and Stacking Context ​

When multiple positioned elements overlap, who's on top and who's on bottom? This is the problem z-index solves.

Understanding the Z-Axis ​

We usually see webpages as two-dimensional (X-axis and Y-axis), but actually there's a third dimension: the Z-axis, which is "depth". The Z-axis is perpendicular to the screen, pointing towards you.

z-index controls the element's position on the Z-axis, larger values are closer to you (upper layer), smaller values are farther from you (lower layer).

css
.layer-1 {
  position: relative;
  z-index: 1;
}

.layer-2 {
  position: relative;
  z-index: 2; /* Will be above layer-1 */
}

.layer-3 {
  position: relative;
  z-index: 3; /* Will be above layer-2 */
}

Basic Z-Index Rules ​

Rule 1: Only effective on positioned elements

z-index only takes effect on elements where position is not static:

css
/* ❌ z-index ineffective */
.element {
  z-index: 100;
}

/* ✅ z-index effective */
.element {
  position: relative; /* Or absolute/fixed/sticky */
  z-index: 100;
}

Rule 2: Value can be negative

css
.background-layer {
  position: relative;
  z-index: -1; /* Below other content */
}

Rule 3: When values are the same, later ones are on top

css
/* HTML: <div class="box-1"></div><div class="box-2"></div> */

.box-1 {
  position: relative;
  z-index: 1;
}

.box-2 {
  position: relative;
  z-index: 1; /* Same value, but box-2 is later in HTML, so on top */
}

Stacking Context ​

Stacking Context is the most important and easily confused concept for understanding z-index.

Imagine folders stacked on a desk. Each folder is a stacking context, the up-down relationship between folders is determined. But files inside a folder can only compare up-down relationship within this folder, cannot compare across folders.

Ways to Create Stacking Context ​

The following situations create new stacking context:

css
/* 1. Root element html (naturally a BFC) */

/* 2. float not none */
.element {
  float: left; /* Or right */
}

/* 3. position is absolute or fixed */
.element {
  position: absolute; /* Or fixed */
}

/* 4. display is inline-block, table-cell, table-caption */
.element {
  display: inline-block;
}

/* 5. Direct children of display flex or inline-flex (if they themselves are not flex containers) */

/* 6. Direct children of display grid or inline-grid (if they themselves are not grid containers) */

/* 7. overflow not visible and clip */
.element {
  overflow: hidden; /* Or auto, scroll */
}

/* 8. display: flow-root (specifically for creating BFC) */
.element {
  display: flow-root;
}

/* 9. contain value is layout, content or paint */
.element {
  contain: layout;
}

/* 10. column-count or column-width not auto */
.element {
  column-count: 2;
}

Among these, display: flow-root is specifically designed for creating BFC, with no other side effects.

Impact of Stacking Context ​

Once an element creates a stacking context, its children's z-index is only effective within this context, cannot compare across contexts.

html
<div class="parent-1">
  <div class="child-1">Child 1 (z-index: 9999)</div>
</div>
<div class="parent-2">
  <div class="child-2">Child 2 (z-index: 1)</div>
</div>
css
.parent-1 {
  position: relative;
  z-index: 1; /* Creates stacking context */
}

.child-1 {
  position: relative;
  z-index: 9999; /* Only effective within parent-1's stacking context */
}

.parent-2 {
  position: relative;
  z-index: 2; /* Creates stacking context, z-index larger than parent-1 */
}

.child-2 {
  position: relative;
  z-index: 1;
}

Although child-1's z-index is 9999, because its parent element parent-1's z-index is 1, and parent-2's z-index is 2, so parent-2 (and its child element child-2) will be above parent-1 (and its child element child-1).

This is like two folders, A folder is on bottom, B folder is on top. Even if there's a paper in A folder that says "I want to be on top", it can't get out of A folder, so still under B folder.

Practical Applications of Z-Index ​

1. Navigation bar above content

css
.navbar {
  position: fixed;
  top: 0;
  z-index: 1000; /* Ensure above other content */
}

.content {
  position: relative;
  z-index: 1;
}

2. Modal hierarchy

css
.modal-overlay {
  position: fixed;
  z-index: 9998; /* Overlay layer */
}

.modal-content {
  position: relative;
  z-index: 9999; /* Content above overlay */
}

3. Dropdown menu above other content

css
.dropdown {
  position: relative;
}

.dropdown-menu {
  position: absolute;
  z-index: 100; /* Ensure above other content */
}

Common Z-Index Problems ​

Problem 1: Set very large z-index but doesn't work

Reason might be parent element created stacking context:

css
/* Problem */
.parent {
  position: relative;
  z-index: 1; /* Created stacking context */
}

.child {
  position: absolute;
  z-index: 99999; /* Only effective within parent's context */
}

/* Solution: Adjust parent element's z-index */
.parent {
  position: relative;
  z-index: 100; /* Raise parent element's z-index */
}

Problem 2: z-index ineffective

Check if element has positioning:

css
/* ❌ Ineffective */
.element {
  z-index: 100;
}

/* ✅ Effective */
.element {
  position: relative;
  z-index: 100;
}

Practical Positioning Techniques ​

1. Horizontal and Vertical Centering ​

Use absolute positioning to achieve perfect centering:

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

Why does this achieve centering? Because top: 50% and left: 50% place the element's top-left corner at the container center, then transform: translate(-50%, -50%) moves the element leftward and upward by 50% of its own width and height, thus achieving perfect centering.

2. Full Screen Overlay ​

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

3. Responsive Positioning ​

Change positioning method on small screens:

css
.sidebar {
  position: fixed;
  top: 0;
  right: 0;
  width: 300px;
  height: 100%;
}

@media (max-width: 768px) {
  .sidebar {
    position: static; /* Restore normal flow on mobile */
    width: 100%;
    height: auto;
  }
}

Summary ​

CSS positioning is a powerful tool for precisely controlling element positions:

Five Positioning Methods:

  • Static: Default value, normal document flow
  • Relative: Offset relative to original position, preserves original space, commonly serves as positioning reference
  • Absolute: Removed from document flow, positioned relative to positioned ancestor, used for overlays, badges
  • Fixed: Positioned relative to viewport, unaffected by scrolling, used for fixed navigation, toolbars
  • Sticky: Hybrid of relative and fixed, used for sticky headers, sidebars

Z-Index Key Points:

  • Only effective on positioned elements
  • Understand the concept of stacking context
  • Children's z-index only effective within parent context

Best Practices:

  • Relative usually doesn't set position properties, only serves as positioning reference
  • Absolute elements need clear positioning context
  • Fixed elements should be careful not to cover content
  • Sticky should check if trigger conditions are met
  • Reasonably plan z-index hierarchy, avoid chaos

Positioning is a very practical technique in CSS layout, mastering positioning can achieve many effects that are difficult with traditional layout. But also be careful not to overuse positioning, because positioned elements are removed from document flow, which may bring complexity to layout. In actual development, prioritize using modern layout methods like Flexbox and Grid, only use positioning when necessary.