CSS z-index
Tags: beginners, css, zindex
Published: 2019-11-08 20:51:14

---
title: CSS z-index
published: true
description: A beginners guide to the CSS z-index
tags: beginners,css,z-index
series: FrontEnd Development Zero to Hero
---

We concluded the last post on [CSS Positioning](https://dev.to/ziizium/css-positioning-34d8) with two questions which are:

1. What is the _stacking context_?
2. What is the `z-index`?

The second question is the main theme of this post, but answering the first question will be of great help. Let's begin.

From [MDN]( https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context):

> The stacking context is a _three-dimensional_ conceptualization of HTML elements along __imaginary__ z-axis __relative to the user__, who is __assumed to be facing the `viewport` or the webpage__. HTML elements occupy this space in priority order based on element attributes.

This is telling us that the _stacking context_  has do with how we (the users) perceive HTML elements on a web page. The image below sum this up nicely.

<figure>
![z-index in CSS](https://thepracticaldev.s3.amazonaws.com/i/fdsib5gr8hesr53il4kr.jpg)
<figcaption>&copy; <a href="https://www.1keydata.com/css-tutorial/z-index.php">1keydata</a></figcaption>
</figure>

From the image above, you might ask three questions:
1. How do we stack page elements?
2. Which page element can be stacked?
3. How can we make a page element appear closer to the user?

Let's answer these questions one after the other.

First, we can stack page elements using the CSS `z-index` property. This property specifies the stack order of an element i.e which page element appear over another.

Mind you, __only positioned element can be stacked__. When we say _positioned element_ we mean element that have one of the following `position` value set in their CSS rule:

* `relative`
* `absolute`
* `fixed`

The `z-index` value can determine which positioned element appear closer to the user and the element with a larger `z-index` value will appear on top i.e closer to the user. The `z-index` can accept the following values:

* number  &#x2014; can be negative, or positive and it specifies the order the element appears in.
* `auto` &#x2014; sets the `z-index` value to that of its parent element.
* `inherit` &#x2014;  inherits the `z-index` value from the parent element.
* `initial` &#x2014;  sets the `z-index` value to the default value. 

Before we proceed we should know the _Default Stacking order_ which is the default order the browser stacks elements in, when no `z-index` is applied:

* Root element i.e the `html` element
* Non-positioned elements in the order they are defined
* Positioned elements in the order they are defined

Now, let's write some code.

_Save the following HTML and CSS with the `.html` and `.css` extension._

```html
<div class="parent">
  <div class="child"></div>
  <div class="child-two"></div>
  <div class="child-three"></div>
</div>
```
```css
.parent {
  width: 500px;
  height: 400px;
  margin: 2em auto;
  background-color: #dddddd;
}

.child {
  width: 150px;
  height: 100px;
  background-color: #1560bd;
}

.child-two {
  width: 150px;
  height: 100px;
  background-color: red;
}

.child-three {
  width: 150px;
  height: 100px;
  background-color: magenta;
}
```

Load the HTML file in your browser. If you make use of "Inspect Element" on any of the boxes and view its  _Box Model_ in the _Developer Tools_ you should get an output similar to the image below (take note of the highlighted part)

![Red blue and magenta colored boxes shown in Firefox 70 developer tools](https://thepracticaldev.s3.amazonaws.com/i/fdvzxinfmuppgkn3osv1.jpg)

From the image above it's evident that the box still has the default `position` i.e `static` and the `z-index` value is `auto`. We need to move the box around so that we can see the effect of the `z-index` when it's applied.

Add the following code to `.child`:

```css
.child {
  /* All properties remain the same */

  position: relative; /* this is necessary for the offset properties to work */
  top: 20px; 	      /* this will move the box down a little bit */
  left: 45px;	      /* this will move the box to the right by 45px */
}
```

Save your file and refresh your browser, the _blue box_ will move to a new location based on the offset properties.

![Positioned element shown in Firefox Devtools](https://thepracticaldev.s3.amazonaws.com/i/z83qtuwxcllvh2vplunh.jpg)

Now, lets move the _red box_. Add the following to `.child-two`:

```css
.child-two {
  /* All properties remain the same */

  position: absolute; /* we are moving the box around with absolute positioning */
  top: 50px;	      /* this will the box from the top of its parent, down by 50px */
  left: 70px;	      /* this will move the box to the right by 70px */
}
```

Save and refresh your browser. If your _Developer Tools is docked to the right_ the _red box_ will appear to be on the _blue box_. This is not the case. Close your _Developer Tools_ and your browser window should be similar to the image below.

![A positioned box in Devtools](https://thepracticaldev.s3.amazonaws.com/i/cydplufi5devjxlf6xjj.jpg)

What just happened? See if you can fix this before you proceed.

The reason the box is out of its parent is because the parent `position` is `static` and that's why the browser positioned the element relative to the `body` element. The fix is to add `position: relative` to the `.parent`.

```css
.parent {
  /* All properties  remains the same */
  
  position: relative;  /* creates a relative position for the element */
}
```

Save your file and refresh your browser. The _red box_ should come back to its parent container by appearing on the _blue box_.

![3 different boxes shown in browser](https://thepracticaldev.s3.amazonaws.com/i/vwzcoxjzexkpde0wt5bi.jpg)

Let's move the third box, Add the following to `.child-three`:

```css
.child-three {
  /* All properties  remains the same */
  
  position: relative;  /* creates a relative position for the element */
  top: 10px;	       /* this will the box from the top of its   parent, down by 10px */
  left: 90px;	       /* this will move the box to the right by 90px */
}
```

Save and refresh your browser.

![Positioned Element in CSS shown in the browser](https://thepracticaldev.s3.amazonaws.com/i/5p3o5sgu263pl09gkuaz.jpg)

What's next? Some `z-index`.

Let's bring the _blue box_ forward. Right now, we'll give it a `z-index` of `1` 

```css
.child {
  /* All properties  remains the same */
  
  z-index: 1; /* add this */
}
```

Save your file and refresh. Use "Inspect element" on the _blue box_ and view the _Box Model_. I have highlighted the `z-index` value in the image.

![A blue box in a browser](https://thepracticaldev.s3.amazonaws.com/i/eja8cin25j4a5taxpbyy.jpg)

How about we bring the _red box_ forward? Good idea! We just have to make its `z-index` higher than that of the _blue box_. Add the following to `.child-two`:

```css
.child-two {
  /* All properties  remains the same */
  
  z-index: 2; /* add this */
}
```

Save and refresh your browser.

![A red box shown in the browser](https://thepracticaldev.s3.amazonaws.com/i/z1ndot6lwbtua1pignvw.jpg)

Now what happens if we give the third box a negative `z-index`?. This snippet should do just that. Don't forget to save your file.

```css
.child-three {
  /* All properties  remains the same */
  
  z-index: -1; /* add this */
}
```

The box is gone. But we can see its position by _clicking on the icon_ beside the word '_relative_' in the _Box Model_ . The browser will show the box's position and its previous position before it was moved.

![A box with negative z-index](https://thepracticaldev.s3.amazonaws.com/i/y1ynbhc1kmc1ikv1vkop.jpg)

If you _hover your mouse_ over the _inner most part_ of the box model you'll get similar result.

![The location of a box shown in the web browser](https://thepracticaldev.s3.amazonaws.com/i/tupfmkmzr94s5fbgc378.jpg)

You can get it back by deleting the negative `z-index`.

<hr>
<hr>
[David](https://dev.to/dovca/) made an important contribution in the comments that i was not aware of:

![David's comment](https://thepracticaldev.s3.amazonaws.com/i/v5yj1rxu91qyqik0ubxr.PNG)

To demonstrate this, you will have to update your HTML to match the snippet below:

```html
<div class="parent">
  <div class="child">
    <div class="child-three"></div>
  </div>
  <div class="child-two"></div>
</div>
```

With this `.child-three` is now a child of `.child`. Now update the CSS rule of `.child-three` by giving it a `z-index` value higher than `.child-two`:

```css
.child-three {
  /* All other properties remain the same */
  
  z-index: 100;
}
```

Save your files. Refresh the browser.

You will realize that despite `.child-three` having a higher `z-index` value than `.child-two` it's still going to appear behind `child-two` because `.child-three` parent (`.child`) has a lower `z-index` value than `.child-two`.

![A box trapped in the z-index of its parent](https://thepracticaldev.s3.amazonaws.com/i/waclrtf1kf2xgwd54pvl.PNG)

Thank you! David.

<hr>
<hr>

We used three different colors to distinguish the boxes. What does it mean at this stage of the article?

It means our next topic is _CSS Colors_.