6

This has been asked before, but only where z-index is explictly defined in the CSS.

I am trying to use clip-path on a heading, but then pull up an image from within an element beneath this back over the top of that header. However, as soon as I define a clip-path on the header, the image (which should be higher up the stacking order as it appears later in the code) goes underneath the header:

body {
  padding: 1em;
}

header {
  background: #a00;
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 5em), 0 100%);
}

h1 {
  margin: 0;
  padding: 2em;
  font: 300%;
  color: white;
  text-align: center;
}

section {
  background: #ccc;
  padding-top:5em;
  margin-top:-5em;
}

img {
  margin-top: -10em;
  
}
<header>
  <h1>Header Content</h1>
</header>

<section>
  <img src="https://via.placeholder.com/330/0000FF/808080"/>
</section>

I would expect the image to be above the header. After playing around some more, I found that if I set position:relative on the image - it works:

body {
      padding: 1em;
    }

    header {
      background: #a00;
      clip-path: polygon(0 0, 100% 0, 100% calc(100% - 5em), 0 100%);
    }

    h1 {
      margin: 0;
      padding: 2em;
      font: 300%;
      color: white;
      text-align: center;
    }

    section {
      background: #ccc;
      padding-top:5em;
      margin-top:-5em;
    }

    img {
      margin-top: -10em;
      position:relative;
    }
<header>
  <h1>Header Content</h1>
</header>

<section>
  <img src="https://via.placeholder.com/330/0000FF/808080"/>
</section>

But why? What's happening here please and why does clip-path appear to affect the stacking order of elements later in the page?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
EvilDr
  • 8,943
  • 14
  • 73
  • 133

1 Answers1

6

From the specifcation:

A computed value of other than none results in the creation of a stacking context the same way that CSS opacity does for values other than 1.

Then considering the painting order:

  1. 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. For those with 'z-index: auto', treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one. For those with 'z-index: 0' treat the stacking context generated atomically.
    2. All opacity descendants with opacity less than 1, in tree order, create a stacking context generated atomically.
    3. All transform descendants with transform other than none, in tree order, create a stacking context generated atomically.

The element with clip-path is painted at the step (8) and the image will be painted before if has no position set

  1. 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 ...

If you add position:relative to image it will be postioned and will fall under the step (8) and the tree order will decide making it above the clip-path element

Here is the same code with opacity where you will have the same painting order:

body {
  padding: 1em;
}

header {
  background: #a00;
  opacity:0.8;
}

h1 {
  margin: 0;
  padding: 2em;
  font: 300%;
  color: white;
  text-align: center;
}

section {
  background: #ccc;
  padding-top:5em;
  margin-top:-5em;
}

img {
  margin-top: -10em;
  
}
<header>
  <h1>Header Content</h1>
</header>

<section>
  <img src="https://via.placeholder.com/330/0000FF/808080"/>
</section>

Related:

Why does position:relative; appear to change the z-index?

Why can't an element with a z-index value cover its child?


Many other properties behave the same way and oblige your element to be painted at the step (8):

  • filter ref
  • backdrop-filter ref
  • perspective ref
  • mix-blend-mode ref
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • 1
    any solution for clip-path element to appear above its child element? – Vishal Bhatt Jul 31 '20 at 05:39
  • @VishalBhatt what do you mean? can you show an example – Temani Afif Jul 31 '20 at 07:55
  • thanks for asking. Actually I have dropped that idea and found another work around. – Vishal Bhatt Jul 31 '20 at 09:56
  • @TemaniAfif when you click on the link **painting order**, the message appears : This version is outdated! For the latest version, please look at https://www.w3.org/TR/css-position-3/. but the link they give no longer offers the painting order. I would like to know why – oceanGermanique Sep 28 '22 at 16:57
  • 1
    @Oceangermanique they removed the painting order from that part of the Spec to re-write it that's why I am linking an old version. You can refer to this one: https://www.w3.org/TR/CSS22/zindex.html but it doesn't include the part I need – Temani Afif Sep 28 '22 at 19:12