211

z-index and the stacking context

Slide instructions

SPACEBAR to move forward through slides.

SHIFT & SPACEBAR to move backwards through slides.

LEFT ARROW & RIGHT ARROW to move through sections.

ESC to see overview and ESC again to exit.

F to enter presentation mode and ESC to exit.

Introduction

This slide deck looks at the z-index property as well as exploring the stacking context.

The z-axis

CSS allows you to position elements on the “x”, “y” and “z” axes.

X, Y and Z axes

The easiest way to understand the “z-axis” is to imagine that every HTML element is just like a piece of paper.

You can stack some pieces of paper on top of others so that they overlap.

Elements that are stacked at the top are closest to the user.

Elements that are stacked below are further away from the user.

Elements closest to the user

The z-index property

The z-index property defines the z-order of positioned elements along the z-axis.

The z-index property can only be applied to positioned elements.

A positioned element is an element with a position value of absolute, relative, fixed or sticky.


p { position: absolute; }
p { position: relative; }
p { position: fixed; }
p { position: sticky; }

The z-index property syntax is:


<'z-index'> =
  auto | <integer> | inherit

The auto value


p { z-index: auto; }

The auto value is the initial value.

The auto value sets the stack level of the box to 0 in the current stacking context.

<integer> values


p { z-index: -2; }
p { z-index: 0; }
p { z-index: 9; }

An <integer> consists of one or more digits between 0 and 9.

An <integer> may be preceded by a "-" (negative) or "+" (positive) symbol.

A value of -0 is equivalent to 0 and is not a negative number.

The <integer> value defines the stack level of the box along the z-axis.

Elements with a larger z-index value will normally sit above elements with a smaller z-index value.

The inherit value


p { z-index: inherit; }

The inherit value inherits the z-index from the parent element.

Exercise 1: Apply some z-index values

Open this HTML file in an editor:
exercises-start/exercise-211-01.html

Write a CSS rule to style the element with a class of example1.

Set with z-index: auto, top: 100px, left: 100px and background: yellow.


/* Add styles here */
.example1 {
  z-index: auto;
  top: 100px;
  left: 100px;
  background: yellow;
}

Write a second CSS rule to style the element with a class of example2.

Set with z-index: 0, top: 120px, left: 120px and background: lime.


/* Add styles here */
.example2 {
  z-index: 0;
  top: 120px;
  left: 120px;
  background: lime;
}

example2 should overlap example1.

Write a third CSS rule to style the element with a class of example3.

Set with z-index: 1, top: 140px, left: 140px and background: pink.


/* Add styles here */
.example3 {
  z-index: 1;
  top: 140px;
  left: 140px;
  background: pink;
}

example3 should overlap example1 and example4.

Write a fourth CSS rule to style the element with a class of example2.

Set with z-index: -1, top: 160px, left: 160px and background: silver.


/* Add styles here */
.example4 {
  z-index: -1;
  top: 160px;
  left: 160px;
  background: silver;
}

example4 should sit behind all other boxes.

Check your work against the finished HTML file:
exercises-finished/exercise-211-01.html

The stacking context

Every element in an HTML document can either be displayed on top of or beneath other elements in the document.

The “stacking context” defines how elements can be stacked on top of each other.

The root (HTML) element forms the root stacking context.

Unless specific conditions are met, all HTML elements are stacked in relation to this root element.

However, some types of elements can form their own stacking contexts.

An element that forms a new stacking context

Then, all descendants are stacked in relation to this new stacking context element rather than the root element.

New stacking contexts

A new stacking context is formed, anywhere in the document, by any element that matches one of the following criteria:

1. The root (HTML) element of document.

2. Any element with a position value of absolute and z-index value other than auto.


p {
  position: absolute;
  z-index: 1;
}

3. Any element with a position value of relative and z-index value other than auto.


p {
  position: relative;
  z-index: 1;
}

4. Any element with a position value of fixed.


p {
  position: fixed;
}

5. Any element with a position value of sticky (for mobile devices only).


p {
  position: sticky;
}

6. Any child of an element set with a display value of flex where the child has a z-index value of anything other than auto.


.parent {
  display: flex;
}

.child-of-parent {
  z-index: 1;
}

7. Any element with an opacity value less than 1.


p {
  opacity: .5;
}

8. Any element with a transform value of anything other than none.


p {
  transform: translate(25px, 5px);
}

9. Any element with a filter value of anything other than none.


p {
  filter: blur(5px);
}

10. Any element with a perspective value of anything other than 0 or none.


p {
  perspective: 350px;
}

11. Any element with a isolation value of isolate.


p {
  isolation: isolate;
}

Some other properties trigger the stacking context. However, they won’t be covered here as they are very obscure.

Stacks within stacks

Stacking contexts can contain other stacking contexts, and these create a hierarchy of stacking contexts.

A stacking context inside another stacking context

Self-contained

Each stacking context is self-contained. Child elements are considered part of the stacking order of the parent stacking context.

Boxes in stacking contexts are self-contained

Boxes in one stacking context cannot come between boxes in another stacking context.

Boxes in one stacking context cannot come between boxes in another stacking context

Descendants with z-index

If z-index values are applied to a child of a stacking context, these values are only relevant inside the parent stacking context.

z-index values only relevant inside that stacking context

Exercise 2: Create some stacking contexts

Open this HTML file in an editor:
exercises-start/exercise-211-02.html

Write a CSS rule to style the element with a class of example1.

Set with z-index: 1, top: 120px, left: 120px and background: yellow.


/* Add styles here */
.example1 {
  z-index: 1;
  top: 120px;
  left: 120px;
  background: yellow;
}

example1 is now a stacking context as it has positioning as well as a z-index value.

Write a second CSS rule to style the element with a class of example2.

Set with z-index: 1, top: 20px, left: 20px and background: lime.


/* Add styles here */
.example2 {
  z-index: 1;
  top: 20px;
  left: 20px;
  background: lime;
}

example2 will be positioned in relation to example1 - the parent element.

Write a third CSS rule to style the element with a class of example3.

Set with z-index: 1, top: 180px, left: 180px and background: pink.


/* Add styles here */
.example3 {
  z-index: 1;
  top: 180px;
  left: 180px;
  background: pink;
}

example3 is also a stacking context as it has positioning as well as a z-index value.

Write a fourth CSS rule to style the element with a class of example4.

Set with z-index: 1, top: 20px, left: 20px and background: silver.


/* Add styles here */
.example4 {
  z-index: 1;
  top: 20px;
  left: 20px;
  background: silver;
}

example4 will be positioned in relation to example3 - the parent element.

example2 and example4 cannot interact as boxes in one stacking context cannot come between boxes in another stacking context.

Check your work against the finished HTML file:
exercises-finished/exercise-211-02.html

Stack order

For every stacking context, there is a complex series of steps to determine how descendant elements will be displayed.

This is referred to as the “stack order”.

This stack order is described from back-to-front (furthest away from the user to closest to the user).

It has been simplified slightly from the CSS Positioned Layout Module Level 3 specification.

1. Root element stacking context

If the stacking context is the root element, this layer displays in order:

  1. background color of the element
  2. background image of the element
Background of root element stacking context

2. Block, list-item or table stacking context

If the stacking context is a block, list-item, or other block equivalent:

  1. background color of the element
  2. background image of the element
  3. column rule of the element
  4. border of the element
Background and borders of block-level stacking context

Otherwise, if the stacking context is a block-level table:

  1. table background (color then image)
  2. column group backgrounds (color then image)
  3. column backgrounds (color then image)
  4. row group backgrounds (color then image)
  5. row backgrounds (color then image)
  6. cell backgrounds (color then image)
  7. cell column rule for multi-column
  8. all table borders (in tree order)
Background and borders of table stacking context

3. Negative positioned descendants

Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.

Positioned element with negative z-index

4. block-level or table descendants

For all its in-flow, non-positioned, block-level descendants in tree order: If the element is a block, list-item, or other block equivalent:

  1. background color of the element
  2. background image of the element
  3. column rule of the element
  4. border of the element
Backgrounds and borders of in-flow block-level elements

Otherwise, the element is a table:

  1. table background (color then image)
  2. column group backgrounds (color then image)
  3. column backgrounds (color then image)
  4. row group backgrounds (color then image)
  5. row backgrounds (color then image)
  6. cell backgrounds (color then image)
  7. cell column rule for multi-column
  8. all table borders (in tree order)
Backgrounds and borders of in-flow table elements

5. Floats

All non-positioned floating descendants, in tree order.

Floating elements

6. Inline elements that generate stacking contexts

If the element is an inline element that generates a stacking context, then:

  • 1. For each child of the line box, in that line box, in tree order:
    • 1.2 background color of the element
    • 1.3 background image of the element
    • 1.4 column rule of the element
    • 1.5 border of the element
    • 1.6 For inline elements: any underlining, any overlining, the text, any line-through
    • 1.7 Optionally, the outline of the element
Backgrounds, borders, text and outline of inline stacking context

7. Other elements

Otherwise: first for the element, then for all its in-flow, non-positioned, block-level descendants in tree order:

  • 7.1 If the element is a block-level replaced element, then: the replaced content, atomically.
  • 7.2 Otherwise, for each child of the line box, in that line box, in tree order:
    • 7.2.1 background color of the element
    • 7.2.2 background image of the element
    • 7.2.3 column rule of the element
    • 7.2.4 border of the element
    • 7.2.5 For inline elements: any underlining, any overlining, the text, any line-through
    • 7.2.6 Optionally, the outline of the element
  • 7.3 Optionally, if the element is block-level, the outline of the element.
Backgrounds, borders, text and outlines of other elements

8. Elements with position, opacity or transform

All positioned, opacity or transform descendants, in tree order that fall into the following categories:

  1. All positioned descendants with z-index: auto or z-index: 0, in tree order.
  2. All opacity descendants with opacity less than 1, in tree order.
  3. All transform descendants with transform other than none, in tree order.
Positioned elements with z-index: 0 or z-index: auto

9. Positioned dependants with z-index

Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order (smallest first) then tree order.

Positioned elements with z-index of 1 or greater

10. Outlines

Finally, implementations that do not draw outlines in steps above must draw outlines from this stacking context at this stage.

Confusion with z-index

Applying z-index to elements seems very simple.

All you need to do is use a higher z-index value for the element to sit on top.

However, this simple rule does not work when you apply z-index to elements inside stacking contexts.

Let’s use an example with three positioned elements, all with different z-index values.


<div class="example1">
  <div class="example2"></div>
</div>
<div class="example3"></div>

.example1,
.example2,
.example3 { position: absolute; }

.example1 { z-index: 1; }
.example2 { z-index: 15; }
.example3 { z-index: 3; }

In theory, example2 should sit on top of the other two elements as it has a higher z-index value than the other two elements.

However, example3 will sit on top of both of the other elements.

example3 sits on top

example1 forms a new stacking context because it has position and a z-index value of 1.

example2 is a child of the example1 stacking context, so its z-index value is only relevant inside example1.

example2 is only relevant inside example1

This means that only two z-index values that matter - the values for example1 and example3.

example1 stacking context has a value of 1, while example2 has a value of 3. So, example3 wins!

z-index: 1 and z-index: 3

Exercise 3: Confusion around z-index and stacking contexts

Open this HTML file in an editor:
exercises-start/exercise-211-03.html

Write a CSS rule to style the element with a class of example1.

Set with z-index: auto, top: 120px, left: 120px and background: yellow.


/* Add styles here */
.example1 {
  z-index: 1;
  top: 120px;
  left: 120px;
  background: yellow;
}

example1 is now a stacking context as it has positioning as well as a z-index value.

Write a second CSS rule to style the element with a class of example2.

Set with z-index: 15, top: 20px, left: 20px and background: lime.


/* Add styles here */
.example2 {
  z-index: 15;
  top: 20px;
  left: 20px;
  background: lime;
}

example2 will be positioned in relation to example1 - the parent element.

Write a third CSS rule to style the element with a class of example3.

Set with z-index: 3, top: 160px, left: 160px and background: pink.


/* Add styles here */
.example3 {
  z-index: 3;
  top: 160px;
  left: 160px;
  background: pink;
}

Even though example2 has the highest z-index, it is inside the example1 stacking context, so example3 will be highest in stack order.

Check your work against the finished HTML file:
exercises-finished/exercise-211-03.html

Confusion with background-colors

Let’s use an example with two <div> elements, one below the other.

Both of these are in-flow block-level elements without any positioning.

example2 not overlapping

<div class="example1"></div>
<div class="example2"></div>

If you were to apply negative margins to the top of example2, this element would overlap example1.


.example1 {
  background: yellow;
}

.example2 {
  background: lime;
  margin-top: -1em;
}
example2 overlapping slightly

If the negative margin value is increased, example2 will overlap example1 more fully.


.example1 {
  background: yellow;
}

.example2 {
  background: lime;
  margin-top: -2em;
}

Even though example2 is overlapping, the background-color of example2 sits under the text from example1.

example2 overlapping further

Some developers assume this is a rendering bug, but this is not correct.

The strange overlap is due to the stack order of elements and their properties.

As described before, the bottom of the stack is the furthest from the user, the top of the stack is the nearest to the user.

The backgrounds of in-flow block-level elements are rendered as part of Layer 4.

The text for example1 is rendered as part of Layer 7.

This means that both pieces of text are on a higher layer than the two background-colors.

Even though the second element overlaps the first, the overlapping happens on two different layers.

Exercise 4: Confusion around backgrounds and text

Open this HTML file in an editor:
exercises-start/exercise-211-04.html

Write a CSS rule to style the element with a class of example2.

Set with margin-top: -2em; and background: lime.


/* Add styles here */
.example2 {
  margin-top: -2em;
  background: lime;
}

Even though example2 overlaps example1, the backgrounds and text overlap at different levels.

Check your work against the finished HTML file:
exercises-finished/exercise-211-04.html

Confusion with negative z-index

If you place a child positioned box on top of a parent positioned box and give the child box a negative z-index value, will the child go behind the parent?

In some circumstances the answer is “yes”, but in other circumstances, “no”.

The answer depends on whether there is a stacking context involved.

Let’s use an example with two <div> elements, one inside the other.


<div class="example1">
  Example1
  <div class="example2">Example2</div>
</div>

example1 needs to be given positioning, z-index, padding and background-color.


.example1 {
  position: absolute;
  z-index: 1;
  padding: 20px;
  background-color: lime;
}

This parent element is now a stacking context as it has been given positioning and z-index value.

example2 also needs to be given positioning, z-index, padding and background-color.

However, the z-index property needs a negative value.


.example2 {
  position: absolute;
  z-index: -1;
  padding: 20px;
  background-color: yellow;
}

Some developers will assume that example2 will now move below example1 due to the negative z-index value.

However, example2 will move below the text of example1, but not below its background.

example2 has a negative z-index but sits on top of the background of example2

This is because example1 is a block-level stacking context and follows the stacking order described earlier.

The backgrounds of block-level stacking contexts are rendered as part of Layer 2.

example2 is a child elements with a negative z-index value and therefore is rendered as part of Layer 3.

The text for both elements is rendered as part of Layer 7.

Exercise 5: Confusion around negative z-index

Open this HTML file in an editor:
exercises-start/exercise-211-05.html

Write a CSS rule to style the element with a class of example1.

Set with position: absolute, z-index: 1, left: 120px, top: 120px and background: lime.


/* Add styles here */
.example1 {
  position: absolute;
  z-index: 1;
  left: 120px;
  top: 120px;
  background: lime;
}

Write a second CSS rule to style the element with a class of example2.

Set with position: absolute, z-index: -1, left: 20px, top: 20px and background: yellow.


/* Add styles here */
.example2 {
  position: absolute;
  z-index: -1;
  left: 20px;
  top: 20px;
  background: yellow;
}

example2 will be positioned in relation to example1.

Even though example2 has a negative z-index value, the background of example1 will be lower in stack order.

Check your work against the finished HTML file:
exercises-finished/exercise-211-05.html

Russ Weakley

Site Twitter Github Slideshare Linkedin

Next deck

212: CSS Floats