1

So I have looked in many different SO questions and google results but I have not found the exact information I have been looking for.

I have a background-image that I wanted to do a transparent color overlay for. The common answer is to just use both the background-image and color properties, or even on the same line. But neither of those options work for me. It simply will NOT allow me to have both. Even using a linear gradient instead of color does not work.

The only thing that I have gotten to work is to use a parent/child div with image/color respectively. Which is confusing.

The parent has the image, but the color overlay is...the child? If there is no opacity on the child's color, then I can't see the image at all.

Can someone please help me understand the relationship and why I can't do both?

.color {
  width: 100%;
  height: 50vh;
  background-color: hsl(277, 64%, 61%);
  opacity: 50%;
}

.hero {
  background-image: url("https://via.placeholder.com/800");
  background-size: cover;
  background-repeat: no-repeat;
  width: 100%;
  height: 100%;
}
<div class="hero">
  <div class="color"></div>
</div>
Drew
  • 21
  • 4
  • Your question is really about setting opacity on a particular background property, yet you make almost no mention of that. You should revise to be more clear. Your title question is nonsensical, since you _can_. – isherwood Nov 12 '21 at 16:18

5 Answers5

1

You can't set opacity on individual properties--only on elements (and pseudo-elements). It sounds to me like you want a background image, and you also want a background color, and you want the color to be over the image and have reduced opacity. CSS doesn't allow that kind of specificity.

You can, however, accomplish what you're after with one markup element. Just create a pseudo-element in your CSS:

.color {
  height: 50vh;
  background: url("https://via.placeholder.com/800x200");
  background-size: cover;
  position: relative;
}

.color:after {
  position: absolute;
  content: '';
  width: 100%;
  height: 100%;
  background-color: hsl(277, 64%, 61%);
  opacity: 50%;
}
<div class="hero color"></div>
isherwood
  • 58,414
  • 16
  • 114
  • 157
0

in principle you can use both. You should try to use in this case z-index. So, the color class should has a z-index higher than hero. I think this should do the trick. So, just add this z-index

.color {
  width: 100%;
  height: 100%;
  background-color: hsl(277, 64%, 61%);
  opacity: 50%;
  z-index: 1;
}

Cheers, Marcelo

Turtles
  • 234
  • 3
  • 13
0

Your background image has no transparency, and is set to cover the entire element. The background colour has been applied, but it's hidden behind the image.

https://developer.mozilla.org/en-US/docs/Web/CSS/background-image
The background images are drawn on stacking context layers on top of each other. The first layer specified is drawn as if it is closest to the user.

The borders of the element are then drawn on top of them, and the background-color is drawn beneath them.

Richard Deeming
  • 29,830
  • 10
  • 79
  • 151
  • That being said, would you agree that using a parent/child relationship is the method of choice? If so, that would still leave me questioning their relationship. – Drew Nov 12 '21 at 16:20
  • Not really. If you want a colour on top of the image, you can use multiple background images on a single element; you'd just need to use a single-colour "gradient" instead of the `background-color` property. However, it would need to be at least partially transparent to let the image show through. – Richard Deeming Nov 12 '21 at 16:25
0

You only need one element for what you are trying to do.

background-image, background-size, background-position, background-repeat might all be relevant depending on your use case.

You can also put a background-color.

If you use the combined form, background, be aware that settings in that will overwrite some of the other settings.

For demo purposes this CSS spells everything out:

background-image: url(your url);
background-size: cover; /* will resize and crop the image as needed to fill the el */
background-position: center center;
background-repeat: no-repeat no-repeat;
background-color: your background color.

Note, you cannot use a gradient (linear, radial or conic) as a background-color. These gradients have the personality of an image and can only be used in background-image. You can however have several images in the background-image value, separated by commas and with the first one being 'above' the second and so on.

A Haworth
  • 30,908
  • 4
  • 11
  • 14
  • I'm aware that they can be combined into the background property separated by commas, however I have stated that method does not work for me, and I don't know why. – Drew Nov 12 '21 at 16:21
  • Hi, what is the 'they' here? Could you show us an example you are using which does not work - an exact copy. Thanks. – A Haworth Nov 13 '21 at 09:39
0

background is shorthand for all background styles

See CSS: background documentation on MDN:

The background shorthand CSS property sets all background style properties at once, such as color, image, origin and size, or repeat method.

You should try background-image for setting the image URL separately.

A similar example would be margin and margin-left, margin-right, margin-top, margin-bottom. You will override the value for margin-left if you set margin.

See example below where .box-3 will lose its background color:

.box {
  width: 200px;
  height: 69px;
  background: #696969 url(https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27) no-repeat;
}

.box-2 {
  background-image: url(https://i.stack.imgur.com/xP24h.jpg?s=48&g=1);
  background-color: #969696;
}

.box-3 {
  background: url(https://i.stack.imgur.com/xP24h.jpg?s=48&g=1) no-repeat;
}
<div class="box box-1"></div>
<div class="box box-2"></div>
<div class="box box-3"></div>
Peter Krebs
  • 3,831
  • 2
  • 15
  • 29