用纯 CSS 实现镂空效果

UPDATE 2/26css

如今为示例 CodePen 添加了厂商前缀,并在正文中添加了兼容性提示。感谢评论区的各位。html

近来研究了一下镂空效果。git

background-clip: text

背景被裁剪为文字的前景色。第一次是在 CSS-Tricks 看到的这个用法: 在 CSS-Tricks 网站上,这个玩意用获得处都是。github

这样,作简单的图片背景镂空效果便再也不困难了。关键代码只有几行。web

.wrapper {
  /* ... */
  background-image: url("/path/to/your/image");
  -webkit-background-clip: text;  /* Chrome 用户注意加 -webkit 前缀 */
  background-clip: text;
  color: transparent;             /* 文字设为透明 */
}
复制代码

就这几行,视觉上会就会有大变化。先后对比浏览器

另外,这里有个比上面更实用的 Demoapp

兼容性提示ide

除了 Firefox 和 Edge ,其它浏览器须要配合厂商前缀:svg

-webkit-background-clip: text;
复制代码

background-clip 既然是“background”家族的,那它天生和图片、渐变打的交道多。不过,咱们作镂空总不会都是图片、渐变这种吧。若是咱们想作视频、文字,甚至更复杂的 DOM 元素的镂空效果呢?动画

单刀直入: CSS mask 属性

这应该是最直接能想到的方法了。毕竟名字里就带个“mask”,谁能忽略呢?

CSS mask-* 系列属性是在 CSS Masking Module Level 1 中定义的。这个规范也定义了为不少人熟知的 clipclip-path 属性,换句话说,这个CSS 模块包括遮罩和剪裁两部分。

第一个例子

虽然是一个新的属性,但设置 mask 属性并不难。下面就是咱们的第一个例子。

<div class="masked" />
复制代码
.masked {
  height: 100px;
  width: 100px;
  background: linear-gradient(red, orange, yellow, lightgreen, blue, purple, red);
  -webkit-mask: url("https://github.githubassets.com/pinned-octocat.svg");
  mask: url("https://github.githubassets.com/pinned-octocat.svg");
}
复制代码

就是下面的效果啦。

上面的用法仍是很简单的,咱们指定了一个 mask 参数,它的值是一张从GitHub盗的SVG图片。因而多彩的渐变就被裁剪遮罩成了那只著名的猫。

兼容性提示

目前 Mask Module 还处于 Candidate Recommendation 状态,很多浏览器如今须要厂商前缀。Chrome 用户和 Edge 用户请加上 -webkit 前缀,如 -webkit-mask: ... ;。Firefox 可直接使用。

从Can I Use 能够知道,加上 -webkit,支持 Mask 的浏览器仍是很多的。

为了方便阅读,下面的代码 均未 使用前缀

mask-* 你们族

mask属性其实是诸多mask-*的缩写:

mask-image
mask-repeat
mask-position
mask-clip
mask-origin
mask-size
-
mask-type
mask-composite
mask-mode
复制代码

有没有 background-* 的即视感?没错,里面的很多属性都是和 backgorund / border 一致的,并且它们的做用也是一致的,只不过 background-* 用在背景上,而 mask-* 用在遮罩层上而已——用在背景上的奇技淫巧搬到 mask 的世界里还能接着用!好比实现这样的效果:

.masked {
  height: /* ... */;
  width: /* ... */;
  background: /* ... */;
  /* Webkit 内核用户请注意添加厂商前缀 -webkit */
  mask-image: url(https://github.githubassets.com/pinned-octocat.svg);
  mask-size: 5em;
  mask-position: center;
  /* 若是你心情好,加个动画也没问题的 */
}
复制代码

进一步控制遮罩效果

可能读者已经发现了,mask-* 家族里有几张生面孔。这也好理解: mask 这么强大的特性,完彻底全地抄 background-* 岂不惋惜了。

mask-mode

mask-mode 用来指定具体的遮罩方式。

兼容性预警:目前 mask-mode 仅 Firefox 53+ 支持。

mask-type CSS 属性设置 mask-image 被用于“亮度型”的遮罩仍是“不透明度”型的遮罩。mask-mode: alaph 表示使用不透明度(即alaph通道)做为 mask value,mask-mode: luminance 表示使用亮度值做为 mask value。

那,遮罩值 / mask value 又是什么?mask value 表示被遮罩的元素被遮罩的程度。mask value 越大,被遮罩区域会更偏向于显露,mask value 最大的时候,那个区域就彻底不透明了。举个例子:

<div class="mode">ABCDEFG</div>
复制代码
.mode {
  height: 200px;
  width: 300px;
  /* and more */
  mask-image: linear-gradient(to left, black, yellow);
  mask-mode: luminance; /* or alaph ? */
}
复制代码

左边是遮罩图片,中间是 luminance 右边使用 alaph。这里的图片是不透明的,因此将一个恒不透明的图片在alaph模式下做为遮罩,其结果是没有遮罩效果。可是图片是有亮度变化的,因此luminance下的被遮罩元素就呈现出透明度的变化了。

通常 luminance 模式慢一点点,由于每个像素点的亮度值须要根据 RGB 三个通道的值计算出来。

mask-composite

指定当有多个遮罩图片叠加起来的时候,如何处理遮罩效果。一些属性值的效果依赖于 mask-image 的层级次序。

MDN 提供的这个 CodePen 来感觉一下

关于 mask 的知识就讲到这里,更具体更准确的说明仍是要到 MDN 看一看

混合模式

这应该是最为神奇的一种方法了。使用PS的时候,常常会看见“混合模式”这个词。还记得多年前我初次使用 Photoshop 的时候还很好奇“混合模式”是什么东西,顿时让我对 Photoshop 充满了敬畏之情。不过,当年的敬畏归敬畏,如今这里说的“混合模式”仍是蛮好理解的。

所谓的“混合模式”,是指当一种当层重叠时计算像素最终颜色值的方法。每种混合模式接收前景颜色值和背景颜色值(分别为顶部颜色和底部颜色)做为输入,执行一些计算并输出最后要显示在屏幕上的颜色值。最终的可见的颜色是对层中的每一个重叠像素执行混合模式计算所得的结果。说白了,混合模式肯定了把一层叠加到另外一层上去会获得什么结果。

在 CSS 中,可使用 mix-blend-mode 来指定混合模式。

你可能会问了,平时也没有用什么“混合模式”这种东西,因此blend-mode的默认值是none吗?可不是。其实,这种最多见的 上层把下层“遮住”了的状况也属于一种混合模式,叫normal,它本质上是一种只保留前景颜色值而彻底抛弃背景颜色值的混合模式。

这里咱们只讨论实现镂空效果用到的混合模式 —— screen。这种混合模式有一个特性,前景层是黑色致使最终可见的颜色直接是背景层的颜色,前景层是白色致使最终可见的颜色直接是白色。

相信你已经搞不明白这和镂空有什么关系了,下面举个例子看一下。

如今,咱们有一个<video>,以及一个“白底黑字”的Logo浮层。

咱们在浮层框上加上下面的 CSS:

.logo {
    /* ... ... */
    mix-blend-mode: screen;
}
复制代码

就变成了下面的样子:

去这个 Demo,看具体代码和效果

齿轮图标确实是变为镂空的了。不过,为何呢?

先来明确一件事:把浮层置于视频之上,浮层是“前景”,视频是“背景”。先来看浮层的白色部分,由于把白色置于任何颜色之上都获得白色,因此白色部分被保留;而由于黑色置于任何颜色之上都获得下层的颜色,因此黑色部分呈现镂空效果。

可是这样的实现比较 Hack,由于这里只使用了黑白两色,若是使用其它的颜色做为浮层的 background-color,获得的就不会像是镂空的效果了,这时仍是得请上面的mask家族出场。不过,单单对于白底的状况,mix-blend-mode 不失为一个可行的解法。

相关文章
相关标签/搜索