深入阴影

Avatar of Rob O'Leary
Rob O'Leary

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

让我们来谈谈网页设计中的阴影。阴影增添纹理、透视感并强调物体的维度。在网页设计中,使用光影可以增加物理真实感,并用于制作丰富、触觉化的界面。

以下面的登陆页面为例。它是冰岛自行车游的登陆页面。请注意自行车运动员的装饰性投影阴影,以及它是如何让人感觉他们不仅飞越页面上的内容,而且飞越页面本身,仿佛他们“弹出”屏幕。这种感觉充满活力和即时性,非常适合冒险主题。

A view of a BMX biker from above leaping over a vast area of light brown land with the words free ride along the bottom edge in large, bold, and white block lettering.
来源:Kate Hahu

将其与下面的例子进行比较。这是一个“扁平化”的设计,没有阴影。在这种情况下,自行车本身是焦点。缺乏深度和真实感可以让自行车本身脱颖而出。

Screenshot of a webpage with a light pink background with a white box that contains the site content with a headline that reads "Ride as Much or as Little" in red, an email subscription form, and a large image of a red and white bicycle to the right.
来源:saravana

您可以欣赏这两种方法之间的差异。使用阴影和深度是一种设计选择;它们应该支持主题以及您希望内容传达的信息。

光与影

正如我们刚才看到的,深度可以增强内容。那么究竟是什么造就了阴影呢?光!

谈论阴影而不谈光是不可能的。它控制着阴影的方向以及阴影的深浅。两者缺一不可。

Google 的 Material Design 设计系统是有效运用光影的一个很好的例子。您肯定遇到过 Material Design 的美学,因为 Google 将其应用于几乎所有产品。

A masonry grid of photos on a mobile screen. The purple header that contains the page title and hamburger menu has a shadow along its bottom edge that separates it from the white background of the photos.
White modal with a list of checkboxes. The modal has an underlying black shadow against the background.
A two-by-three grid of cards on a mobile screen. Each card has a light shallow shadow against a white background.

该设计系统借鉴了物理世界,并使用光、表面和投影阴影在三维空间中表达界面。他们关于使用光影的指南 详细介绍了这一点。

在 Material Design 环境中,虚拟光线照亮 UI。关键光线产生更锐利、有方向性的阴影,称为关键阴影。环境光从各个角度出现,产生漫射的、柔和的阴影,称为环境阴影。

阴影是 Material Design 的核心组成部分。将其与 Apple 的 macOS 人机界面指南 进行比较,在 macOS 中,半透明和模糊是唤起深度的主要因素。

Screenshot of Apple's Reminders app on a desktop. The left column that contains search and navigation is opaque and blends lightly into the desktop background while the solid white right column contains a checkbox list of reminders.
Screenshot of Apple's Maps app. The left column contains the map addresses and different route options with an opaque background that lightly blends in with the desktop background. The right column contains the map and does not blend in with the background.

在这种情况下,光仍然是一个有影响力的因素,因为它允许元素融入桌面,甚至融入 UI 中的其他面板。同样,在您的界面中使用它也是一种设计选择。无论哪种方式,您都可以看到光如何影响对深度的视觉感知。

光源和颜色

现在我们已经理解了光与阴影之间的关系,我们应该更深入地了解光是如何影响阴影的。我们已经看到光线的强度是如何产生不同深度的阴影的。但关于光线影响阴影的**方向**和**颜色**的方式,还有很多值得探讨。

当光线照射到物体上时,会产生两种阴影,即**投影阴影**和**形体阴影**。

Photo of an orange with light shining on it from the top right. That area is brighter than the left side which is covered in shadow. The ground contains a light reflection of the orange.

投影阴影

当物体阻挡光源时,就会产生**投影阴影**。投影阴影的色调和明暗度可能有所不同。颜色术语可能很密集且令人困惑,所以让我们先谈谈**色调**和**明度**。

色调是色相与灰色的混合。明度描述了颜色的整体亮度或暗度。明度在绘画中非常重要,因为它是在艺术家将光线和物体关系转换为颜色的过程中使用的。

Illustration showing the effects of Hue, Tint, Tone, and Shade on red rectangles. Each rectangle is a slightly different shade of red where tint adds white, tone adds gray and shade adds black.

在网页设计领域,这些颜色的方面是颜色选择器 UI 的内在组成部分。

形体阴影

另一方面,**形体阴影**是指物体背对光源的一侧。形体阴影的边缘比投影阴影更柔和、更不清晰。形体阴影说明了物体的体积和深度。

阴影的外观取决于光线的方向、光线的强度以及物体与阴影投射到的表面之间的距离。光线越强,阴影越深越锐利。光线越柔和,阴影越暗淡越柔和。在某些情况下,对于方向光,我们会得到两个不同的阴影。本影是光线被遮挡的地方,半影是光线被散射的地方。

Two vertically stacked illustrations.The top is a green circle with a yellow light source coming at it from the left and both umbra and penumbra shadows are cast to the right. The bottom illustration is the same green circle and light source, but with a solid black shadow cast to the right.

如果表面靠近物体,阴影会更锐利。如果表面距离较远,阴影会更暗淡。这并不是什么抽象的科学内容。这是我们每天都会遇到的东西,无论你是否意识到它。

This stuff comes up in just about everything we do, even when writing with a pencil.

光线也可能从物体的侧面或其他表面反射。明亮的表面反射光线,黑暗的表面吸收光线。

这些是理解网页设计中最有价值的光线方面。光线的物理学是一个复杂的话题,我在这里只是简单地提到了其中的一些。如果您想查看基于不同光源投射的阴影的明确示例,这份关于漫画阴影绘制的指南 很有指导意义。

光源定位

请记住,阴影与光线密不可分,因此定义光源——即使实际上不存在光源——是创造令人印象深刻的阴影效果的方法。诀窍是根据光源始终如一地添加阴影。位于元素上方的光源会在元素下方投射阴影。将光源置于元素左侧会在右侧投射阴影。将多个光源置于元素的顶部、底部、左侧和右侧实际上根本不会投射阴影!

Showing two browser mockups side by side. The left has light shining on it from all four directions showing uniform light and no shadows. The right has a single light source from the top casting a shadow along the bottom edge.

光源可以投射到您选择的任何方向。只需确保在您的设计中始终如一地使用它,以便一个元素上的阴影与页面上的其他阴影相匹配。

海拔高度

阴影还可以传达**海拔高度**。再次以 Material Design 为例,因为它展示了如何使用阴影在元素之间创建感知的分离。

Showing a mobile screen flat on a light blue background with header, box, and navigational elements elevated over the screen showing depth.
来源:Nate Wilson

内阴影

说到海拔高度,box-shadow 属性是唯一可以为下沉效果创建内阴影的属性。因此,元素看起来不是向上提升,而是被压入。这要归功于inset关键字。

这对于诸如单击按钮时看起来物理上按下按钮的效果很有用。

也可以使用一些技巧“伪造”内文字阴影,这些技巧在大多数浏览器中都得到了支持。

阴影分层

我们并不局限于每个元素只有一个阴影!例如,我们可以在box-shadow属性上提供一个用逗号分隔的阴影列表。我们为什么要这样做呢?其中一个原因是为了创建更平滑的阴影。

另一个原因是为了创建有趣的视觉效果。

阴影分层甚至可以使用text-shadow属性来增强排版效果。

需要注意的是,对于filter: drop-shadow(),阴影分层的方式略有不同。它的语法也接受列表,但使用空格分隔而不是逗号分隔。

.box {
  box-shadow: 
    0 2px 2px #555, /* commas */
    0 6px 5px #777,
    0 12px 10px #999
  ;
}

.box {
  filter:
    drop-shadow(0 2px 2px #555) /* spaces */
    drop-shadow(0 6px 5px #777)
    drop-shadow(0 12px 10px #999);
}

还有一点?阴影会叠加在一起,按照声明的顺序排列,其中最上面的阴影是列表中的第一个。

Two vertically stacked examples showing a white circle with a yellow and a grey circle behind it and the CSS code snippets that create the effect. On the top, the gray shadow is above the yellow shadow. On the bottom, the yellow shadow is above the gray shadow.

你可能已经猜到drop-shadow()在这里的工作方式有点不同。阴影呈指数级增加,即2^阴影数量 - 1

以下是它的工作原理

  • 1 个阴影 = (2^1 – 1)。渲染一个阴影。
  • 2 个阴影 = (2^2 – 1)。渲染三个阴影。
  • 3 个阴影 = (2^3 – 1)。渲染七个阴影。

或者,用代码表示

.one-shadow {
  filter: drop-shadow(20px 20px 0 grey);
}

.three-shadows {
  filter: 
    drop-shadow(20px 20px 0 grey)
    drop-shadow(40px 0 0 yellow);
}

.seven-shadows {
  filter: 
    drop-shadow(20px 20px 0 grey)
    drop-shadow(40px 0 0 yellow);
    drop-shadow(80px 0 0 red);
}

<feDropShadow>元素对 SVG 的工作方式完全相同。

阴影和可访问性

以下是一些需要思考的内容:阴影可以帮助提高可访问性。

Google 进行了一项针对低视力参与者的研究,以更好地了解阴影和轮廓如何影响个人识别和交互组件的能力。他们发现,使用阴影和轮廓

  • 增加了在扫描页面时查找组件的便捷性和速度,并且
  • 提高了用户确定组件是否可交互的能力。

那不是一项广泛的科学研究,所以让我们转向看看 W3C 在其针对WCAG 2.0 标准的指南中怎么说

[...] 设计师可能会使字母后面的背景变暗,或在字母周围添加一个细黑色轮廓(至少 1 个像素宽),以使字母与背景之间的对比度比率保持在 4.5:1 以上。

这指的是浅色背景上的浅色文本。WCAG 建议文本和图像之间的对比度比率至少为 4.5:1。您可以使用文本阴影来增加它们之间的对比度。

照片来源:Woody Van der Straeten

阴影和性能

在深入研究阴影并在所有事物上添加阴影之前,值得注意的是它们确实会影响性能。

例如,filter: drop-shadow会被一些浏览器硬件加速。可能会为该元素创建一个新的合成层,并卸载到 GPU。您不希望有太多层,因为这会占用有限的 GPU 内存,并最终导致性能下降。您可以在浏览器的 DevTools 中评估这一点。

模糊是一项代价高昂的操作,因此请谨慎使用。当您模糊某些内容时,它会混合输出像素周围所有像素的颜色以生成模糊的结果。例如,如果您的<blur-radius>参数为 2px,则过滤器需要查看每个输出像素周围每个方向的两个像素以生成混合颜色。这会针对每个输出像素发生,这意味着大量的计算呈指数级增长。因此,具有较大模糊半径的阴影通常比其他阴影渲染速度慢。

您知道吗?

您知道阴影不会影响文档布局吗?

阴影与目标元素的大小相同。您可以修改box-shadow的大小(通过扩展半径参数),但其他属性无法修改阴影大小。

您是否知道阴影的z-index隐式地低于元素?这就是为什么阴影位于其他元素下方。

剪辑和蒙版呢?如果具有box-shadow的元素被剪辑(使用clip-path)或使用蒙版(使用mask),则不会显示阴影。相反,如果具有text-shadowfilter: drop-shadow()的元素被剪辑,则会显示阴影,只要它在剪辑区域内即可。

还有一个:我们无法使用阴影属性创建斜阴影(带有对角线)。这需要创建一个阴影元素并在其上使用transform:skew()

哦,还有一个:box-shadow遵循border-radius。如果元素具有圆角,则阴影也会是圆角。换句话说,阴影会镜像盒子的形状。另一方面,filter: drop-shadow()可以创建不规则形状,因为它会尊重透明度并遵循内容的形状。

Showing two of the same card component side-by-side. They are brightly colored with a background gradient that goes from red to gold. The Nike logo is at the top, a title is below it, then a paragraph of white text beneath that. A red show with an exaggerated shadow is on both cards. The cards illustrated the difference between box shadow, which follows the boundaries of the card's edges, and drop shadow, which includes the shape of the shoe outside the card boundary.

不同类型阴影的最佳使用场景

实际上,网络上的任何内容都可以拥有阴影,并且有多个 CSS 属性和函数可以创建阴影。但是,选择正确的阴影类型才能使阴影有效。

让我们评估一下选项

  • box-shadow:此 CSS 属性创建符合元素边界框的阴影。它用途广泛,可以用于从卡片到按钮到几乎任何需要阴影简单地遵循元素框的地方。
  • text-shadow:这是一个 CSS 属性,专门为文本元素创建阴影。
  • filter: drop-shadow():此处的 CSS 属性是filter,但创建阴影的是它接受的drop-shadow函数。使这种类型的阴影与例如box-shadow不同的原因在于,它遵循任何元素(包括伪元素)的渲染形状。
  • <feDropShadow>:这实际上是一个 SVG 元素,而其余的是 CSS 属性。因此,您将使用它在 SVG 标记中直接创建投影。

一旦您掌握了不同类型的阴影以及每种阴影的独特阴影创建能力,阴影效果的可能性就会变得无限。从简单的投影到浮动元素,甚至内部阴影,我们都可以创建有趣的视觉效果,为 UI 添加额外的意义或价值。

文本阴影也是如此。

现实中的阴影

阴影无处不在。我们一直看到它们以新的、有趣的方式被使用。

您最近是否听说过流行词“拟态设计”?这都与阴影有关。以下是 Maria Muñoz 的一个实现

Yuan Chuan,他创作令人惊叹的生成艺术,称阴影为 UI 设计中的秘密武器

CSS 依赖于浏览器中现有的 DOM 结构。除了::before::after之外,无法生成新的元素。有时我真的希望 CSS 能够直接做到这一点。

然而,我们可以通过完全在 CSS 中创建各种阴影和渐变来部分弥补这一点。

这就是为什么拥有drop-shadow如此令人兴奋的原因。结合text-shadowbox-shadow,我们可以做更多的事情。

看看他是如何使用投影来创建复杂的图案的。

是的,这很疯狂。说到疯狂,值得一提的是,变得过于疯狂会导致性能下降,因此请谨慎操作。

伪元素呢?

哦,是的,阴影属性受::before::after伪元素的支持。

其他尊重阴影的伪元素?::first-letter伪元素接受box-shadowtext-shadow::first-line伪元素接受text-shadow

看看 Jhey Tompkins 如何在伪元素上使用box-shadow来创建动画加载器,非常有创意。

阴影动画

是的,我们可以让它们动起来!我们这里介绍的属性和函数完全兼容 CSS 动画和过渡。这意味着我们可以移动阴影、模糊阴影、扩展/缩小阴影(使用box-shadow)以及改变颜色。

阴影动画可以为用户提供一个提示,表明某个元素是交互式的,或者某个操作已经发生。我们在之前的按钮示例中看到,inset阴影表明按钮已被按下。另一种常见的动画模式是在悬停时提升卡片。

如果想要优化动画性能,避免对box-shadow进行动画!对drop-shadow()进行动画的性能更高。但是,如果想要最流畅的动画,使用一个小技巧是最佳选择!添加一个带有更大box-shadow::after伪元素,并对其opacity进行动画。

当然,还有很多其他的东西可以进行动画。我将把探索留给你们!

总结

哇,谁知道像 CSS 阴影这样看似“简单”的东西竟然有这么多内容!有光源和阴影的投射方式。不同类型的阴影及其颜色。有使用阴影来营造深度、提升元素和内嵌元素。还有将阴影叠加在其他阴影上的事实。以及我们有一系列 CSS 属性可用于不同的用例。然后,还有随之而来的可访问性和性能影响。而且,嘿,动画也是一回事!这真是太不可思议了!

无论如何,希望这个广泛的概述能让你有所收获,或者至少能帮助你复习一些概念。