高级样式效果

本文充当一个技巧宝典,介绍了诸如盒阴影、混合模式和滤镜等一些有趣的进阶样式功能。

预备知识 HTML 基础知识(学习 HTML 简介)以及对 CSS 工作原理的了解(学习 CSS 样式基础)。
目标 了解如何在现代浏览器中使用一些高级样式效果。

盒阴影

box-shadow 允许你对元素的盒子应用一个或多个投影。与文本阴影类似,盒阴影在浏览器中的支持度相当好,包括 IE9+ 和 Edge。使用较旧 IE 版本的用户可能不得不接受没有阴影的情况,因此请测试你的设计,确保在没有阴影的情况下内容仍然清晰可读。

一个简单的盒阴影

让我们看一个简单的例子来开始。首先,一些 HTML 代码

html
<article class="simple">
  <p>
    <strong>Warning</strong>: The thermostat on the cosmic transcender has
    reached a critical level.
  </p>
</article>

现在是 CSS 代码

css
p {
  margin: 0;
}

article {
  max-width: 500px;
  padding: 10px;
  background-color: red;
  background-image: linear-gradient(to bottom, transparent, rgb(0 0 0 / 25%));
}

.simple {
  box-shadow: 5px 5px 5px rgb(0 0 0 / 70%);
}

这给了我们以下结果:

你会看到 box-shadow 属性值中有四个项

  1. 第一个长度值是水平偏移——阴影从原始盒子向右偏移的距离(如果值为负,则向左偏移)。
  2. 第二个长度值是垂直偏移——阴影从原始盒子向下偏移的距离(如果值为负,则向上偏移)。
  3. 第三个长度值是模糊半径——应用于阴影的模糊量。
  4. 颜色值是阴影的基色

你可以使用任何有意义的长度和颜色单位来定义这些值。

多个盒阴影

你也可以在单个 box-shadow 声明中指定多个盒阴影,通过用逗号分隔它们

css
p {
  margin: 0;
}

article {
  max-width: 500px;
  padding: 10px;
  background-color: red;
  background-image: linear-gradient(to bottom, transparent, rgb(0 0 0 / 25%));
}

.multiple {
  box-shadow:
    1px 1px 1px black,
    2px 2px 1px black,
    3px 3px 1px red,
    4px 4px 1px red,
    5px 5px 1px black,
    6px 6px 1px black;
}

现在我们得到这个结果

我们通过创建带有多个彩色图层的凸起盒子来做了一些有趣的事情,但你可以以任何你想要的方式使用它,例如创建具有基于多个光源的阴影的更逼真的外观。

其他盒阴影特性

text-shadow 不同,box-shadow 有一个 inset 关键字可用——将其放在阴影声明的开头会导致它成为内阴影,而不是外阴影。让我们来看看这意味着什么。

首先,我们将为此示例使用一些不同的 HTML 代码

html
<button>Press me!</button>
css
button {
  width: 150px;
  font-size: 1.1rem;
  line-height: 2;
  border-radius: 10px;
  border: none;
  background-image: linear-gradient(to bottom right, #777777, #dddddd);
  box-shadow:
    1px 1px 1px black,
    inset 2px 3px 5px rgb(0 0 0 / 30%),
    inset -2px -3px 5px rgb(255 255 255 / 50%);
}

button:focus,
button:hover {
  background-image: linear-gradient(to bottom right, #888888, #eeeeee);
}

button:active {
  box-shadow:
    inset 2px 2px 1px black,
    inset 2px 3px 5px rgb(0 0 0 / 30%),
    inset -2px -3px 5px rgb(255 255 255 / 50%);
}

这给了我们以下结果:

在这里,我们设置了一些按钮样式以及聚焦/悬停/活动状态。默认情况下,按钮上设置了一个简单的黑色盒阴影,以及几个内阴影,一明一暗,放置在按钮的相对角上,以提供漂亮的阴影效果。

当按钮被按下时,活动状态会导致第一个盒阴影被替换为一个非常暗的内阴影,从而产生按钮被按下的外观。

注意:box-shadow 值中还可以设置另一个项——一个可选的长度值可以在颜色值之前设置,即扩散半径。如果设置,这会导致阴影比原始盒子更大。它不常用,但值得一提。

过滤器

虽然你不能使用 CSS 改变图像的构图,但你可以做一些有创意的事情。一个非常好的属性,可以帮助你为你的设计带来兴趣,是 filter 属性。这个属性可以直接从 CSS 启用类似于 Photoshop 的滤镜。

在下面的示例中,我们使用了两个不同的滤镜值。第一个blur()——这个函数可以传递一个值来指示图像应该模糊多少。

第二个是 grayscale();通过使用百分比,我们设置了我们想要去除多少颜色。

在下面的示例中调整百分比和像素参数,看看图像如何变化。你也可以将这些值替换为其他值。在上面的实时示例中尝试 contrast(200%)invert(100%)hue-rotate(20deg)。查看 MDN 上的 filter 页面,了解你可以尝试的许多其他选项。

html
<div class="wrapper">
  <div class="box">
    <img
      alt="balloons"
      class="blur"
      src="https://mdn.github.io/shared-assets/images/examples/balloons.jpg" />
  </div>
  <div class="box">
    <img
      alt="balloons"
      class="grayscale"
      src="https://mdn.github.io/shared-assets/images/examples/balloons.jpg" />
  </div>
</div>
css
img {
  height: 100%;
  width: 100%;
  display: block;
  object-fit: cover;
}

.blur {
  filter: blur(10px);
}

.grayscale {
  filter: grayscale(60%);
}

你可以将滤镜应用于任何元素,而不仅仅是图像。一些可用的滤镜选项与其他的 CSS 功能做着非常相似的事情,例如 drop-shadow() 的工作方式与 box-shadowtext-shadow 类似,并产生相似的效果。然而,滤镜真正好的一点是,它们作用于盒子内部内容的精确形状,而不仅仅是整个盒子作为一个大块,因此了解其中的区别是值得的。

在下一个示例中,我们将滤镜应用于一个盒子,并将其与盒阴影进行比较。如你所见,投影滤镜遵循文本和边框虚线的精确形状。盒阴影只遵循盒子的正方形。

html
<p class="filter">Filter</p>
<p class="box-shadow">Box shadow</p>
css
body {
  font-family: sans-serif;
}
p {
  margin: 1em 2em;
  padding: 20px;
  width: 100px;
  display: inline-block;
  border: 5px dashed red;
}

.filter {
  filter: drop-shadow(5px 5px 1px rgb(0 0 0 / 70%));
}

.box-shadow {
  box-shadow: 5px 5px 1px rgb(0 0 0 / 70%);
}

混合模式

CSS 混合模式允许我们为元素添加混合模式,这些模式在两个元素重叠时指定混合效果——每个像素最终显示的颜色将是原始像素颜色与其下方图层像素颜色组合的结果。混合模式再次让像 Photoshop 这样的图形应用程序用户感到非常熟悉。

CSS 中有两个属性使用混合模式

  • background-blend-mode,它将设置在单个元素上的多个背景图像和颜色混合在一起。
  • mix-blend-mode,它将自身元素与与其重叠的元素(包括背景和内容)混合在一起。

你可以在我们的 blend-modes.html 示例页面(请参阅源代码)以及 <blend-mode> 参考页面上找到比这里更多的示例。

注意:混合模式也非常新,并且支持度略低于滤镜。Edge 尚不支持,Safari 只支持部分混合模式选项。

background-blend-mode

同样,让我们看一些例子,以便更好地理解。首先,background-blend-mode——这里我们将展示几个简单的 <div> 元素,这样你就可以比较原始版本和混合版本

html
<div></div>
<div class="multiply"></div>

现在是一些 CSS——我们正在为 <div> 添加一个背景图像和一个绿色背景颜色

css
div {
  width: 250px;
  height: 130px;
  padding: 10px;
  margin: 10px;
  display: inline-block;
  background: url("colorful-heart.png") no-repeat center 20px;
  background-color: green;
}

.multiply {
  background-blend-mode: multiply;
}

我们得到的结果是这样——你可以看到左边是原始的,右边是乘法混合模式

mix-blend-mode

现在让我们看看 mix-blend-mode。这里我们将展示相同的两个 <div> 元素,但每个元素现在都位于一个带有紫色背景的简单 <div> 之上,以展示元素将如何混合在一起

html
<article>
  No mix blend mode
  <div></div>
  <div></div>
</article>

<article>
  Multiply mix
  <div class="multiply-mix"></div>
  <div></div>
</article>

这是我们将用于样式设置的 CSS

css
article {
  width: 280px;
  height: 180px;
  margin: 10px;
  position: relative;
  display: inline-block;
}

div {
  width: 250px;
  height: 130px;
  padding: 10px;
  margin: 10px;
}

article div:first-child {
  position: absolute;
  top: 10px;
  left: 0;
  background: url("colorful-heart.png") no-repeat center 20px;
  background-color: green;
}

article div:last-child {
  background-color: purple;
  position: absolute;
  bottom: -10px;
  right: 0;
  z-index: -1;
}

.multiply-mix {
  mix-blend-mode: multiply;
}

这给了我们以下结果

你可以看到,乘法混合模式不仅混合了两个背景图像,还混合了其下方 <div> 的颜色。

注意:如果对上面的一些布局属性(如 positiontopbottomz-index 等)不理解,请不用担心。我们将在 CSS 布局模块中详细介绍这些内容。

CSS 形状

虽然 CSS 中的所有内容都是矩形框,图像也是物理矩形框,但我们可以通过使用 CSS Shapes 让内容看起来像是环绕着非矩形对象流动。

CSS Shapes 规范允许文本围绕非矩形形状环绕。当处理具有一些你可能希望文本环绕的空白区域的图像时,它特别有用。

在下面的图片中,我们有一个讨人喜欢的圆形气球。实际文件是矩形的,但是通过浮动图像(形状仅适用于浮动元素)并使用值为 circle(50%)shape-outside 属性,我们可以实现文本沿着气球线条流动的效果。

html
<div class="wrapper">
  <img
    alt="balloon"
    src="https://mdn.github.io/shared-assets/images/examples/round-balloon.png" />
  <p>
    One November night in the year 1782, so the story runs, two brothers sat
    over their winter fire in the little French town of Annonay, watching the
    grey smoke-wreaths from the hearth curl up the wide chimney. Their names
    were Stephen and Joseph Montgolfier, they were papermakers by trade, and
    were noted as possessing thoughtful minds and a deep interest in all
    scientific knowledge and new discovery. Before that night—a memorable night,
    as it was to prove—hundreds of millions of people had watched the rising
    smoke-wreaths of their fires without drawing any special inspiration from
    the fact.
  </p>
</div>
css
body {
  font-family: sans-serif;
}
img {
  float: left;
  shape-outside: circle(50%);
}

此示例中的形状没有对图像文件的内容做出反应。相反,circle 函数从图像文件的中心点获取其中心点,就好像我们在文件的中间放置了一个指南针并绘制了一个适合文件内部的圆。文本就是围绕着这个圆流动的。

注意:在 Firefox 中,你可以使用 DevTools Shapes Inspector 来检查形状。

circle() 函数只是少数几个基本形状中的一个,然而,有多种不同的方法来创建形状。有关 CSS Shapes 的更多信息和示例代码,请参阅 MDN 上的CSS Shapes 指南

-webkit-background-clip: text

我们想简要提及的另一个功能是 background-cliptext 值。当与专有的 -webkit-text-fill-color: transparent; 功能结合使用时,这允许你将背景图像裁剪到元素的文本形状,从而产生一些不错的效果。这不是官方标准,但由于其受欢迎和开发人员的广泛使用,已在多个浏览器中实现。在这种情况下,这两个属性都需要一个 -webkit- 供应商前缀,即使对于非 WebKit/基于 Chrome 的浏览器也是如此。你可以在下面的实时示例中看到它的实际应用

html
<h2>WOW</h2>
<h2 class="text-clip">WOW</h2>
css
h2 {
  color: white;
  display: inline-block;
  background: url("colorful-heart.png") no-repeat center;
}

.text-clip {
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

那么为什么其他浏览器也实现了 -webkit- 前缀呢?主要是为了浏览器兼容性——许多网页开发者已经开始使用 -webkit- 前缀来实现网站,以至于其他浏览器看起来像是损坏了,而实际上它们是遵循标准的。因此它们被迫实现了一些这样的功能。这突显了在你的工作中使非标准和/或带有前缀的 CSS 功能的危险——它们不仅会导致浏览器兼容性问题,而且也可能随时更改,因此你的代码可能随时崩溃。坚持标准要好得多。

如果你确实想在生产工作中使用这些功能,请务必在各种浏览器上进行彻底测试,并检查在这些功能不起作用的情况下,网站是否仍然可用。

总结

我们希望这篇文章很有趣——玩闪亮的玩具通常很有趣,而且看到现代浏览器中正在提供哪些高级样式工具总是很有趣。