Menu

CSS opacity 透明度:透明元素、透明背景与淡入淡出

opacity 让整个元素及其内部的一切变得半透明,取值从 0(不可见)到 1(完全不透明)。本文讲解它的取值、为什么 opacity 会让文字也变淡、如何只让背景透明、opacity: 0 与 visibility 和 display 的区别,以及悬停时的淡入淡出。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

opacity 的作用

opacity 设置元素的透明程度:1 是完全不透明(默认值),0 是不可见,介于两者之间的值会让背景透出来。下面的盒子放在条纹背景上,方便你看清效果:

最后一个盒子其实还在:它在这一行中占据着自己 90px 的位置,只是什么都没画出来。注意,白色数字也和盒子一起变淡了。opacity 作用于元素及其内部的一切。

背景透明,文字不透明

因为 opacity 也会让子元素变淡,所以想要“在清晰的文字后面放一个半透明背景”时,它并不是合适的工具。应该改用带 alpha 通道的背景色:

两块白色面板透出条纹的程度相同。在第一块中,文字随着面板一起变淡了。在第二块中,只有背景色是透明的(rgb(255 255 255 / 0.6),等同于 rgba(255, 255, 255, 0.6)),所以文字保持不透明,清晰易读。带透明度的颜色在颜色页面中有详细介绍。

子元素无法摆脱父元素的 opacity:在子元素上设置 opacity: 1 不起作用,因为父元素被当作一个变淡的图层来绘制,子元素已经在其中了。

取值

值效果
1 或 100%完全不透明(默认值)
0.5 或 50%半透明
0 或 0%完全透明,但仍在布局中,也能被点击
1.5、-1被限制为 1 和 0

opacity 在视觉上会“继承”,但作为属性并不继承:子元素计算出的 opacity 仍然是 1,只是它被绘制在一个变淡的父元素里。

opacity: 0、visibility: hidden 与 display: none 的区别

这三种写法都能让元素消失,但在其他方面各不相同:

opacity: 0visibility: hiddendisplay: none
占据空间是是否
能接收点击和焦点是否否
被屏幕阅读器读出是否否
能做过渡动画能,过渡平滑在一端突然切换,没有淡出不能

最容易出问题的是第二行。opacity: 0 的按钮仍然可以被点击,也可以用 Tab 键聚焦:

读数结果是询问浏览器:每个隐藏按钮内部的某个点上是哪个元素。opacity: 0 的按钮回答“clickable”(可点击);visibility: hidden 的按钮则不是。Visible 按钮排在两个空的 150px 位置之后,因为只有 display: none 的按钮把自己的空间让了出来。如果想先淡出再把元素移除,就对 opacity 做动画,并在结束时设置 visibility: hidden。

悬停时淡入淡出

opacity 是做动画开销最小的属性之一,所以它是实现淡入淡出的标准方式。下面是一个在图片上方出现的说明文字:

:focus-within 让使用键盘的用户也能看到说明文字。别忘了上面的表格:说明文字不可见时,仍会被屏幕阅读器读出,对说明文字来说这正是你想要的。

无障碍:变淡的文字会降低对比度

降低 opacity 就会降低对比度。白底上的灰色文字在 opacity: 0.5 时,对比度可能远低于正文所需的 4.5:1。对于次要文字,应该直接选一个对比度达标的颜色,而不是把深色文字调淡。对于禁用的控件,降低不透明度是一种常见的提示,但要同时加上 disabled 属性,这样键盘也无法聚焦到该控件,屏幕阅读器也会把它报告为已禁用。

副作用:层叠上下文

任何小于 1 的 opacity 都会创建一个新的层叠上下文,和 transform 一样。这时具有较高 z-index 的子元素只能在这个变淡的元素内部层叠,无法盖过它外面的元素。如果一个变淡面板里的下拉菜单滑到了另一个元素下面,原因就在这里(z-index 页面讲解了层叠的原理)。

常见错误

  • 为了让卡片背景透明而把整张卡片调淡。 文字也会变淡。在背景上使用 rgb(... / 0.5)。
  • 想让子元素重新变得不透明。 父元素的 opacity 会限制每一个子元素。
  • 只用 opacity: 0 来隐藏元素。 元素仍然能接收点击和焦点。加上 visibility: hidden,或者使用 display: none(pointer-events: none 能阻止点击,但阻止不了键盘焦点)。
  • 写成 opacity: 50。 opacity 的范围是 0 到 1;50 会被限制为 1。应写成 0.5 或 50%。
  • 用 opacity 造成文字对比度过低。 要检查最终效果的对比度,而不是原始颜色的对比度。

常见问题

CSS 中的 opacity 有什么作用?

它设置元素的透明程度,从 0(完全透明)到 1(完全不透明)。它作用于整个元素,包括文字、边框、图片和每一个子元素,把它们当作一个合并后的图层来处理。

如何只让背景透明,而文字不透明?

不要动 opacity,而是给背景设置一个带透明度的颜色:background-color: rgb(37 99 235 / 0.5); 或 rgba(37, 99, 235, 0.5)。文字和子元素会保持完全不透明。

子元素能比父元素更不透明吗?

不能。父元素的 opacity 作用于整组内容,所以在子元素上设置 opacity: 1 无法抵消它。父元素为 0.5 时,子元素最多只能以一半的不透明度绘制。应该改为把透明度放到父元素的背景色上。

opacity: 0、visibility: hidden 和 display: none 有什么区别?

opacity: 0 会隐藏元素,但它仍然占据空间、可以被点击,也会被屏幕阅读器读出。visibility: hidden 保留空间,但不能点击也不会被读出。display: none 则把它从布局中完全移除。

opacity 可以用百分比吗?

可以。在所有当前浏览器中,opacity: 50% 和 opacity: 0.5 效果相同。小于 0 或大于 1 的值会被限制在这个范围内。

Coddy 编程语言插图

和 Coddy 一起学编程

开始