What is the order of application of multiple blend modes? - css

I have following CSS code:
div {
background: url('image-url'), linear-gradient(gradient), url('image-url-2');
background-blend-mode: blend-mode-1, blend-mode-2;
}
The position of gradients or url backgrounds can change. I think that should have have any effect on blending order. My question is how are these modes applied to calculate final value?
Do browsers first apply blend-mode-1 on url('image-url') and linear-gradient(gradient) and later apply blend-mode-2 on the result of first and url('image-url-2') or is it the other way around?
Am I using the correct number of background-blend-modes or do I need to specify 3 of them?

The stacking order of the background-images is the key factor here.
Your background images are stacked in the reverse order, the first in the list being the uppermost in the rendering stack.
The blendmodes are applied as any comma separated property applied on backgrounds, the first one to the first image, the second one to the second, and so on.
in your example
div {
background: url('image-url'), linear-gradient(gradient), url('image-url-2');
background-blend-mode: blend-mode-1, blend-mode-2;
}
url2 is at the bottom.
Above it, you have the gradient, with blend-mode-2 applied.
And above it, the image-url with blend-mode-1.
You could set a third background-blend-mode. In this case, it would aply to the blend between image-url-2 and background-color (That you don't set in your example, but that could be set)

Blending takes place from back to front.
In other words, each element (image or gradient) is blended with the result of blending all underlying elements.
This is important, because many blend modes are not associative.
An example is difference.
Suppose you have 3 elements:
A = solid color #fff (front element; closest to user)
B = solid color #666
C = solid color #666 (back element; farthest from user)
What will happen is this:
Blending B with C; the result is black (#666 - #666 = #000).
Blending A with the result from the previous step (black); the result is white (#fff - #000 = #fff).
If blending would have started from the front element, then the result would have been 'dark charcoal':
(#fff - #666) - #666 = #333.
Live demo:
.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>
Here's what the specs had to say about it.
From Compositing and Blending Level 2:
Conceptually, the colors in the source element are blended in place with the backdrop.
and:
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.
Still a bit vague; composition and blending are related, but not the same.
But the logical interpretation is:
blending should work from back to front.
I think all major browser vendors have followed that interpretation.
It makes sense to specify the third blend mode.
As already pointed out by vals, a third blend mode can be specified to blend the third element with the background-color.
This blend step will always come first, since background color is always behind any of the elements specified in background-image.
You could say background-color acts like a fourth element.
However, the absence of the third blend mode does not mean 'do not blend'!
From 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.
In other words, background-blend-mode: <bm1>, <bm2> is automatically expanded into:
background-blend-mode: <bm1>, <bm2>, <bm1>
I won't deny this third blend mode has no effect, but that is for an entirely different reason:
the absence of background-color.
From the same document:
Everything in CSS that creates a stacking context must be considered an ‘isolated’ group.
and:
In an isolated group, the initial backdrop shall be black and fully transparent.
and:
Cs = (1 - αb) x Cs + αb x B(Cb, Cs)
A fully transparent background (αb = 0) causes the result of blending to be discarded, and to keep the color of the source element (here: the third element).
This is what happens when no background color is specified.
There is always the possibility that somebody will add a background color later.
To avoid unexpected color changes, I would recommend to always specify an explicit blend mode for the element in the back.
If you don't want to blend with the background color (if any), then just say so, by adding normal to the end of the list of blend modes.
It may prevent nasty surprises in the future, especially when <bm1> (the front blend mode, which will automatically occupy the empty spot in the back) is kind of an exotic blend.

Related

CSS Transparent Text with Solid Background Surrounding Text

I am searching for a pure CSS method for creating transparent text within a box(div,p,etc) where the box is filled with a color surrounding the text, but not the text itself (which would be transparent a la rgba/hsla).
Imagine a div styled in such a way that the text color within is rgba .2 alpha lvl, and the background color is solid, where the background solid color cannot be seen in the text. Of course, a solution using multiple stacked divs/blocks would be greatly acceptable, but should allow for a hover state, so the effect can be switched on/off. In using this, one could apply this div on top of an image or another div that can be seen through the letters.
SO! CSS/html works in such a way that text is always applied on top of a background (called a background for a reason), so, using transparent colors on text color does nothing but show the color of the background. I have tried creating a background with a big box shadow, in order to see if it's ever calculated differently, and it is not (and couldn't think of another method).
Instead of blabbering on with my limited CSS knowledge, I think you get the point, so give me your best! I want this to work in Chrome and Firefox at least.
Stacked Overflow doesn't allow me to put a jsfiddle without accompanied code, and I don't want to put pointless code here just to link to a 'starting point' code.
Instead, here's an image explaining the obvious idea:
Demo Fiddle
You CAN accomplish this in CSS only, but with limited support.
You can set the -webkit-background-clip property, and -webkit-text-fill-color to transparent.
This will only work in webkit browsers however.
e.g.:
div {
color: white; /* Fallback */
background: url(yourimage.png) no-repeat;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
See here for more on background-clip
The background-clip CSS property specifies whether an element's
background, either the color or image, extends underneath its border.
If there is no background image, this property has only visual effect
when the border has transparent regions (because of border-style) or
partially opaque regions; otherwise the border covers up the
difference.
Alternatively- you can use SVG, per this question

Cannot combine translucent Gradient filter with Shadow filter in IE8

I am trying to mimic, in IE8, the effect of having both an RGBA background and a box-shadow applied to a div. If I set an opaque background, I can use the Microsoft 'Shadow' filter to successfully achieve the box-shadow effect. With the background set to 'transparent', I can get an RGBA background by applying the 'Gradient' filter. But, if I try to combine both filters like so,
div#translucentBG {
zoom : 1;
background : transparent;
filter:
progid:DXImageTransform.Microsoft.Gradient(StartColorStr=#80464646, EndColorStr=#80464646),
progid:DXImageTransform.Microsoft.Shadow(Color=#ffffff, Strength=5, Direction=0),
progid:DXImageTransform.Microsoft.Shadow(Color=#ffffff, Strength=5, Direction=90),
progid:DXImageTransform.Microsoft.Shadow(Color=#ffffff, Strength=5, Direction=180),
progid:DXImageTransform.Microsoft.Shadow(Color=#ffffff, Strength=5, Direction=270);
}
then the div will have the correct box shadow but an opaque #464646 background. Simply remove all the Shadow filters, and magically, the div turns translucent again. This is pretty frustrating; since IE renders both effects perfectly separately, I can't imagine why it fails when combining them. I know there are probably workarounds and alternative methods available, but what really interests me is why the above technique fails the way it does.
Explanation
I set up this fiddle for people to see the effect (in IE8 of course).
I believe the reason why is that the gradient is registering as a "fill" value, and when it does, the drop shadow is itself filling in solid behind it. This is in effect taking away the transparency you are probably seeking (that is, it is transparent, it is just showing through to the drop shadow below, which is opaque, and thus covering up the background). Notice how the last div in my example fiddle is not "showing" at all because the drop shadow does not get applied when there is no fill to "shadow" for.
That the drop shadow is in fact filling in behind your gradient is further supported by the fact that when just a border is applied, as in the last div on this fiddle, the drop shadow is going "into" the div as well. So the shadow is not just an "edge" property that does not fill in below the fill of the object.
Box-Shadow Comparison
This fiddle shows the box-shadow implementation.
Note that the specification for box-shadow is different than the behavior seen with the IE Shadow filter. You were not "deluded by the behavior of the box-shadow property in FF/Chrome, which acted like an edge property," because it is an edge property. (Well, maybe you were deluded in thinking IE filters would work the same.) It does not fill in behind the box itself unless the inset keyword is part of the definition (in which case, it only fills to the inside). The box-shadow spec says (emphasis added):
An outer box-shadow casts a shadow as if the border-box of the element
were opaque. The shadow is drawn outside the border edge only: it is
clipped inside the border-box of the element.
This is exactly what you are seeing in FF/Chrome. The IE filter was around long before box-shadow and the way it was implemented was obviously different. Note that I also emphasized in the above quote that the element is treated as if opaque, which means that even a background: transparent will show a shadow (as the example fiddle shows at the bottom). This is also different from the IE Shadow filter.

Showing two different gradients as a background using CSS?

I want to have 2 different gradients in the background of my site - I am using the following to call one gradient - how do I declare more than one (i.e. to show a different gradient on the left and a different one on the right)
body
{
background: -webkit-gradient(linear, left top, left bottom, from(#E0E0E0), to(#fff));
background: -moz-linear-gradient(top, #E0E0E0, #fff);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#E0E0E0', endColorstr='#ffffff');
}
So I want want the left side of the background to be a different colour gradient to the right.
Any ideas?
Cheers!
<void after update of your question>
You should use a [multi-background](http://www.w3.org/TR/css3-background/#layering)
declaration where the first and second values are separated by a comma like
`background: value1, value2;`.
Also the background on top (here a gradient) should whether not recover entirely the
first one or have some transparency, obviously.
</void>
Here's a fiddle using the :before pseudo to create something to stick a background on without creating an extra element in the HTML code. If linear-gradient is supported by a browser, then :before is also supported AFAIK so no problem here.
http://jsfiddle.net/URWD8/
The main trick is creating a box half-size and well positioned (and then having text content above this absolutely positioned box with z-index ... by trial and error I admit).
And use also declarations with the other vendor prefixes: -o- is lacking here and also the one without prefix linear-gradient for IE10 and future versions of other browsers. See http://caniuse.com/#feat=css-gradients
OT:
Fun and/or abusing of :before and :after :) with http://css-tricks.com/examples/ShapesOfCSS/ and http://ie7nomore.com/#CSS2 (search for those pseudos in both pages)

CSS Background Overloads

I'm trying to understand someone's CSS >> HERE <<.
Basically, he has defined his background element with this syntax:
background: url( 'bars.gif' ) 0 -50px no-repeat;
My image is a different size than his, so I am trying to adjust my code to fit my image. However, the w3schools info on CSS Background shows that this format should be used:
background: #ffffff url('img_tree.png') no-repeat right top;
Where is the overload info for background located?
Good question.
Short answer: The order is irrelevant to the final product.
Background is shorthand for five different properties.
background-color (# followed by digits or a named color)
background-image (url('url goes here'))
background-repeat (repeat, repeat-x, ...)
background-attachment (fixed, scroll)
background-position (location, percent, or pixels)
Notice that each option contains a unique formatting. This allows the renderer to understand the declaration without relying on a specific order. Also, any parameters unspecified are set to the default.
W3schools suggests a format to reduce the cognitive load on developers (which obviously didn't work in this case). I would suggest that you stick with W3's suggestion to hopefully avoid this confusion in the future.

Can you add noise to a CSS gradient?

Is it possible to add noise to a gradient in CSS?
Here is my code for a radial gradient:
body {
color: #575757;
font: 14px/21px Arial, Helvetica, sans-serif;
background-color: #2f3b4b;
background: -moz-radial-gradient(center 45deg, circle closest-corner, #2f3b4b 0%, #3e4f63 100%);
background: -webkit-gradient(radial, center center, 10, center center, 900, from(#2f3b4b), to(#3e4f63));
}
What would I add to that to have noise on top of it, to give it texture?
This is by far the most hassle free and best way to implement this. It is purely CSS and very very simple to do, no extra files - nothing. Ok, it's not the best way possible, but it works very well, very reliable (never failed when testing across very old browsers) and very fast to load.
Found it a few months ago, and used it ever since, simply copy and paste this code in to your CSS.
background-image: url(data:image/png;base64,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);
Then add your background color
background-color:#0094d0;
Demo: JSFiddle
Source:
https://coderwall.com/p/m-uwvg
Creating Textures (Noise) Using SVG Filters & CSS Gradients
You want noise in your gradient? You're in luck!
Perlin noise is a type of gradient noise. The SVG standard specifies a filter primitive called <feTurbulence>, which implements the Perlin function. It allows the synthesis of artificial textures like clouds or marble—the noise you want.
Step 1: Define an SVG Graphic
Create a small SVG file called noise.svg.
<svg
xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink'
width='300' height='300'>
<filter id='n' x='0' y='0'>
<feTurbulence
type='fractalNoise'
baseFrequency='0.75'
stitchTiles='stitch'/>
</filter>
<rect width='300' height='300' fill='#fff'/>
<rect width='300' height='300' filter="url(#n)" opacity='0.80'/>
</svg>
This graphic defines two rectangles. The first is filled with a solid color. The second is translucent with the noise filter applied. The second rectangle is overlayed on the first to provide a noise effect.
SVG Options
Fist and most obvious is that you can change the dimensions of the graphic. However, the CSS background-repeat property can be used to fill an element, thus 300×300 should suffice.
The filter's type attribute can be fractalNoise or turbulence, which specifies the filter function. Both provide a different visual, but in my opinion, the noise filter is a little more subtle.
The filter's baseFrequency attribute can range from 0.5–0.9 to provide a course to fine texture, respectively. This range is visually optimal for either filter in my opinion.
The first rectangle's fill can be changed to provide a different base color. Later, however, we essentially combine this color with a translucent CSS gradient, which also defines a color(s). So white is a good starting point here.
The second rectangle's opacity can range from 0.2–0.9 to set the filter intensity, where a higher number increases the intensity.
At this point, you could tweak the aforementioned options, set this noise graphic as a background image via CSS, and call it a day. But if you want a gradient, like the OP, go to Step 2.
Step 2: Apply a CSS Gradient
Using the background-image property, you can set the SVG noise graphic as the background on any element and overlay a gradient. In this example, I'll apply the noise graphic to the entire body and overlay a linear gradient.
body {
/* white to black linear noise gradient spanning from top to bottom */
background:
linear-gradient(rgba(255,255,255,.5), rgba(0,0,0,.5)),
url('noise.svg');
}
The linear-gradient() function creates a pseudo image, which is stacked on top of noise.svg. The result is a translucent gradient with our noise showing through it.
CSS Options
First, and most obvious, is that the defined gradient colors can be changed. However, if you want a solid color without a gradient, make the two end-point colors equal. The benefit is that you can use the same noise graphic with or without a gradient throughout a site or among projects.
Multiple images, created with the *-gradient() functions, can be overlayed on the noise graphic and more than two color parameters and angles can be specified in a single gradient function to provide all kinds of cool visuals.
The opacity of the gradient parameters—i.e. rgba() and hsla()—can be increased to intensify the defined color and reduce the noise level. Again, 0.2–0.9 is an ideal range.
Conclusion
This is a highly customizable and very light-weight (~400 bytes) solution that allows you to simply define noise of any color or gradient. Although there are several knobs to turn here, this is only the beginning. There are other SVG filter primitives, such as <feGaussianBlur> and <feColorMatrix>, which can provide additional results.
There's no current way in css to add 'noise' to a background.
An alternative solution would be to create a transparent noise png in your graphic editor. Then apply that graphic as a background to a <div>. You would then need to place that <div> over the entire area of the <body> which should then give an appearance of a gradient with noise.
For the sake of novelty, here is some pure CSS noise without using a data URI:
#box {
width:250px;
height:250px;
position:relative;
background-size:55px 10px;
background-repeat: repeat;
background-image: -webkit-repeating-radial-gradient(1% 21%, closest-corner, rgba(255,0,255,.5), rgba(0,255,255,.5), rgba(0,0,0,1) 1.7%), -webkit-repeating-radial-gradient(51% 51%, closest-corner, rgba(255,255,255,1), rgba(255,255,255,1), rgba(0,255,0,1) 10%);
}
#box::before {
content:'';
width:100%;
height:100%;
position:absolute;
mix-blend-mode:exclusion;
background-size:12px 22px;
background-repeat: repeat;
background-image: -webkit-repeating-radial-gradient(61% 21%, closest-corner, rgba(255,255,255,1), rgba(0,255,0,.5), rgba(3,0,255,1) 20%), -webkit-repeating-radial-gradient(91% 51%, closest-corner, rgba(255,255,255,1), rgba(255,255,1,.5), rgba(055,255,255,1) 20%);
left:0;
z-index:998;
}
#box::after {
content:'';
width:100%;
height:100%;
position:absolute;
mix-blend-mode:exclusion;
background-size:15px 13px;
background-repeat: repeat;
background-image: -webkit-repeating-radial-gradient(21% 21%, closest-corner, rgba(255,255,255,1), rgba(0,0,255,.5), rgba(3,0,255,1) 20%);
left:0;
top:0;
z-index:999;
}
<div id="box"></div>
Some more information about how this was created: http://jollo.org/LNT/public/css-noise.html
While this doesn't qualify as true noise, a pure CSS3 approach would be using multiple repeating-linear-background selectors, which are often used in pattern generators.
Here are a few examples:
http://jsfiddle.net/andrewodri/eMB6E/
http://lea.verou.me/2010/12/checkered-stripes-other-background-patterns-with-css3-gradients/
http://lea.verou.me/css3patterns/
With some right combination of backgrounds, angles, color stops, and transparency, a reasonable noise-like effect should be achievable :)
Hope that sets you in the right direction anyways...
Yes, there's currently no CSS-based approach for noise textures. If you're hell-bent on a programmatic (rather than image-based) approach, though, you could try using HTML5 canvas. There's a tutorial here on how to generate noise using JavaScript --> Creating Noise in HTML5 Canvas
However, doing the Canvas approach will result in a much slower experience for your visitors, because A) JavaScript is an interpreted language, and B) writing graphics using JS is extra slow.
So, unless you're trying to make a point by using HTML5, I'd stick with an image. It'll be faster (for you to make and for your users to load), and you'll have a finer degree of control over the appearance.
It's 2023, so here's my answer: the best option would be with a lightweight inline SVG filter and one CSS declaration... which includes the background gradient. No external files, no base64-ing anything. Plus it does a good job of preserving the non-grainy gradient as it doesn't mess up with its contrast or brightness.
The SVG filter would look as follows:
<svg width='0' height='0'>
<filter id='grainy' x='0' y='0' width='100%' height='100%'>
<feTurbulence type='fractalNoise' baseFrequency='.537'/>
<feColorMatrix type='saturate' values='0'/>
<feBlend in='SourceGraphic' mode='multiply'/>
</filter>
</svg>
The CSS code would look as follows:
background: filter(radial-gradient(circle, red, tan), url(#grainy))
What's the catch?
Well, it doesn't really work anywhere at this point (early January 2023), though it should soon start working in Safari. Safari is the only browser to have implemented the filter() function, which allows us to only apply a filter on a background-image layer, without affecting the element's text content or descendants. Right now, even in Safari, it only works on url() images, though it should soon work on CSS gradients as well.
We can still do this and it works cross-browser:
background: radial-gradient(circle, mediumturquoise, darkslateblue);
filter: url(#grainy)
live demo
However, as mentioned above, this filter affects the entire element it's set on, including descendants and text content.
In order to avoid that, we need to move the background and filter declarations on a pseudo, absolutely positioned, behind its parent's content, covering the area of its entire parent - live demo.
This is easily doable and cross-browser, but it would still be nicer to have support for the filter() function, not use up a pseudo just for this and reduce the CSS needed for this to ~15% of what we have to write now with this workaround.
So here are the bug links for this in the other browsers:
Chrome
Firefox
One more thing: if you don't really need the graininess, it's just a nice to have visual enhancement, you could store the gradient in a --grad custom property and have:
div {
--grad: radial-gradient(circle, mediumturquoise, darkslateblue);
background: var(--grad);
#supports (background: filter(conic-gradient(red, tan), blur(1px))) {
background: filter(var(--grad), url(#grainy))
}
}
For anyone interested, breaking down the SVG filter:
this svg only exists to contain the filter, it won't actually be used to display anything, so we zero its dimensions (and ideally also get it out of the flow with position: absolute in the CSS); no other attributes on it are necessary when it's inline (if you want to move it to an external file, you'll have to add xmlns='http://www.w3.org/2000/svg')
the filter obviously needs an idto be referenced, but by default, the filter effect will also spill (relevant for feTurbulence) outside the the element it's applied to by 10% in every direction (default values for x and y are -10% and for width and height are 120%), so we want to restrict it to just the element's area, from 0% to 100% along both axes (alternatively if you don't feel like setting all those attributes, I guess you could set clip-path: inset(0) in the CSS; note that overflow: hidden won't cut it as that only hides the element's content spilling outside its padding-box, but not graphical effects on the actual element, such as those produced by a filter)
first filter primitive creates a noise layer; I don't really understand how this works - there's this article which a lot of people have recommended, but it loses me once it goes from 1D to 2D; what I have noticed is that it's better to switch from the default type value (turbulence) to fractalNoise and that the smaller the baseFrequency value is, the finer the graininess of the noise is (also, don't use integers for this - use 7.01, but not 7)
second filter primitive completely desaturates its input (equivalent to the effect of grayscale(1) or saturate(0)); since we haven't explicitly specified an input, it defaults to using the result of the previous filter primitive - the noise layer; to do this, it switches from the default type for feColorMatrix (which is matrix) to saturate and sets values to 0 (if you have a good mental image of the HSL model/ bicone, you'll know that a saturation of 0% means we always have a grey; how light or how dark, that depends on the lightness, the 'L' in "HSL")
third and final filter primitive blends the desaturated noise with the element the filter is applied on; feBlend takes two inputs, one of which is set to 'SourceGraphic' (note those capitals matter!), while the other one defaults to using the result of the previous filter primitive; finally, the mode we use is multiply (this multiplies the % RGB values of the two layers, pixel by pixel)
This is all that's needed for the filter. There's nothing in there that you don't need.
A lot of times, SVG generators spit out a lot of unnecessary attributes, but this was handwritten and I only included what's really needed for it to work cross-browser.
Building on top of Clint Pachl's answer, I used CSS's mix-blend-mode to get a grainier effect and to selectively punch up the colors of that make up the gradient.
See https://jsfiddle.net/jimmmy/2ytzh30w/ for example code.
Update: I wrote an article about it in CSS-Tricks: Grainy Gradients
It is not possible (even if it was, it'd take a crapton of code tricks to do so) to generate noise textures using CSS alone. There aren't any new CSS3 properties that provide that sort of effect out of the box. A much quicker solution is to use a graphic editor such as Photoshop to do that.

Resources