多种混合模式的应用顺序是什么?

What is the order of application of multiple blend modes?

我有以下 CSS 代码:

div {
  background: url('image-url'), linear-gradient(gradient), url('image-url-2');
  background-blend-mode: blend-mode-1, blend-mode-2;
}

渐变或 url 背景的位置可以改变。我认为这应该对混合顺序有任何影响。我的问题是这些模式如何应用于计算最终价值?

浏览器是先在 url('image-url')linear-gradient(gradient) 上应用 blend-mode-1 然后在第一个和 url('image-url-2') 的结果上应用 blend-mode-2 还是另一个?绕开?

我使用的背景混合模式数量是否正确,还是我需要指定其中的 3 个?

背景图像的堆叠顺序是这里的关键因素。

您的背景图像以相反的顺序堆叠,列表中的第一个是渲染堆栈中的最上面。

混合模式应用为应用在背景上的任何逗号分隔 属性,第一个应用到第一个图像,第二个应用到第二个,依此类推。

在你的例子中

div {
  background: url('image-url'), linear-gradient(gradient), url('image-url-2');
  background-blend-mode: blend-mode-1, blend-mode-2;
}

url2 在底部。

在它上面,你有渐变,应用了 blend-mode-2。

在它上面,图像-url 混合模式-1。

您可以设置第三种背景混合模式。在这种情况下,它将适用于 image-url-2 和 background-color 之间的混合(您没有在示例中设置,但可以设置)

混合从后向前进行。

换句话说,每个元素(图像或渐变)都与混合所有底层元素的结果混合。

这很重要,因为许多混合模式不是 associative。 一个例子是差异。 假设你有 3 个元素:

  • A = 纯色 #fff(前面的元素;最靠近用户)
  • B = 纯色 #666
  • C = 纯色 #666(背面元素;离用户最远)

会发生这样的事情:

  • 将B与C混合;结果是黑色 (#666 - #666 = #000).
  • 将A与上一步的结果混合(黑色);结果是白色的 (#fff - #000 = #fff).

如果混合从前面的元素开始,那么结果会是 'dark charcoal':
(#fff - #666) - #666 = #333.

现场演示:

.p1 {                   /* |#fff - |#666 - #666|| = #fff */
   background-image:
      linear-gradient(#fff, #fff),       /* front element */
      linear-gradient(#666, #666),
      linear-gradient(#666, #666);       /* back element */
   background-blend-mode: difference, difference, normal;
}

.p2 {                   /* |#666 - |#666 - #fff|| = #333 */
   background-image:
      linear-gradient(#666, #666),       /* front element */
      linear-gradient(#666, #666),
      linear-gradient(#fff, #fff);       /* back element */
   background-blend-mode: difference, difference, normal;
}
<p class="p1">White</p>
<p class="p2">Dark charcoal</p>

这是规范中必须说明的内容。 来自 Compositing and Blending Level 2:

Conceptually, the colors in the source element are blended in place with the backdrop.

和:

The backdrop is the content behind the element and is what the element is composited with. This means that the backdrop is the result of compositing all previous elements.

还是有点模糊;组合和混合是相关的,但并不相同。 但逻辑解释是: 混合应该从后往前进行。 我认为所有主要的浏览器供应商都遵循了这种解释。

指定第三种混合模式是有意义的。

正如 vals 已经指出的那样,可以指定第三种混合模式以将第三个元素与 background-color 混合。 此混合步骤将始终排在第一位,因为背景颜色始终位于 background-image 中指定的任何元素之后。 你可以说 background-color 就像第四个元素。

但是没有第三种混合模式并不代表'do not blend'! 来自 Compositing and Blending Level 2:

If a property doesn’t have enough comma-separated values to match the number of layers, the UA must calculate its used value by repeating the list of values until there are enough.

换句话说,background-blend-mode: <bm1>, <bm2>会自动展开为: background-blend-mode: <bm1>, <bm2>, <bm1>

我不否认这第三种混合模式没有效果,但这是出于完全不同的原因: background-color 缺席。 来自同一文档:

Everything in CSS that creates a stacking context must be considered an ‘isolated’ group.

和:

In an isolated group, the initial backdrop shall be black and fully transparent.

和:

Cs = (1 - αb) x Cs + αb x B(Cb, Cs)

完全透明的背景(αb = 0)导致混合结果被丢弃,并保持源元素(此处:第三个元素)的颜色。 这是未指定背景颜色时发生的情况。

以后总有可能有人会添加背景色。 为避免意外的颜色变化,我建议始终 为后面的元素指定一个明确的混合模式。 如果您不想与背景颜色(如果有)混合,那么只需在混合模式列表的末尾添加 normal 即可。 它可以防止将来出现令人讨厌的意外情况,尤其是当 <bm1>(前面的混合模式,它将自动占据后面的空白点)是一种奇异的混合时。