How can I tint a background image with CSS?
CssBackgroundTintCss Problem Overview
I have a background image set up through CSS.
html {
background-image: url('../img/cello.jpg');
background-attachment: fixed;
background-size: 100%;
}
I plan on having a different background image for different pages of the website: so it's important that text is legible over it. Right now I've got a translucent black background to my #main content box in the middle like this in order to ensure legibility:
#main {
background: rgba(0, 0, 0, 0.5);
}
What I really want to do, though, is to have that kind of translucent background over the entire background image, because the black box looks a bit clunky. I've tried making a <div id=#tint>
which includes the whole HTML document and giving rgba(0, 0, 0, 0.5) to #tint, but that doesn't work at all--I can either get nothing to change or I can get the entire background to become a simple grey with no background image visible at all. Is this simply not possible?
Css Solutions
Solution 1 - Css
background-blend-mode
for a simple tint
Use You can use the background-blend-mode
css property:
.background-tint {
background-color: rgba(200,100,0,.5); /* Tint color */
background-blend-mode: multiply;
}
Place it on any element with a background image and you're good to go.
The property is well supported in modern browsers NOT including IE 11. For non supporting browsers you can use a polyfill.
Other Options
filter
for a complex tint
Use You can use the filter
css property:
.background-tint {
filter: sepia(100%) saturate(200%) brightness(70%) hue-rotate(330deg);
}
Place it on any element with a background image and you're good to go.
In order to change the color change the hue-rotate
value.
The property is well supported in modern browsers NOT including IE 11.
Use a flat linear-gradient and a multiple background overlay
.background-tint {
background-image:
linear-gradient( rgba(0,0,0,.5), rgba(0,0,0,.5) ),
url('http://placehold.it/420')
}
I think this is the most widely used technique but it has the downside of being hardcoded i.e. you can't just take a class, stick it on an element and make a tint.
You could make this into a less or sass mixin, something like:
less
.background-tint(@tint-color, @image-url) {
background-image:
linear-gradient( @tint-color, @tint-color ),
url( @image-url )
}
sass
@mixin background-tint($tint_color, $image_url) {
background-image:
linear-gradient( $tint_color, $tint_color ),
url( $image_url )
}
Use a transparent background
.background-tint { position: relative; }
.background-tint::after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,.5);
}
This method has the advantage of working on most browsers and is just a nice class you add to any element.
The downside is that if you have anything else inside of that element you will have to wrap it in a div with some kind of positioning position: relative
would work best.
Example:
<div class="background-tint">
<div class="u-relative">Some text here</div>
</div>
.u-relative { position: relative; }
Solution 2 - Css
I think you need to create an overlay element (potentially div
) which has the sought translucent background. Something like:
.overlay {
z-index: 1;
height: 100%;
width: 100%;
position: fixed;
overflow: auto;
top: 0px;
left: 0px;
background: rgba(0, 0, 0, 0.7); /*can be anything, of course*/
}
And of course, a little demo: little link.
Solution 3 - Css
This worked great for me:
https://css-tricks.com/tinted-images-multiple-backgrounds/
.tinted-image {
background:
/* top, transparent red, faked with gradient */
linear-gradient(
rgba(255, 0, 0, 0.45),
rgba(255, 0, 0, 0.45)
),
/* bottom, image */
url(image.jpg);
}
And building on another answer, you can do this with existing colors in less like:
linear-gradient(
fade(@brand-primary, 50%),
fade(@brand-primary, 50%)
),
Solution 4 - Css
It would be the overlay
property
https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingoverlay
But it's a draft. Don't rely on it
Solution 5 - Css
Try opacity:
opacity:0.4;
filter:alpha(opacity=40); /* For IE8 and earlier */