三种用纯CSS实现染色效果的方法

 2016-10-03 15:48

为一张图片增加染色效果(color tint)渐渐变成了一种潮流。它可以给网站上的图片一个统一的色调,当你与图片发生交互时还可以变化成另外一种风格。

有时候,这种效果也被运用到一些特殊的情况下,比如默哀。

滤镜效果

一直以来,我们需要使用图像处理软件来生成两个版本,然后在写一些简单的CSS代码来处理这两个版本的交替显现。这个方法行得通,但它会导致你需要更多的资源。另外一种方法是:在图片上层遮盖一层半透明的纯色;或者把图片设置为半透明。但这个不是真正意义上的染色效果:不仅没有把图片的各种颜色转换为目标色调,同时也极大削弱了图片的对比度。

基于滤镜的方法(不完全支持)

由于没有一种现成的滤镜是专门为了这个效果而设计的,我们需要花费一些心思,把多个滤镜组合起来。

我们使用的第一个滤镜是sepia(),它会给图片增加一种降饱和度的橙黄色染色效果,几乎所有像素的色相值会被收敛到35~40。

滤镜效果

如果我们想要的主色调饱和度比这个更高,可以用saturate()滤镜来给每个像素提升饱和度。假设我们想要的主色调是hsl(335,100%,50%),那就需要把饱和度提升一些。具体取决于实际情况,我们通常需要用肉眼来观察和判断。这种效果有一种暖黄金色的染色效果。

滤镜效果

图片看起来很不错了,但我们需要的是亮粉色。因此,我们还需要再添加一个hue-rotate()滤镜,把每个像素的色相以指定的度数进行偏移。因此,我们就到如下代码和效果:

filter:sepia(1) saturate(4) hue-rotate(295deg);

滤镜效果

最后,我们再稍微整合下,把图片做一些动画效果放在上面:

img.lvjing{
    transition: .5s filter;
    filter:sepia(1) saturate(4) hue-rotate(295deg);
}
img.lvjing:hover{
    filter:none;
}

基于混合模式的方案(不完全支持)

你可能会发现,滤镜产生的结果与我们在图像处理软件中得到的效果不完全一致。即使我们想把图像调为一种很亮的颜色,结果仍然会显得像褪了色一般。如果尝试把saturate()滤镜增加饱和度,又会得到一种不自然的、过度风格化的效果。不过,幸好我们还有另外一种更好的实现方法——混合模式!

如果用过类似photoshop的朋友就会知道,当我们把两个元素叠加时,混合模式控制了上层元素的颜色与下层元素进行混合。用它来实现混合模式会保留上层元素的HSL亮度信息,并从它的下层吸取色相和饱和度信息。如果在下层准备好我们想要的主色调,并把待处理的图片放在上层并设置为这种混合模式,那本质上就是在做染色处理。

要对一个元素设置混合模式,有两个属性可以派上用场:max-blend-mode可以为整个元素设置混合模式,background-blend-mode可以为每层背景单独置顶混合模式。这意味着,如果用这个方案来处理图片,我们实际上有两种选择,不过各有千秋:

  • 第一种:需要把图片包裹在一个容器中,并把容器的背景色设置为我们想要的主色调。

  • 第二种:不用图片元素,而是用<div>元素——把这个元素的第一层背景设置为要染色的图片,并把第二层背景设置为我们想要的主色调。

针对不同的场景,可以选择这两者其中之一。举例来说,如果我们希望对一个<img>元素应用到这个效果,就需要把它包含在另一个元素内部。不过如果我们有了这一层容器,比如<a>,那就水到渠成了。

<a herf="#"><img class="lvjing" src="..." alt="..."></a>

然后,只需要两行代码就可以实现这个效果:

a{background:hsl(335,100%,50%);}
img{mix-blend-mode:luminosity;}

滤镜效果

和CSS滤镜类似,混合模式可以平稳退化,如果不支持,效果只是不出现而已,图片本身还是完好可见的。另外还有一点要注意,滤镜可以动画,混合模式不行。

max-blend-mode是把整个元素向下进行混合,而不管它下层是什么。因此,如果我们把这个属性设置为luminosity混合模式,那图片就总算会跟着某些东西进行混合。此外,使用background-blend-mode属性则可以让每层背景跟它的下层进行混合,但并不关系元素之外是什么情况。另外,当我们只有一个背景图像以及一个透明背景色时,会发生什么?

不会出现任何混合效果!

那么,我们尝试用background-blend-mode属性来达成我们想要的效果。先调整下html:

<div class="img" style="background-image:url(...)"></div>

这样一来,我们只需要对一个<div>设置CSS了,因为这个技巧不需要其他额外的元素:

.img{
    width:720px;height:300px;
    background-size:cover;
    background-color:hsl(335,100%,50%);
    background-blend-mode:luminosity;
    transition:.5s background-color;
}
.img:hover{
    background-color:transparent;
}


不过,就和之前提到的那样,这两种方法都不理想。它们的主要问题在于:

  • 图片的尺寸需要在CSS代码中写死;

  • 在语意上,这个元素并不是一张图片,因此并不会被读屏器之类的设备读出来。

生活就是这样,没有完美的。需要用到哪种,就看各位的需求了。

作者头像

作者:紫铜炉

自由博主,网页设计师。我关注科技产品和个人博客发展,注重用户体验和界面优化。

 发表评论: