CSS Z-Index Property

The CSS Z-Index Property is used to control the stacking order of overlapping elements. When multiple elements overlap, z-index helps determine which element appears on top.

By default, elements on a webpage stack according to their order in the HTML document. The natural stacking order follows these rules:

  1. Background and border of the root element (<html>)
  2. Non-positioned elements (normal document flow, e.g., <p>, <div> without position)
  3. Positioned elements (position: relative, absolute, fixed, sticky) with a defined z-index
  4. Elements with a higher z-index value appear above those with a lower z-index value

If two elements have the same z-index, the one that appears later in the HTML document will be placed on top.

The z-index property is only effective when applied to positioned elements (relative, absolute, fixed, sticky). If an element has position: static (default position), z-index will not work.

Syntax

.element {
  position: relative; /* Required for z-index to work */
  z-index: 5; /* Higher values appear on top */
}
CSS

Example

Basic Overlapping with z-index

Let’s create three overlapping boxes and control their stacking order using z-index.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box {
            width: 150px;
            height: 150px;
            position: absolute;
            text-align: center;
            line-height: 150px;
            font-size: 20px;
            font-weight: bold;
            color: white;
        }

        .box1 {
            background: red;
            top: 50px;
            left: 50px;
            z-index: 1;
        }

        .box2 {
            background: blue;
            top: 80px;
            left: 80px;
            z-index: 3;
            /* This box will be on top */
        }

        .box3 {
            background: green;
            top: 110px;
            left: 110px;
            z-index: 2;
        }
    </style>
</head>

<body>
    <div class="box box1">Box 1</div>
    <div class="box box2">Box 2</div>
    <div class="box box3">Box 3</div>
</body>

</html>
HTML

output:

CSS Z-Index Property

Explanation:

  • Box 2 (z-index: 3) is on top because it has the highest z-index value.
  • Box 3 (z-index: 2) is in the middle.
  • Box 1 (z-index: 1) is at the bottom.

You can also use negative values for z-index, which moves elements behind other elements.

Example:

.box {
  width: 150px;
  height: 150px;
  position: absolute;
}

.box1 {
  background: red;
  top: 50px;
  left: 50px;
  z-index: -1; /* Moves behind other elements */
}

.box2 {
  background: blue;
  top: 70px;
  left: 70px;
  z-index: 2;
}
HTML

Here, Box 1 will be behind Box 2 because it has a negative z-index.

If an element is inside a parent with a z-index, it cannot exceed the parent’s stacking order unless the parent has z-index: auto.

Example:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .parent {
            width: 200px;
            height: 200px;
            background: gray;
            position: relative;
            z-index: 2;
        }

        .child {
            width: 100px;
            height: 100px;
            background: orange;
            position: absolute;
            z-index: 3;
        }
    </style>
</head>

<body>
    <div class="parent">
        <div class="child">Child</div>
    </div>
</body>

</html>
HTML

  • Even though .child has z-index: 3, it cannot be placed above elements outside the .parent div because .parent has z-index: 2.
  • The child’s stacking order is limited by its parent.

Issue 1: z-index Not Working?

Solution: Ensure the element has a positioned value (relative, absolute, fixed, sticky).

.element {
  position: relative; /* Required */
  z-index: 5;
}
CSS

Issue 2: z-index Not Respecting the Value?

Solution: Check parent elements for z-index.
If a parent has a lower z-index, its children cannot exceed that stacking level.

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

.child {
  position: absolute;
  z-index: 9999; /* Will still be limited by parent's z-index */
}
CSS

Fix: Increase the parent’s z-index.

.navbar {
  position: relative;
  z-index: 10;
}

.dropdown {
  position: absolute;
  z-index: 20; /* Ensures it appears on top */
}
CSS

.modal {
  position: fixed;
  z-index: 9999; /* Ensures it is above all other elements */
}
CSS

.image {
  position: absolute;
  z-index: 1;
}

.text {
  position: absolute;
  z-index: 2; /* Ensures text appears above image */
}
CSS

Z-index ValueStacking Order
Higher Value (z-index: 100;)Appears in front
Lower Value (z-index: 1;)Appears behind
Negative Value (z-index: -1;)Moves behind elements
Default (z-index: auto;)Follows natural HTML order
  • z-index works only on positioned elements (relative, absolute, fixed, sticky).
  • Higher z-index values appear in front of lower values.
  • Parent elements limit child elements’ z-index.
  • Use z-index for dropdowns, modals, overlapping elements, and layered designs.