63

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?

user1623053
  • 633
  • 1
  • 5
  • 5

6 Answers6

135

Use background-blend-mode for a simple tint

You can use the background-blend-mode css property:

.box {
  width: 300px;
  height: 300px;
  background-size: cover;
  background-image: url('https://placehold.co/300');
}

.background-tint {
  background-color: rgba(200,100,0,.5);
  background-blend-mode: multiply;
}
<div class="box background-tint"></div>

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.

Working demo


Other Options

Use filter for a complex tint

You can use the filter css property:

.box {
  width: 300px; height: 300px;
  background-size: cover;
  background-image: url('https://placehold.co/300');
}

.background-tint {
  filter: sepia(100%) saturate(200%) brightness(70%) hue-rotate(330deg);
}
<div class="box background-tint"></div>

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.

Working demo

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 )
}

Working demo

Use a transparent background

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:

.box {
  width: 300px; height: 300px;
  background-size: cover;
  background-image: url('http://placehold.it/300');
  color: #facebc;
}

.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);
  margin: auto;
}

.u-relative { position: relative; z-index: 1; } 
  <div class="box background-tint">
    <div class="u-relative">300 x 300</div>
  </div>

Working Demo

hitautodestruct
  • 20,081
  • 13
  • 69
  • 93
  • only one that worked that didn't sewer the colour of the font within the `div` – pjammer Sep 17 '16 at 14:28
  • @pjammer What do you mean by "sewer"? I tested out all examples and the color of the font is what you set the `color` param to be. – hitautodestruct Nov 08 '16 at 08:57
  • Note: if your looking for the most browser support use the linear-gradient. https://caniuse.com/#feat=css-gradients – Clifford Fajardo Jul 26 '18 at 13:58
  • very good solutions. unfortunately, this always create a complete fill. p.e. if i have a partially transparent background image, the overlay-color will also fill the tranparent areas of the background image. so the multiply does not fully behave like a tint. – Thomasn Sep 16 '19 at 11:40
  • 1
    @Thomasn Thanks for pointing that out. I added another method using the `filter` property that should allow for covering only the non transparent areas. The downside is that it's not easy to choose the color of the tint. – hitautodestruct Sep 18 '19 at 08:55
24

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.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Chris
  • 26,544
  • 5
  • 58
  • 71
  • OK that was helpful thanks--however, though my background image is now successfully dimmed, now my content box/column in the centre can't be seen... Well, it's not so much a box/column as much as it is simply giving `` a margin of 10% 30%. Now that content has vanished. I am not really experienced enough with web design to know why. – user1623053 Aug 24 '12 at 16:43
  • @user1623053 You need to nest all your content within the overlay `div` -- treat it as if it's `body`. **Edit:** Oh, well, it's a bad idea to give `body` margins. Use another element and give it the same margins instead. – Chris Aug 24 '12 at 16:45
  • OK, all of my content is nested within the overlay div, and I've moved the margins to a special div just for them. Both of these divs are nested within body but outside anything else. Now I've got the overlay tint working perfectly, but my content has no margins... – user1623053 Aug 24 '12 at 16:53
  • @user1623053 Can you please share a demo or a link to your site if it's live? – Chris Aug 24 '12 at 16:55
  • OK well I've just whacked the whole page into Jsfiddle: http://jsfiddle.net/TqNqT/15/ – user1623053 Aug 24 '12 at 16:58
  • @user1623053 Are you trying to achieve [this](http://jsfiddle.net/TqNqT/16/show)? (You can view source here: [little link](http://jsfiddle.net/TqNqT/16/)). – Chris Aug 24 '12 at 17:02
  • Yes, I'm trying to achieve that, but with the tint covering the whole page. In that demo (and I've tried using it on my computer too, same result) the tint only covers parts visible without scrolling. – user1623053 Aug 24 '12 at 17:07
  • @user1623053 So sorry -- please update your CSS to match my edited answer. Basically just change the tinting `div`'s `position: absolute;` to `position: fixed;` and add `overflow: auto;`. Working demo: [little link](http://jsfiddle.net/TqNqT/18/show/) ([another link to view source](http://jsfiddle.net/TqNqT/18/)). (If this is what you're trying to achieve, don't forget to tick this answer as "accepted" and upvote it so that the question is no longer open!) – Chris Aug 24 '12 at 17:11
  • Brilliant thanks! (Don't have enough reputation to be able to upvote but I ticked it) – user1623053 Aug 24 '12 at 17:15
8

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%)
),
Chris Moschini
  • 36,764
  • 19
  • 160
  • 190
  • 1
    This is supported on all major browsers including IE11 + edge, the second response using `background-blend-mode` isn't supported on IE or Edge" https://caniuse.com/#feat=css-gradients – Clifford Fajardo Jul 26 '18 at 13:57
1

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

yunzen
  • 32,854
  • 11
  • 73
  • 106
0

Try opacity:

opacity:0.4;
filter:alpha(opacity=40); /* For IE8 and earlier */
tahdhaze09
  • 2,220
  • 1
  • 21
  • 36
0

This is the simplest solution to the problem in my opinion.

.parent-div{
     background-color : desired-color
}
#image-id{
     opacity: dersired_value%
}

To increase readibity background-color: black and opacity percentages of range 50 to 60% seem to work nicely.