Search code examples
htmlcssstacking-contextview-transitions-api

Why are elements with view-transition-name painted on top of elements with position fixed?


div {
  width: 50px;
  height: 50px;
  border: solid 2px black;
}

.fixed {
  position: fixed;
  top: 25px;
  left: 25px;
  background-color: red;
}

.named {
  background-color: green;
  view-transition-name: something;
}
<div class="fixed"></div>
<div class="named"></div>

As far as I know, positioned elements render on top of non-positioned elements in the same stacking context.

The spec says the following:

Elements captured in a view transition during a view transition or whose view-transition-name computed value is not none (at any time):

  • Form a stacking context.
  • Are flattened in 3D transforms.
  • Form a backdrop root.

It doesn't say that elements with view-transition-name become positioned, so I don't understand why it is being rendered on top of the fixed-positioned one in the previous example.


Solution

  • As far as I know, positioned elements render on top of non-positioned elements in the same stacking context.

    That's not true, there are a lot of properties that change the painting order of elements and make them at the same level as positioned elements.

    Example using opacity:

    div {
      width: 50px;
      height: 50px;
      border: solid 2px black;
    }
    
    .fixed {
      position: fixed;
      top: 25px;
      left: 25px;
      background-color: red;
    }
    
    .named {
      background-color: green;
      opacity: .999;
    }
    <div class="fixed"></div>
    <div class="named"></div>

    Or clip-path

    div {
      width: 50px;
      height: 50px;
      border: solid 2px black;
    }
    
    .fixed {
      position: fixed;
      top: 25px;
      left: 25px;
      background-color: red;
    }
    
    .named {
      background-color: green;
      clip-path: inset(0);
    }
    <div class="fixed"></div>
    <div class="named"></div>

    view-transition-name is one of them. It doesn't make the element positioned. It only updates its painting order to make it similar to positioned elements and since there is no z-index involved, the tree order will decide.

    Related: Why does clip-path (and other properties) affect the stacking order (z-index) of elements later in DOM?