使用纯 CSS 创建多彩且智能的阴影
几天前,我在家得宝(我的大女儿又名玩具反斗城[1])发现他们有一个巨大的显示屏,展示所有这些彩色灯泡待售! 其中一个项目是位于电视旁边的一组智能灯泡。 它们在电视正面投射与电视所显示内容近似的彩色阴影,类似于以下内容 [2]:
注意电视旁边发生的事情。 屏幕上显示的颜色由灯泡投射为电视机身旁边的彩色阴影。 当屏幕上的颜色发生变化时,背景中投影的颜色也会发生变化。 真的很酷,对吧?
当然,听到这个,我的第一个想法是我们是否可以使用网络技术来创建足够智能的彩色阴影来模仿以前的景观。 事实证明,我们可以完全仅使用 CSS 来构建这个示例。 在本文中,我们将了解如何创建这些效果。
我们走吧!
使它成为现实!
正如您将在以下部分中看到的,使用 CSS 创建这些彩色阴影需要大量工作(实际上css背景色透明,这只是开始)。 当我们开始踏入其中,将这个艰巨任务的核心分解成一个个小任务时,我们可能还会发现,要达到这种治疗效果显然是相当简单的。 在接下来的几节中,我们将创建以下示例:
您应该听到的是一张拉面的图片,旁边有彩色的阴影。 (只是为了指出我们正在做这一切,我们正在向阴影添加脉冲动画效果)抛开示例,让我们深入研究实现,看看 HTML 和 CSS 如何实现这一点!
展示我们的照片
不过,用于显示拉面图片的 HTML 并没有什么特别之处:
<div class="parent">
<div class="colorfulShadow sushi"></div>
</div>
我们有一个父 div 元素,其中包含一个负责显示拉面的子 div 元素。 我们显示拉面的方式是将其指定为背景图像,并按以下 .sushi 样式规则处理:
.sushi {
margin: 100px;
width: 150px;
height: 150px;
background-image: url("https://www.kirupa.com/icon/1f363.svg");
background-repeat: no-repeat;
background-size: contain;
}
在此样式规则中,我们将 div 的大小指定为 150x150 像素,并在其上设置背景图像和其他相关属性。 就目前情况而言,我们看到的 HTML 和 CSS 会给我们这样的东西:
现在是影子时间
现在我们的图像就在那里,剩下的就是定义阴影的有趣部分了。 我们定义阴影的方法是指定一个子伪元素(使用 ::after ),它将执行三件事:
直接位于我们的图像旁边;
继承与父元素相同的背景图片;
使用滤镜实现多彩的阴影效果;
这三件事是通过以下两个样式规则完成的:
.colorfulShadow {
position: relative;
}
.colorfulShadow::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
background-position: center center;
filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.50)) blur(20px);
z-index: -1;
}
让我们花点时间看看这里发生了什么:首先注意每个属性及其相应的值,有一些值得注意的属性 - 背景和过滤器。 背景属性使用inherit继承父元素,也就是说可以继承父元素的背景:
.colorfulShadow::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
background-position: center center;
filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.50)) blur(20px);
z-index: -1;
}
我们为filter属性定义了两个滤镜属性,分别是drop-shadow和blur:
.colorfulShadow::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
background-position: center center;
filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.50)) blur(20px);
z-index: -1;
}
我们的投影滤镜设置为显示不透明度为 50% 的红色阴影,而我们的模糊滤镜会将伪元素模糊 20 像素。 这两个滤镜的组合最终创建了彩色阴影,当应用这两个样式规则时,该阴影现在将出现在我们的拉面图像前面:
至此,我们已经实现了智能阴影。 为了完整起见,如果我们想要一个带有彩色阴影缩放的动画,可以添加以下 CSS:
.colorfulShadow {
position: relative;
}
.colorfulShadow::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
background-position: center center;
filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.50)) blur(20px);
z-index: -1;
/* animation time! */
animation: oscillate 1s cubic-bezier(.17, .67, .45, 1.32) infinite alternate;
}
@keyframes oscillate {
from {
transform: scale(1, 1);
}
to {
transform: scale(1.3, 1.3);
}
}
您还可以使用 CSS 过渡来修改阴影在单个操作(例如悬停)上的行为方式,以防您想要一些交互性而不需要无限循环的动画。 困难的部分是像处理 HTML 中显式定义的或使用 JavaScript 动态创建的任何其他元素一样处理伪元素。 唯一的区别是伪元素完全使用 CSS 创建!
推理
伪元素允许我们使用 CSS 来完成一些元素创建任务,这些任务历来是 HTML 和 JavaScript 的领域。 对于我们多彩且智能的阴影css背景色透明,我们可以使用父元素来设置背景图像。 这使得我们可以轻松地定义一个子伪元素,它不仅继承了父元素的背景图像细节,还允许我们在其上设置一系列属性来实现模糊和阴影效果。 虽然这一切都很好,而且我们已经最大限度地减少了大量的复制和粘贴,但这种方式不太灵活。
如果我想将这样的阴影应用于不只有背景图像的空元素怎么办? 如果我有一个像 Button 或 ComboBox 这样的 HTML 元素,我想要应用这些阴影效果,该怎么办? 一种解决方案是借助 JavaScript 在 DOM 中复制适当的元素,将它们放置在前景元素下方,应用过滤器,然后就可以了。 即使它有效,考虑到过程的复杂性,这还是有点令人不寒而栗。 可惜 JavaScript 没有等效的 renderTargetBitmap[3] API 来将我们的视觉效果渲染为位图,然后你就可以做任何你想做的事情......
以上内容是译文的翻译,以下是一些扩展:
扩张
说实话,我们可能不需要那么复杂的内容。 图片可以是任意的,比如PNG、SVG。 最后简化后,HTML代码只是任意元素,附加样式来指定图片的地址和大小:
<div class="shadowedImage" style="--data-width: 164px; --data-height: 48px; --data-image: url('https://sf3-scmcdn2-tos.pstatp.com/xitu_juejin_web/dcec27cc6ece0eb5bb217e62e6bec104.svg');"></div>
CSS代码如下:
.shadowedImage {
position: relative;
margin: 100px;
width: var(--data-width);
height: var(--data-height);
max-height: 150px;
background-image: var(--data-image);
background-repeat: no-repeat;
background-size: contain;
}
.shadowedImage::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
background-position: center center;
filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.50)) blur(20px);
z-index: -1;
}
示例代码
示例代码如下:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.shadowedImage {
position: relative;
}
.shadowedImage::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
background-position: center center;
filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.50)) blur(20px);
z-index: -1;
/* animation time! */
animation: oscillate 1s cubic-bezier(.17, .67, .45, 1.32) infinite alternate;
}
@keyframes oscillate {
from {
transform: scale(1, 1);
}
to {
transform: scale(1.1, 1.1);
}
}
.shadowedImage {
margin: 100px;
width: var(--data-width);
height: var(--data-height);
max-height: 150px;
background-image: var(--data-image);
background-repeat: no-repeat;
background-size: contain;
}
</style>
</head>
<body>
<div class="parent">
<div class="shadowedImage" style="--data-width: 164px; --data-height: 48px; --data-image: url('https://sf3-scmcdn2-tos.pstatp.com/xitu_juejin_web/dcec27cc6ece0eb5bb217e62e6bec104.svg');"></div>
<div class="shadowedImage" style="--data-width: 164px; --data-height: 164px; --data-image: url('https://sf1-dycdn-tos.pstatp.com/img/bytedance-cn/4ac74bbefc4455d0b350fff1fcd530c7~noop.image');"></div>
<div class="shadowedImage" style="--data-width: 164px; --data-height: 164px; --data-image: url('https://sf1-ttcdn-tos.pstatp.com/img/bytedance-cn/4bcac7e2843bd01c3158dcaefda77ada~noop.image');"></div>
</div>
</body>
</html>
功效示例
疗效如下:
参考
[1]
[2]
[3]
译者:雄鹿 - 霜羽 Hoarfroster
-EOF-
发表评论