Title: Compositing and Blending Module Level 1 Status: ED Work Status: Refining ED: https://drafts.csswg.org/compositing-1/ TR: https://www.w3.org/TR/compositing-1/ Prepare for TR: no Previous Version: https://www.w3.org/TR/2015/CR-compositing-1-20150113/ Shortname: compositing Link Defaults: css-color-4 (property) color, css-masking-1 (property) mask Level: 1 Group: csswg Repository: w3c/csswg-drafts Complain About: missing-example-ids true Complain About: broken-links false Complain About: accidental-2119 true Inline Github Issues: title !Feedback: https://github.com/w3c/csswg-drafts/labels/compositing-1 Issue Tracking: GitHub https://github.com/w3c/csswg-drafts/labels/compositing-1 Implementation Report: https://wpt.fyi/results/css/compositing WPT Path Prefix: css/compositing/ WPT Display: open Former Editor: Rik Cabanier, then of Adobe Systems Inc., w3cid 106988 Former Editor: Nikos Andronikos, Canon Information Systems Research Australia, Nikos.Andronikos@cisra.canon.com.au Editor: Chris Harrelson, Google, chrishtr@chromium.org, w3cid 90243 Abstract: Compositing describes how shapes of different elements are combined into a single image. There are various possible approaches for compositing. Previous versions of SVG and CSS used Simple Alpha Compositing. In this model, each element is rendered into its own buffer and is then merged with its backdrop using the Porter Duff ''source-over'' operator. This specification will define a new compositing model that expands upon the Simple Alpha Compositing model by offering: Abstract:
spec:html; type:element; text:body
This subsection is non-normative.
The first part of this document describes the properties used to control the compositing in CSS.
The second part will describe the algorithms of Porter Duff compositing and blending.
Name: mix-blend-mode Value: <The syntax of the property of <> Initial: normal Applies to: All elements. In SVG, it applies to container elements, graphics elements and graphics referencing elements. [[SVG11]] Inherited: no Percentages: N/A Computed value: as specified Media: visual Animation type: discrete
<blend-mode> =
normal |
darken | multiply | color-burn |
lighten | screen | color-dodge |
overlay | soft-light | hard-light |
difference | exclusion |
hue | saturation | color | luminosity
Applying a blendmode other than normal to the element must establish a new stacking context [[!CSS21]]. This group must then be blended and composited with the stacking context that contains the element.
Given the following sample markup:
<body> <img src="ducky.png"/> </body>
And the following style rule:
body { background-color: lime; }
... will produce the following result:
Partially transparent image on a lime backdrop
If we change the style rule to include blending:
body { background-color: lime; }
img { mix-blend-mode: multiply; }
... the output will be the image blending with the lime background of the body element.
Blending of a transparent image on a lime backdrop.
Given the following svg code:
<svg> <circle cx="40" cy="40" r="40" fill="red"/> <circle cx="80" cy="40" r="40" fill="lime"/> <circle cx="60" cy="80" r="40" fill="blue"/> </svg>
And the following style rule:
circle { mix-blend-mode: screen; }
... the output will be blending of the 3 circles. Each circle is rendered from bottom to top. Where the elements overlap, the blend mode produces a change in color.
Example of 3 circles blending with a screen blend mode
In the following style sheet and document fragment:
body { background-color: lime; }
div { background-color: red; width: 200px; opacity: .95}
img { mix-blend-mode: difference; }
<body>
<div>
<img src="ducky.png"/>
</div>
</body>
... the 'opacity' on the div element is causing the creation of a stacking context. This causes the creation of a new group so the image doesn't blend with the color of the body element.
Example of blending within a stacking context.
Note how the image is not blending with the lime color.
Given the following sample markup:
<body>
<div>
<p>''overlay'' blending on text</p>
</div>
</body>
And the following style rule:
div { background-image: url('texture.png'); }
@font-face {
font-family: "Mythos Std";
src: url("http://myfontvendor.com/mythos.otf");
}
p {
mix-blend-mode: overlay;
font-family: "Mythos Std"
}
Text with a blend overlay on top of an image.
Name: isolation Value: <The syntax of the property of <> Initial: auto Applies to: All elements. In SVG, it applies to container elements, graphics elements and graphics referencing elements. [[SVG11]] Inherited: no Percentages: N/A Computed value: as specified Media: visual Animation type: discrete
<isolation-mode> = auto | isolate
In CSS, a background image or the content of an img must always be rendered into an isolated group.
For instance, if you link to an SVG file through the img tag, the artwork of that SVG will not blend with the backdrop of the content.
Name: background-blend-mode Value: <># Initial: normal Applies to: All HTML elements Inherited: no Percentages: N/A Computed value: as specified Media: visual Animation type: discrete
Given the following sample markup:
<body> <div></div> </body>
And the following style rule:
body { background-color: lime; }
div {
width: 200px;
height: 200px;
background-size: 200px 200px;
background-repeat:no-repeat;
background-image: linear-gradient(to right, #000000 0%,#ffffff 100%), url('ducky.png');
background-blend-mode: difference, normal;
}
Blending of 2 background images.
Note that the gradient is not blending with the color of body. Instead it retains its original color.
| Value: | < |
| Initial: | source-over |
<composite-mode> = clear | copy | source-over | destination-over | source-in |
destination-in | source-out | destination-out | source-atop |
destination-atop | xor | lighter
co = Cs x αs + Cb x αb x (1 - αs)Where
αo = αs + αb x (1 - αs)Where
Often, it can be more efficient to store a pre-multiplied value for the color and opacity.
The pre-multiplied value is given by
cs = Cs x αswith
Thus the formula for simple alpha compositing using pre-multiplied values becomes
co = cs + cb x (1 - αs)
To extract the color component of a pre-multiplied value, the formula is reversed:
Co = co / αo
This describes the most basic case. It consists of 1 shape that is filled with a solid color (α = 1). The shape is composited with an empty background. The empty background has no effect on the resultant composite.
Cs = RGB(1,0,0) αs = 1 Cb = RGB(0,0,0) αb = 0 co = Cs x αs + Cb x αb x (1 - αs) co = RGB(1,0,0) x 1 + RGB(0,0,0) x 0 x (1 - 1) co = RGB(1,0,0) x 1 co = RGB(1,0,0)
This is a more complex example. There is no transparency, but the 2 shapes intersect.
Applying the compositing formula in the area of intersection, gives:
Cs = RGB(0,0,1) αs = 1 Cb = RGB(1,0,0) αb = 1 co = Cs x αs + Cb x αb x (1 - αs) co = RGB(0,0,1) x 1 + RGB(1,0,0) x 1 x (1 - 1) co = RGB(0,0,1) x 1 + RGB(1,0,0) x 1 x 0 co = RGB(0,0,1) x 1 co = RGB(0,0,1)Calculating the alpha of the resultant composite
αo = αs + αb x (1 - αs) αo = 1 + 1 x (1 - 1) αo = 1Calculating the color component of the resultant composite
Co = co / αo Co = RGB(0, 0, 1) / 1 Co = RGB(0, 0, 1)
This is an example where the shape has some transparency, but the backdrop is fully opaque.
Applying the compositing formula in the area of intersection, gives:
Cs = RGB(0,0,1) αs = 0.5 Cb = RGB(1,0,0) αb = 1 co = Cs x αs + Cb x αb x (1 - αs) co = RGB(0,0,1) x 0.5 + RGB(1,0,0) x 1 x (1 - 0.5) co = RGB(0,0,1) x 0.5 + RGB(1,0,0) x 0.5 co = RGB(0.5,0,0.5)Calculating the alpha of the resultant composite
αo = αs + αb x (1 - αs) αo = 0.5 + 1 x (1 - 0.5) αo = 1Calculating the color component of the resultant composite
Co = co / αo Co = RGB(0.5, 0, 0.5) / 1 Co = RGB(0.5, 0, 0.5)
Figure 4 shows an example where both the shape and the backdrop are transparent.
Applying the compositing formula in the area of intersection, gives:
Cs = RGB(0,0,1) αs = 0.5 Cb = RGB(1,0,0) αb = 0.5 co = Cs x αs + Cb x αb x (1 - αs) co = RGB(0,0,1) x 0.5 + RGB(1,0,0) x 0.5 x (1 - 0.5) co = RGB(0,0,1) x 0.5 + RGB(1,0,0) x 0.25 co = RGB(0.25, 0, 0.5)Calculating the alpha of the resultant composite
αo = αs + αb x (1 - αs) αo = 0.5 + 0.5 x (1 - 0.5) αo = 0.75Calculating the color component of the resultant composite
Co = co / αo Co = RGB(0.25, 0, 0.5) / 0.75 Co = RGB(0.33, 0, 0.66)
Cs = (1 - αb) x Cs + αb x B(Cb, Cs)Composite
Co = αs x Fa x Cs + αb x Fb x CbWhere:
This example has 2 simple shapes. The backdrop for the blue shape includes the bottom right corner of the red shape . The dotted line shows the area that is examined during compositing of the blue shape.
The shape in the backdrop has an alpha value. The alpha value of the backdrop shape is preserved when the backdrop is calculated.
so: A + B + C = A + (B + C) = (A + B) + CWhen adding attributes to the group such as ''isolation/isolate'', blending modes other than ''normal'' or Porter Duff compositing operators other than ''source-over'', groups may no longer be invariant.
Browsers often use an infinite white, 100% opaque canvas surface [[!CSS3BG]] in the root group, for final compositing, but this is not required.
| Both | αs x αb |
|---|---|
| Source only | αs x (1 – αb) |
| Destination only | αb x (1 – αs) |
| None | (1 – αs) x (1 – αb) |
Both = 0.5 x 0.5 = 0.25 Source Only = 0.5 (1 – 0.5) = 0.25 Destination Only = 0.5(1 – 0.5) = 0.25 None = (1 – 0.5)(1 – 0.5) = 0.25Therefore, the coverage of each region is 0.25 in this example.
αo = αs x 1 + αb x (1 – αs)
The fractional terms Fa (1 in this example) and Fb (1 – αs in this example) are defined for each operator and specify the fraction of the shapes that may contribute to the final pixel value.
The general form of the equation for coverage is:
αs x Fa + αb x Fb
and incorporating color gives the general Porter Duff equation
co = αs x Fa x Cs + αb x Fb x Cb
Where:
Fa = 0; Fb = 0
co = 0
αo = 0
Only the source will be present.
Fa = 1; Fb = 0
co = αs x Cs
αo = αs
Fa = 0; Fb = 1
co = αb x Cb
αo = αb
Fa = 1; Fb = 1 – αs
co = αs x Cs + αb x Cb x (1 – αs)
αo = αs + αb x (1 – αs)
Fa = 1 – αb; Fb = 1
co = αs x Cs x (1 – αb) + αb x Cb
αo = αs x (1 – αb) + αb
Fa = αb; Fb = 0
co = αs x Cs x αb
αo = αs x αb
Fa = 0; Fb = αs
co = αb x Cb x αs
αo = αb x αs
Fa = 1 – αb; Fb = 0
co = αs x Cs x (1 – αb)
αo = αs x (1 – αb)
Fa = 0; Fb = 1 – αs
co = αb x Cb x (1 – αs)
αo = αb x (1 – αs)
Fa = αb; Fb = 1 – αs
co = αs x Cs x αb + αb x Cb x (1 – αs)
αo = αs x αb + αb x (1 – αs)
Fa = 1 - αb; Fb = αs
co = αs x Cs x (1 - αb) + αb x Cb x αs
αo = αs x (1 - αb) + αb x αs
Fa = 1 - αb; Fb = 1 – αs
co = αs x Cs x (1 - αb) + αb x Cb x (1 – αs)
αo = αs x (1 - αb) + αb x (1 – αs)
Fa = 1; Fb = 1
co = αs x Cs + αb x Cb;
αo = αs + αb
Cm = B(Cb, Cs)
with:
Cr = (1 - αb) x Cs + αb x B(Cb, Cs)
with:
This example has a red rectangle with a blending mode that is placed on top of a set of green rectangles that have different levels of opacity.
Note how the top rectangle shifts more toward red as the opacity of the backdrop gets smaller.
simple alpha compositing:
co = cs + cb x (1 - αs)
written as non-premultiplied:
αo x Co = αs x Cs + (1 - αs) x αb x Cb
now substitute the result of blending for Cs:
αo x Co = αs x ((1 - αb) x Cs + αb x B(Cb, Cs)) + (1 - αs) x αb x Cb
= αs x (1 - αb) x Cs + αs x αb x B(Cb, Cs) + (1 - αs) x αb x Cb
B(Cb, Cs) = Cs
B(Cb, Cs) = Cb x Cs
B(Cb, Cs) = 1 - [(1 - Cb) x (1 - Cs)]
= Cb + Cs -(Cb x Cs)
B(Cb, Cs) = HardLight(Cs, Cb)
Overlay is the inverse of the hard-light blend mode. See the definition of hard-light for the formula.
B(Cb, Cs) = min(Cb, Cs)
B(Cb, Cs) = max(Cb, Cs)
The result must be rounded down if it exceeds the range.
if(Cb == 0)
B(Cb, Cs) = 0
else if(Cs == 1)
B(Cb, Cs) = 1
else
B(Cb, Cs) = min(1, Cb / (1 - Cs))
if(Cb == 1)
B(Cb, Cs) = 1
else if(Cs == 0)
B(Cb, Cs) = 0
else
B(Cb, Cs) = 1 - min(1, (1 - Cb) / Cs)
if(Cs <= 0.5)
B(Cb, Cs) = Multiply(Cb, 2 x Cs)
else
B(Cb, Cs) = Screen(Cb, 2 x Cs -1)
See the definition of multiply and screen for their formulas.
if(Cs <= 0.5)
B(Cb, Cs) = Cb - (1 - 2 x Cs) x Cb x (1 - Cb)
else
B(Cb, Cs) = Cb + (2 x Cs - 1) x (D(Cb) - Cb)
with
if(Cb <= 0.25)
D(Cb) = ((16 * Cb - 12) x Cb + 4) x Cb
else
D(Cb) = sqrt(Cb)
B(Cb, Cs) = | Cb - Cs |
B(Cb, Cs) = Cb + Cs - 2 x Cb x Cs
Lum(C) = 0.3 x Cred + 0.59 x Cgreen + 0.11 x Cblue
ClipColor(C)
L = Lum(C)
n = min(Cred, Cgreen, Cblue)
x = max(Cred, Cgreen, Cblue)
if(n < 0)
C = L + (((C - L) × L) / (L - n))
if(x > 1)
C = L + (((C - L) × (1 - L)) / (x - L))
return C
SetLum(C, l)
d = l - Lum(C)
Cred = Cred + d
Cgreen = Cgreen + d
Cblue = Cblue + d
return ClipColor(C)
Sat(C) = max(Cred, Cgreen, Cblue) - min(Cred, Cgreen, Cblue)
The subscripts min, mid, and max in the next function refer to the color
components having the minimum, middle, and maximum values upon entry to the function.
SetSat(C, s)
if(Cmax > Cmin)
Cmid = (((Cmid - Cmin) x s) / (Cmax - Cmin))
Cmax = s
else
Cmid = Cmax = 0
Cmin = 0
return C;
B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
B(Cb, Cs) = SetLum(Cs, Lum(Cb))
B(Cb, Cs) = SetLum(Cb, Lum(Cs))
No new privacy considerations have been reported on this specification.
If this rule is not followed, an attacker could infer information and mount a timing attack.
A timing attack is a method of obtaining information about content that is otherwise protected, based on studying the amount of time it takes for an operation to occur. If, for example, red pixels took longer to draw than green pixels, one might be able to reconstruct a rough image of the element being rendered, without ever having access to the content of the element.