CodingBanana
CodingBanana
CSS Fundamentals

CSS Z-index

8 min read📖 Intermediate
Z-index controls which layer an element sits on when elements overlap. Higher number means closer to you. Lower number means further away. It only works on elements that have a position value set.
.navbar {
  position: fixed;
  z-index: 9999;
}

.badge {
  position: absolute;
  z-index: 10;
}

.movie-card {
  position: relative;
  z-index: 1;
}

Let me ask you something.

Have you ever had two elements overlapping on your page and the wrong one was showing on top? You had a dropdown menu appearing behind a card. Or a badge getting hidden underneath an image. Or a modal popping up but sitting behind the navbar.

That is a z-index problem. And once you understand how it works you will be able to fix these situations instantly instead of scratching your head wondering why things are stacking the wrong way.

What is Z-index

Think of your webpage as a stack of layers. Every element sits on one of these layers. Elements on higher layers appear on top of elements on lower layers.

Z-index controls which layer an element sits on. Higher number means closer to you. Lower number means further away.

Think of it like a stack of cards on a table. If you put card number 3 on top of card number 1 you see card number 3. Z-index works exactly the same way.

How to Use Z-index

Z-index only works on elements that have a position set. So the element needs position: relative, absolute, fixed, or sticky before z-index does anything.

The second card sits on top of the first where they overlap because it has a higher z-index.

Here is what is happening.

Both cards have position: absolute — this is required. Z-index does nothing without a position value set.

card-one has z-index: 1 — it sits on layer one.

card-two has z-index: 2 — it sits on layer two which is above layer one, so it appears on top where the cards overlap.

Now try swapping the z-index values. Give card-one z-index: 2 and card-two z-index: 1. The first card jumps on top. That is z-index in action.

Z-index With Negative Values

You can also use negative z-index values to push an element behind everything else.

The first card is now pushed behind the container itself because of z-index: -1. You will rarely use negative values but it is useful when you need something to sit behind a background element.

The Stacking Context

Here is the part that trips up almost everyone — including experienced developers. Z-index does not always work globally across the whole page. It works within something called a stacking context.

A stacking context is like a group. Elements inside a group compete with each other for z-index order. But the whole group competes as one unit with elements outside it.

A new stacking context is created when an element has a position value and a z-index that is not auto. Or when it has certain other properties like opacity less than 1, transform, or filter.

Let me show you why this matters.

Even though the badge has z-index: 999 it still gets hidden behind group-two. That is because the badge lives inside group-one which has z-index: 1. The whole group competes as one unit. Group-two has z-index: 2 so it wins and covers everything inside group-one — no matter what z-index values the children have.

Here is what is happening.

group-one has z-index: 1 — the whole group including everything inside sits on layer 1.

group-two has z-index: 2 — the whole group sits on layer 2, which is above layer 1.

The badge has z-index: 999 — but it is trapped inside group-one which is on layer 1. It can be on top of other things inside group-one, but it cannot break out of layer 1 to compete with group-two.

This is confusing at first, but once it clicks it explains a lot of z-index mysteries you will encounter in real projects.

💡

If z-index is not working the way you expect, the first thing to check is whether a parent element is creating a stacking context. Look up the parent chain for any element with position plus z-index, opacity, transform, or filter. One of those is almost always the culprit. Removing or adjusting it usually fixes the problem immediately.

Real World Z-index Values

In real projects z-index values tend to follow a pattern. Developers usually pick numbers with gaps between them so they can insert new layers later without renumbering everything.

A common pattern looks like this:

/* Base content */
.movie-card { z-index: 1; }

/* Badges and labels on cards */
.badge { z-index: 10; }

/* Dropdown menus */
.dropdown { z-index: 100; }

/* Modals and overlays */
.modal { z-index: 1000; }

/* Navbar — always on top */
.navbar { z-index: 9999; }

Using big gaps like this means if you ever need to add something between the navbar and the modal you can use z-index: 5000 without touching anything else.

💡

Never use z-index: 9999999 or crazy high numbers. It is a sign that z-index is being used as a band-aid instead of being understood. If you find yourself needing absurdly high z-index values, step back and look at your stacking contexts. The real fix is almost always restructuring the HTML or adjusting which parent creates a stacking context.

Building the Netflix Clone

Our Netflix clone already uses z-index in a few places. Let us make sure everything is layered correctly — the navbar on top of everything, the badges on top of the movie cards, and the hero background behind the content.

Here is what is happening with the z-index layers in the full clone.

The navbar has z-index: 9999 — it sits at the very top of everything. No matter how many sections or overlapping elements are on the page the navbar will always be visible above them all as you scroll.

The hero has z-index: 1 — it sits above the base page background but below the navbar. The background image and gradient are part of this layer.

Each movie card has z-index: 1 — the cards sit in their normal stacking order within the movie sections.

Each badge has z-index: 10 — the badges sit on top of their parent cards. Because they are positioned inside the card which has position: relative, they measure from the card edges. The z-index: 10 makes sure they always appear above the card image.

Everything is layered intentionally now. The page has clear depth and nothing is accidentally hidden behind something else.

In the next lesson I am going to show you opacity — how to make elements transparent, fade things in and out, and create subtle layering effects that make your page feel more polished. Come on in.

Learn about CSS Opacity →

Have anything to say about this lesson?

Your feedback helps improve these tutorials. If something was confusing or missing, let us know.

We don't currently reply to feedback — but if we add that feature in the future, we'll reach out to you.