Skip to main content

Last updated: March 13, 2026

How to Fix Z-Index Not Working in CSS

Complete troubleshooting guide for z-index issues. Learn about stacking contexts, position requirements, and common gotchas that break z-index.

Why Is Z-Index So Confusing?

z-index seems simple: higher numbers go in front, right? But it's one of the most frustrating CSS properties because it has hidden rules. The key concept is stacking contexts - invisible boundaries that control how z-index actually works.

This guide covers the most common z-index problems and their solutions, from missing position properties to parent stacking contexts trapping your elements.

Common Causes

Before diving into solutions, here are the typical reasons why z-index doesn't work as expected.

No Position Property Set

z-index only works on positioned elements. If your element has position: static (the default), z-index is ignored.

Parent Creates New Stacking Context

If a parent element creates a stacking context (via position + z-index, opacity, transform, etc.), children can't escape it.

Transform or Other Properties

Properties like transform, filter, perspective, and will-change create new stacking contexts, isolating z-index values.

Competing with Wrong Siblings

Elements only compete with their siblings in the same stacking context. Check if you're comparing the right elements.

Solutions

1

Solution 1: Add Position Property

Problem

Your element has z-index but no position property, so z-index is being ignored.

Before (Not Working)

.element {
  z-index: 999;
  /* position is missing! */
}

After (Fixed)

.element {
  position: relative; /* or absolute, fixed, sticky */
  z-index: 999;
}

Why This Works

z-index only works on positioned elements. Adding position: relative is usually the safest choice as it keeps the element in the normal document flow while enabling z-index. Use absolute or fixed if you need the element removed from the flow.

2

Solution 2: Understand Stacking Contexts

Problem

Your element has z-index: 9999 but still appears behind another element with z-index: 1 because they're in different stacking contexts.

Before (Not Working)

<div class="parent"> <!-- Creates stacking context -->
  <div class="child">z-index: 9999</div>
</div>
<div class="other">z-index: 1</div>

.parent {
  position: relative;
  z-index: 0; /* Creates stacking context */
}
.child {
  position: relative;
  z-index: 9999; /* Trapped inside parent! */
}
.other {
  position: relative;
  z-index: 1; /* Wins because parent has z-index: 0 */
}

After (Fixed)

.parent {
  position: relative;
  z-index: 2; /* Increase parent's z-index */
}
.child {
  position: relative;
  z-index: 9999; /* Now parent is above .other */
}
.other {
  position: relative;
  z-index: 1;
}

Why This Works

When a parent creates a stacking context, children compete only with each other, not with elements outside. The parent's z-index determines the group's position. To fix this, adjust the parent's z-index, not the child's.

3

Solution 3: Remove Transform from Parent

Problem

A parent element has transform, which creates a stacking context and traps children's z-index values.

Before (Not Working)

.parent {
  transform: translateX(0); /* Creates stacking context! */
}
.child {
  position: relative;
  z-index: 999; /* Can't escape parent's context */
}

After (Fixed)

/* Option 1: Remove transform */
.parent {
  /* transform: translateX(0); - removed */
}
.child {
  position: relative;
  z-index: 999; /* Now works! */
}

/* Option 2: Move transform to wrapper */
.wrapper {
  transform: translateX(0);
}
.parent {
  /* No transform here */
}
.child {
  position: relative;
  z-index: 999;
}

Why This Works

Transform creates a stacking context even without z-index. If you need the transform, consider applying it to a wrapper element instead, or adjusting your HTML structure so the stacking context doesn't interfere with your z-index needs.

4

Solution 4: Use Negative Z-Index Correctly

Problem

You're trying to use z-index: -1 to put an element behind content, but it's disappearing behind the page background.

Before (Not Working)

.background {
  position: absolute;
  z-index: -1; /* Disappears! */
}

After (Fixed)

.container {
  position: relative;
  z-index: 0; /* Creates stacking context */
}
.background {
  position: absolute;
  z-index: -1; /* Now behind content but visible */
}
.content {
  position: relative;
  z-index: 1; /* In front of background */
}

Why This Works

Negative z-index places elements behind their stacking context. If you want an element behind content but still visible, create a stacking context on the parent with z-index: 0. This keeps negative z-index elements inside that context, preventing them from going behind the page.

5

Solution 5: Check for Other Stacking Context Properties

Problem

Your z-index isn't working because a parent has opacity, filter, or other properties that create stacking contexts.

Before (Not Working)

.parent {
  opacity: 0.99; /* Creates stacking context! */
}
.child {
  position: relative;
  z-index: 999; /* Trapped inside */
}

After (Fixed)

/* Remove the stacking context property */
.parent {
  /* opacity: 0.99; - removed or moved */
}
.child {
  position: relative;
  z-index: 999; /* Now works freely */
}

/* Or adjust parent's z-index */
.parent {
  opacity: 0.99;
  position: relative;
  z-index: 10; /* Raise entire group */
}

Why This Works

Many CSS properties create stacking contexts: opacity < 1, filter, mix-blend-mode, isolation: isolate, will-change: transform/opacity, and more. Use DevTools to identify if a parent has these properties, then either remove them, move them to a different element, or adjust the parent's z-index.

Quick Troubleshooting Checklist

When z-index isn't working, run through this checklist to identify the issue.

1

Does the element have a position property?

position: relative, absolute, fixed, or sticky is required

2

Is there a parent with a stacking context?

Check parents for position + z-index, opacity, transform, filter, etc.

3

Are you comparing elements in the same stacking context?

Elements only compete with siblings in the same context

4

Is the z-index value high enough?

Compare with siblings' z-index values, not unrelated elements

5

Does DevTools show the z-index is applied?

Check computed styles - if it's not there, position is missing

Properties That Create Stacking Contexts

These CSS properties create new stacking contexts, which can trap z-index values. Watch out for them on parent elements.

position + z-index (not auto)
opacity < 1
transform (any value except none)
filter (any value except none)
perspective (any value except none)
clip-path (any value except none)
mask / mask-image / mask-border
mix-blend-mode (not normal)
isolation: isolate
will-change: opacity, transform
-webkit-overflow-scrolling: touch
contain: layout, paint, or strict

Frequently Asked Questions

Why is my z-index not working?

The most common reason z-index doesn't work is that the element doesn't have a position property set. z-index only works on positioned elements (position: relative, absolute, fixed, or sticky). If your element has position: static (the default), z-index will be ignored.

What is a stacking context in CSS?

A stacking context is a three-dimensional conceptualization of HTML elements along the z-axis. Elements with certain CSS properties (like position + z-index, opacity < 1, transform, or filter) create a new stacking context. Elements inside a stacking context can only compete with their siblings - they can't escape their parent's stacking order.

Can I use negative z-index values?

Yes, negative z-index values are valid and useful. z-index: -1 will place an element behind its parent (if the parent has z-index: 0 or auto). This is commonly used for background decorative elements that should appear behind content but still be part of the DOM for animation purposes.

Does transform affect z-index?

Yes, applying transform creates a new stacking context, even without z-index. This means an element with transform will isolate its children's z-index from the rest of the page. Children can't use z-index to appear above elements outside their transformed parent's stacking context.

How do I debug z-index issues?

Use browser DevTools to inspect the element and check: 1) Does it have a position property? 2) Is there a parent with a stacking context? 3) Are siblings also positioned? You can also use Frontend Hero's CSS Scanner to quickly see all z-index values and stacking contexts on a page.