位置的堆叠上下文:固定伪元素

Stacking context for position: fixed pseudo-elements

我正在尝试通过 this post from Four Kitchens 中描述的代码实现固定背景图像,但使用多个背景图像而不是只有一个。这是来自 post:

的代码
.what-we-do-cards {
  @include clearfix;
  border-top: 10px solid rgba(255, 255, 255, .46);
  color: $white;
  padding-bottom: 4em;
  overflow: hidden; // added for pseudo-element
  position: relative; // added for pseudo-element

  // Fixed-position background image
  &::before {
    content: ' ';
    position: fixed; // instead of background-attachment
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    background-color: white;
    background: url('/img/front/strategy.jpg') no-repeat center center;
    background-size: cover;
    will-change: transform; // creates a new paint layer
    z-index: -1;
  }
}

基本思想是使用 :before 伪元素为固定位置背景图像创建内容部分,除了 post 中链接到的示例仅使用单个固定位置部分.

我有一个故障排除 jsfiddle that works in Safari and Chrome, but not Firefox, and I'm trying to figure out how the browsers are handling the pseudo-elements differently. Also, if you comment out will-change: transform; in Chrome (line 25), you'll see the same behavior as Firefox, which I believe is due to Chrome triggering a stacking context。我不确定为什么 Safari 在 Chrome.

中没有触发堆叠上下文的情况下工作

关于堆叠上下文有一个很好的 SO 答案 here,但我不确定它如何与固定位置元素、伪元素和显式设置 z-index 一起工作。

编辑:最初的 jsfiddle 显示了如何跨浏览器创建(或不创建)固定元素的包含框,但并未真正显示背景图像如何变化。 @Oriol 解释了添加 transform: rotate(0); 如何强制在 Firefox 上创建一个包含框,但它也删除了 Chrome 中的固定关系到视口效果。我创建了一个 new jsfiddle - 是什么导致了渲染差异?

确实will-change: transform产生了一个堆叠上下文。但是,堆叠上下文与此问题无关。事实上,CSS 工作组最近 resolved position: fixed 已经创建了一个堆栈上下文。

相反,这是由于为固定位置元素创建了一个包含块。

根据The will-change property,

If any non-initial value of a property would cause the element to generate a containing block for fixed-position elements, specifying that property in will-change must cause the element to generate a containing block for fixed-position elements.

因此,will-change: transform为固定位置元素生成一个包含块,因为根据The Transform Rendering Model

Any value other than none for the transform results in the creation of both a stacking context and a containing block. The object acts as a containing block for fixed positioned descendants.

我认为 Safari 不需要 will-change: transform 因为它认为固定元素应该为固定后代创建一个包含块,即使这不是标准的。这并不奇怪,因为在 CSSWG 决定这样做之前,固定元素在 Webkit 浏览器上产生了一个堆栈上下文。

并且 Firefox 支持 will-change,但尚未实现此行为。但是,您可以通过将 transform 设置为 none 以外的任何值来获得相同的结果,例如

.fixed { transform: rotate(0); }

body { margin: 0; }
.fixed {
  height: 20vh;
  transform: rotate(0); /* Containing block for fixed elements */
}
.fixed:before {
  content: '';
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}
.one:before { background: orange; }
.two:before { background: blue; }
.three:before { background: black; }
.four:before { background: gray; }
.five:before { background: purple; }
<div class="container">
  <div class="one fixed"></div>
  <div class="two fixed"></div>
  <div class="three fixed"></div>
  <div class="four fixed"></div>
  <div class="five fixed"></div>
</div>