如何使用CSS给背景图片着色?

64

我通过CSS设置了一个背景图像。

html {
background-image: url('../img/cello.jpg');
background-attachment: fixed;
background-size: 100%;
}

我计划为网站的不同页面设置不同的背景图片,因此文本对其非常重要。目前我在 #main 内容框中使用半透明黑色背景来确保可读性:

#main {
background: rgba(0, 0, 0, 0.5);
}

但是,我真正想做的是在整个背景图像上具有这种半透明背景,因为黑色框看起来有点笨重。我尝试制作一个包括整个HTML文档的<div id=#tint>,并将rgba(0, 0, 0, 0.5)赋予#tint,但完全行不通——我要么什么也看不到变化,要么整个背景都变成了简单的灰色,根本没有任何背景图像可见。这是否完全不可能?

6个回答

138
使用background-blend-mode来实现简单的着色效果。
你可以使用background-blend-mode CSS 属性:

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

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

将其放置在具有背景图像的任何元素上,您就可以开始使用了。
该属性在现代浏览器中得到很好的支持,但不包括IE 11。对于不支持的浏览器,您可以使用polyfill工作演示

其他选项

使用filter进行复杂的着色

您可以使用filter CSS属性:

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

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

将其放置在具有背景图像的任何元素上,然后您就可以开始使用了。 为了改变颜色,请改变hue-rotate的值。
该属性在现代浏览器中得到很好的支持,但不包括IE 11。 工作演示

使用平面线性渐变和多重背景叠加

.background-tint {
  background-image: 
    linear-gradient( rgba(0,0,0,.5), rgba(0,0,0,.5) ),
    url('http://placehold.it/420')
}

我认为这是最常用的技术,但它的缺点是硬编码,也就是说你不能只是拿一个类,贴在一个元素上并进行着色。
你可以将其转化为一个较少或者Sass的mixin,类似于: 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 )
}

工作演示

使用透明背景

这种方法的优点是适用于大多数浏览器,并且只需将其添加到任何元素的一个漂亮的类中。 缺点是,如果该元素内还有其他内容,则必须将其包装在一个带有某种定位的 div 中,最好使用 position: relative

示例:

.box {
  width: 300px; height: 300px;
  background-size: cover;
  background-image: url('https://picsum.photos/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%;
  /* Tint color */
  background-color: rgba(100,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>

工作演示


唯一有效的方法是不会影响div内字体颜色的方法。 - pjammer
@pjammer,“sewer”是什么意思?我测试了所有的例子,字体的颜色就是你设置color参数的颜色。 - hitautodestruct
请注意:如果您正在寻找最广泛的浏览器支持,请使用linear-gradient。https://caniuse.com/#feat=css-gradients - Clifford Fajardo
非常好的解决方案。 不幸的是,这总是会创建一个完整的填充。例如,如果我有一个部分透明的背景图像,覆盖颜色也会填充背景图像的透明区域。 因此,乘法并不完全像着色一样行为。 - Thomasn
1
@Thomasn 感谢指出这一点。我添加了另一种方法,使用filter属性,应该可以仅涵盖非透明区域。缺点是很难选择色调的颜色。 - hitautodestruct

24

我认为您需要创建一个覆盖层元素(可能是div),该元素具有所需的半透明背景。类似于:

.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*/
}

当然,还有一个小演示:小链接


好的,那很有帮助,谢谢。然而,尽管我的背景图片现在已经成功变暗了,但是现在我的中心内容框/列看不到了......嗯,它不太像是一个盒子/列,而更像是只是给 <body> 设置了 10% 30% 的边距。现在内容已经消失了。我对网页设计并不是很有经验,不知道为什么会这样。 - user1623053
@user1623053 你需要将所有内容嵌套在覆盖层的 div 中,就像它是 body 一样。编辑:哦,好吧,给 body 添加边距是个坏主意。使用另一个元素并给它相同的边距即可。 - Chris
好的,我的所有内容都嵌套在覆盖层div中,并且我已经将边距移动到一个特殊的div中。这两个div都嵌套在body中,但不在任何其他元素之内。现在我的覆盖层色调完美地工作了,但是我的内容没有边距... - user1623053
@user1623053,如果您的网站已经上线,能否请您分享一个演示或链接?谢谢。 - Chris
太棒了,谢谢!(我没有足够的声望来点赞,但我已经打勾了) - user1623053
显示剩余4条评论

8
这对我非常有帮助: https://css-tricks.com/tinted-images-multiple-backgrounds/ 这是一个关于多重背景和图像着色的CSS技巧。
.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);
}

借鉴另一个答案,您可以使用Less中的现有颜色来完成此操作,例如:

linear-gradient(
  fade(@brand-primary, 50%),
  fade(@brand-primary, 50%)
),

1
这在所有主要浏览器上都得到支持,包括IE11 + Edge。使用background-blend-mode的第二个响应在IE或Edge上不受支持。"https://caniuse.com/#feat=css-gradients - Clifford Fajardo

1

0

在我看来,这是问题最简单的解决方案。

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

为了提高可读性,背景颜色可以选择黑色,并将不透明度设置在50%到60%的范围内,效果很好。

0

尝试使用不透明度:

opacity:0.4;
filter:alpha(opacity=40); /* For IE8 and earlier */

我真的不明白——rgba 对于主要内容框正常工作。 - user1623053

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接