如何利用 box-shadows 创建手风琴悬停效果
本教程最初发布在fossheim.io上。
在本教程中,我们将使用该box-shadow
属性创建分层卡片组件,并在悬停时为其设置动画。
box-shadow 属性解释
要向框添加阴影,我们需要在box-shadow
属性中指定几项:
x-offset
:x 轴上的位置。正值表示阴影向右移动,负值表示阴影向左移动。(必填)y-offset
:y 轴上的位置。正值表示阴影向下移动,负值表示阴影向上移动。(必需)blur
:阴影的模糊程度。值越高,阴影越柔和。默认值为 0px,表示无模糊。(可选)spread
:阴影相对于组件的放大倍数。正值表示阴影大于框,负值表示阴影小于框。(可选)color
:阴影的颜色。默认值为文本颜色。(可选,Safari 浏览器必需)inset
:阴影的位置。默认情况下,阴影位于框外。设置 inset 可将其移至框内。(可选)
box-shadow: [x-offset] [y-offset] [blur] [spread] [color] [inset];
例如:
你可以在W3Schools或css-tricks上阅读更多关于 box-shadows 的内容。我的纯 CSS 宝丽来相机也是用 box-shadows 做的。
卡片组件
我们不需要编写任何额外的 HTML 代码来在背景中添加堆叠卡片。我们将从以下代码开始我们的教程:
<div class="card">
<p>Similar post</p>
<h2>How I recreated a Polaroid camera with CSS gradients only</h2>
</div>
将卡片转化为阴影
我们希望在组件后面堆叠 4 张卡片,每张卡片具有相同的边框宽度(3px)和相同的背景(白色),但位置和边框颜色不同。
这意味着我们需要绘制 8 个阴影:每个颜色/边框一个,每个白色填充一个。
添加第一张背景卡
我们首先在组件后面添加第一个绿色网格。我们来看看它的要求:
- 向右移动 10px
- 向顶部移动 10px
- 无模糊
- 与容器尺寸相同(无扩散)
- 绿色(#5CBD3F)
转换成 CSS 如下:
box-shadow: 10px -10px 0 0 #5CBD3F;
结合阴影来创建填充和边框
接下来,我们必须在绿色阴影上方绘制一个白色阴影,以模仿盒子的白色填充。
边框的宽度应该是 3px,所以白色阴影应该比两侧的彩色阴影小 3px。我们可以通过设置负的 spread 来实现:
box-shadow: 10px -10px 0 -3px white;
当添加多个阴影时,列出的第一个阴影将渲染在最上面。所以我们的代码现在看起来像这样:
box-shadow: 10px -10px 0 -3px white, 10px -10px 0 0 #1FC11B;
对其他颜色重复相同的过程三次,并继续将阴影向上和向右移动 10px。
box-shadow: 10px -10px 0 -3px white, 10px -10px 0 0 #1FC11B, /* Green */
20px -20px 0 -3px white, 20px -20px 0 0 #FFD913, /* Yellow */
30px -30px 0 -3px white, 30px -30px 0 0 #FF9C55, /* Orange */
40px -40px 0 -3px white, 40px -40px 0 0 #FF5555; /* Red */
添加悬停动画
现在设计已经完成,剩下要做的就是添加悬停动画。
所有卡片都必须从其原始位置移动到后面红色卡片的位置。第一步是更改组件的位置。
.card {
position: relative;
top: 0;
left: 0;
transition: left 1s, top 1s;
}
.card:hover {
top: -40px;
left: 40px;
}
由于偏移量保持不变,阴影仍然会随组件一起移动。所有阴影都必须移动到与盒子相同的位置,这意味着它们的水平和垂直偏移量必须设置为 0。
.card {
position: relative;
top: 0;
left: 0;
transition: box-shadow 1s, left 1s, top 1s;
}
.card:hover {
box-shadow: 0 0 0 -3px white, 0 0 0 0px #1FC11B,
0 0 0 -3px white, 0 0 0 0px #FFD913,
0 0 0 -3px white, 0 0 0 0px #FF9C55,
0 0 0 -3px white, 0 0 0 0px #FF5555;
top: -40px;
left: 40px;
}
这给了我们期望的最终结果: