前端开发者学堂 - fedev.cn

【转载】CSS技巧-rgba函数的妙用

发布于 大漠

本文转载自:众成翻译 译者:谢于中 链接:http://www.zcfy.cc/article/2001 原文:https://css-tricks.com/the-power-of-rgba/

新出现的 CSS 颜色配置函数是一项非常有意思的功能,它给予我们在浏览器中直接操纵颜色的能力。例如,当鼠标悬停在按钮上时,可以使用color: color(black darkness(50%))改变颜色,而不需要使用 Sass 这类 CSS 预处理器。

但是浏览器现在对这种颜色函数还不支持,我们只能暂时 使用 PostCSS 将其编译成常规的颜色。当然,我们也可以使用 CSS 中的rgba()函数达到类似的效果,下面就让我们看看具体该如何操作。

工作原理

basic idea

在设计软件中,如果我们分别将具有一定透明度的白色盒子和黑色盒子放在一个较大的蓝色盒子上,它们将分别变成浅蓝色和深蓝色。

这是因为当小盒子的透明度较高时,前景色和背景色将会混在一起。如果我们将背景色从蓝色变成绿色,你能想出结果将会怎样吗?

Basic Idea Green

如你所见,当背景色变成绿色时,小盒子的颜色分别变成了浅绿色和深绿色。同理,我们也可以通过改变前景色的透明度来生成更深或更浅的颜色。现在,就让我们根据这个基本前提,深入研究一些实际例子。

理论结合实际

在上面的例子中,为了保持简洁,我们只改变了不透明度属性(opacity)。其实,在实际设计中,更为普遍的是改变rgba()的alpha值。如:

.header {
  background: rgba(0, 0, 0, 0.5); /* 不透明度为50%的黑色 */
} 

在这里我们用的是背景色(background)而不是透明度(opacity),这是因为如果使用 opacity,那么所有子元素都会受到影响,这是应该避免的。(当 opacity 属性的值应用于某个元素上时,是把这个元素(包括它的内容)当成一个整体看待,即使这个值没有被子元素继承。因此,一个元素和它包含的子元素都会具有和元素背景相同的透明度,哪怕这个元素和它的子元素有不同的 opacity 属性值。译者注)。相反,如果使用 background 的 alpha 通道的话,就能保证只更改指定的元素。

注意:在下面的 demo 中,为了让表述更简洁,将采用 Sass 中的rgba()函数。如:

.elem {
  background: rgba(white, 0.5);
} 

这将被编译为:

.elem {
  background: rgba(255, 255, 255, 0.5);
} 

为网站 header 定制主题

第一个rgba()的使用场景是为网站的 header 定制主题。在 Trello 中,使用rgba()为头部子元素 (logo, search input, buttons) 的背景色赋值:

.search {
  background: rgba(255, 255, 255, 0.5); /* 透明度为50%的白色 */
} 

Trello with Devtools

有了这个,我们就可以通过只改变 header 背景的颜色来变换主题,因为具有透明度的子元素颜色也将随之变化。

在我们的例子中,将会采用和 Trello 头部相似的方式,在开发者工具中进行实验。

Trello Header

注意在下面两个 header中,子元素的背景色是不同的。通过改变父级元素的背景色,我们可以非常方便的定制 header 主题。

Theming Header

文章标题

Article Header

在这个例子中,使用rgba()将有助于改变下列元素的颜色:

  • 顶部和底部边框
  • 中间包裹元素的背景
  • 类别链接的背景

Article Header Annotated

.parent {
  background: #5aaf4c; /* 父级背景 */
  box-shadow: 
    inset 0 8px 0 0 rgba(255, 255, 255, 0.5), 
    inset 0 -8px 0 0 rgba(255, 255, 255, 0.5); /* 顶部和底部边框 */
}

.contain {
  background: rgba(0, 0, 0, 0.1);
}

.category {
  background: rgba(255, 255, 255, 0.5);
} 

按钮

当定制按钮的主题时,可以使用rgba()来改变 hoverfocus 按钮时边框和阴影的样式。

.button {
  background: #026aa7;
  box-shadow: inset 0 -4px 0 0 rgba(0, 0, 0, 0.2);
}

.button:hover {
  box-shadow: inset 0 -4px 0 0 rgba(0, 0, 0, 0.6), 0 0 8px 0 rgba(0, 0, 0, 0.5);
}

.button:focus {
  box-shadow: inset 0 3px 5px 0 rgba(0, 0, 0, 0.2);
} 

渐变

另一个有用的场景就是给背景设置纯色,然后添加一个带有rgba()背景色的伪元素,用其生成渐变效果。

Gradients

.elem {
  background: green;
}

.elem:before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(to right, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.7));
} 

这种方法也可以帮助我们在只改变背景色的前提下模拟渐变动画效果。

.elem {
  /* other styles */
  animation: bg 2s ease-out alternate infinite;
}

@keyframes bg 
  to {
    background: green;
  }
} 

子元素

如果在 header 中有一个导航列表,我们可以给导航栏添加一个由rgba()定义的背景色。这可以使导航背景透明,从而与父级元素的背景混合。

这种方法也可以被用于实现 hover 效果:

调色盘中的深/浅效果

我们可以使用这种方法来生成调色板中的不同色调,只需要在纯色盒子上覆盖一个具有特定rgba()颜色的伪元素即可。

图像效果

如果我们想让一张图片变的更深或者更浅,同样可以使用具有rgba()背景色的伪元素。

通过使用彩色背景,我们可以产生一个彩色效果。此外,我们还可以使用mix-blend-mode属性将背景和图片混合,从而得到不同的效果。

在使用mix-blend-mode之前,请注意检查一下兼容性:

.elem:before {
  background: rgba(0, 0, 0, 1);
  mix-blend-mode: color;
} 

如果mix-blend-mode不被支持,图片将会变成黑色的一块。所以,这种效果最好被作为一种增强方式,而不是作为一种依赖。使用这种方法时,可以使用@support或者 Modernizr。

@supports (mix-blend-mode: color) {
  /* your enhanced styles go there */
} 

使用CSS变量定制主题

如果给父级元素使用 CSS 变量 (自定义属性),当变量变化时,所有的子元素都会发生变化。例如:

:root {
  --brand-color: #026aa7;
}

/* Checking for the support of CSS Variables */
@supports (--color: red) {
  .elem {
    background: var(--brand-color);
  }
} 

JavaScript

var colors = ["#026aa7", "#5aaf4c", "#00bcd4", "#af4c4c"];
var colorOptions = document.querySelectorAll(".option");
var colorLabels = document.querySelectorAll(".option + label");

for (var i = 0; i < colorOptions.length; i++) {

  /* Add an event listener to each radio button */
  colorOptions[i].addEventListener('click', changeColor);

  /* Add a value to each radio button based on colors[] array */
  colorOptions[i].value = colors[i];

  colorLabels[i].style.background = colors[i];
}

function changeColor(e) {
  /* calling the root element and set the value of a specific property. In our case: --brand-color */
  document.documentElement.style.setProperty('--brand-color', e.target.value);
} 

通过将 CSS 变量和rgba()相结合,我们可以在不给每个元素赋予新颜色的前提下,动态改变布局和颜色。

需要考虑的地方

后备颜色

虽然目前浏览器对 CSS 颜色的支持度达到了97.39%,但是对于不支持的浏览器,也需要给出后备手段。

.elem {
  background: #fff; 
  background: rgba(255, 255, 255, 0.5); /* 不支持rgba的浏览器将会忽略这个命令 */
} 

颜色对比检查

我们应确保元素之间的对比度符合可访问性标准,毕竟有时使用rgba()将得到难以识别的颜色。可以使用像 Lea Verou 的对比度检查工具来帮助确定颜色是否满足可访问性标准。Air Max 95 Invigor Print