阴影的几种实现方式你都会了吗说到前端阴影,大家肯定会第一时间想到box-shadow,一个CSS轻松搞定,但是本文要说的
说到前端阴影,大家肯定会第一时间想到box-shadow,一个CSS轻松搞定,但是本文要说的不止box-shadow,主要介绍5种实现方式之间的特性和差异。
现有如下HTML结构
<div class="wrapper">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block">未来可期</div>
<div class="block"></div>
<div class="block">
<div class="image-move">未来可期</div>
<div class="image-move shadow">未来可期</div>
</div>
</div>
<style>
* {
box-sizing: border-box;
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: auto;
}
.wrapper {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.block {
flex: 0 1 auto;
position: relative;
width: 150px;
height: 150px;
margin: 50px;
}
</style>
1、box-shadow
众所周知的CSS属性,但是作为对比,还是简单介绍一下
/* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影扩散半径 | 阴影颜色 | 阴影位置 */
box-shadow: 10px 10px 20px 5px rgba(0, 0, 0, 0.5) inset;
/* 多个阴影用英文逗号隔开 */
box-shadow: 10px 10px 20px 5px rgba(0, 0, 0, 0.5) inset, 0px 0px 30px red;
box-shadow共有6个可设置属性值,除了x偏移量、y偏移量是必填的,其他都是选填。
1)以下CSS,会将第1个.block元素渲染为
.block:nth-child(1) {
box-shadow: inset 16px 16px 20px red;
}
2)以下CSS,会将第2个.block元素渲染为
.block:nth-child(2) {
box-shadow: 16px 16px 20px red;
}
.block:nth-child(2)::after {
content: '';
display: block;
width: 20px;
height: 220px;
margin: auto;
background: yellow;
}
以上效果,::after
伪元素虽然在.block元素内,但是不会产生阴影效果,因为box-shadow只作用于目标元素,不会对子元素产生任何影响。
2、filter: drop-shadow
drop-shadow的属性值跟box-shadow大体上一样,不同的地方在于drop-shadow没有inset和阴影扩散半径,所以drop-shadow的取值如下
/* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影颜色 */
filter: drop-shadow(10px 10px 20px rgba(0, 0, 0, 0.5));
/* 多个阴影用空格隔开 */
filter: drop-shadow(10px 10px 20px rgba(0, 0, 0, 0.5)) drop-shadow(12px 12px 30px red);
以下CSS,会将第3个.block元素渲染为
.block:nth-child(3) {
background: blue; /* 没有非透明值则drop-shadow不会生效 */
filter: drop-shadow(16px 16px 20px red);
}
.block:nth-child(3)::after {
content: '';
display: block;
width: 20px;
height: 220px;
margin: auto;
background: yellow;
}
以上效果,虽然没有给::after
伪元素声明任何阴影,但是仍然会有阴影效果,可以将drop-shadow理解成投影,drop-shadow作用的元素及其子孙元素,只要产生新的边界的,一定会有投影,比如上面黄色的模块,在蓝色模块内交集的地方并没有产生阴影,只在蓝色模块之外产生了阴影,这也是drop-shadow和box-shadow不同的地方。并且对比前面的box-shadow,一样的阴影属性值(16px 16px 20px red
),drop-shadow的阴影效果更淡、更扩散些。
假如我们把黄色::after元素设置marign-left: 200px
移出蓝色模块之外,则会产生如下效果
综合上面几点,drop-shadow跟box-shadow不同的点在于
-
drop-shadow
没有阴影扩散半径和inset设置,box-shadow
有; -
drop-shadow
作用的元素,只要该元素及其子孙元素产生新的边界,就会产生投影阴影效果,而box-shadow
只作用于元素本身; -
同样的属性值(
16px 16px 20px red
),drop-shadow
产生的阴影效果更淡、渐变效果更好,而box-shadow
的阴影颜色更重。
3、text-shadow文字阴影
text-shadow的属性值跟box-shadow大体上一样(跟drop-shadow完全一样),不同的地方在于text-shadow没有inset和阴影扩散半径,text-shadow的取值如下:
/* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影颜色 */
text-shadow: 10px 10px 10px rgba(0, 0, 0, 0.5);
/* 多个阴影用英文逗号隔开 */
text-shadow: 10px 10px 10px rgba(0, 0, 0, 0.5), 0px 0px 10px red;
以下代码,会将第4个.block元素渲染为
.block:nth-child(4) {
font-size: 54px;
font-weight: bold;
text-align: center;
border: 1px solid #000;
text-shadow: 10px 10px 8px red;
}
4、filter滤镜 + 伪元素
已知filter: blur(5px)
CSS滤镜能让元素产生高斯模糊效果,如果我们加一个伪元素,给伪元素加上这个滤镜、加上适当的位移,是不是也可以模拟box-shadow的效果呢,答案是肯定的。当然,这种方式也是没法实现阴影扩散半径和inset的效果,下面我们来看个例子。
以下代码,会将第5个.block元素渲染为
.block:nth-child(5) {
position: relative;
background: url("static/image/butterfly.jpeg") no-repeat center center;
background-size: cover;
&::after {
content: "";
position: absolute;
z-index: -1;
top: 16px;
left: 16px;
width: 100%;
height: 100%;
background: inherit;
background-size: cover;
filter: blur(20px) opacity(0.8);
}
}
图片原图如下:(图片来自500px,非商业用途,如有侵权删)
保持上面CSS不变,我们换一张图片,会产生不同颜色的阴影效果,说明这种方式的阴影是会跟随元素颜色变化的。
如上效果可以看到,filter blur + 伪元素模拟的阴影效果,更加淡雅,并且会随着元素背景内容颜色变化,由于是filter+伪元素实现的,所以xy轴的偏移靠top、left属性来设置,模糊半径及效果靠filter: blur(半径) opacity(透明度)
来实现。
5、filter滤镜 + background-clip裁剪 = 文字阴影
上面第4点演示了filter产生跟随元素背景变化的阴影,不经联想到,文字阴影有没有办法达到这种效果呢,不妨来试试。
如下代码,会将第6个.block元素渲染为
.image-move {
position: relative;
font-size: 54px;
font-weight: bold;
text-align: center;
border: 1px solid red;
overflow: hidden;
}
.shadow {
position: absolute;
left: 10px;
top: 10px;
width: 100%;
background: url("static/image/butterfly.jpeg");
background-size: 100% 100%;
background-position: 0% 0%;
-webkit-background-clip: text;
color: transparent;
filter: blur(3px) opacity(0.5);
}
文字阴影效果产生了,并且阴影的文字还是以图片为底裁剪出来的,效果还不错。
接着我们换种方式,给两个.image-move都加上backgroup和backgroup-clip看看效果:
.image-move {
position: relative;
font-size: 54px;
font-weight: bold;
text-align: center;
border: 1px solid red;
overflow: hidden;
background: url("static/image/butterfly.jpeg");
background-size: 100% 100%;
background-position: 0% 0%;
-webkit-background-clip: text;
color: transparent;
/* color: rgba(255, 0, 0, 0.2); */
}
.shadow {
position: absolute;
left: 10px;
top: 10px;
width: 100%;
filter: blur(3px) opacity(0.5);
}
效果更加惊艳,试想一下,将背景换成渐变图案或者其他图片,是不是有更多不同效果。
以上用到了好几个CSS特性,但产生文字背景裁剪效果的必要前提是:
-
声明了
background-image
或者background-color
值 -
声明了
-webkit-background-clip: text
-
字体颜色要带有透明度,比如
color: transparent
、color: rgba(255, 0, 0, 0.2)
,并且不同颜色不同透明度的效果也不一样
总结
虽然都是普通常见的CSS属性,但组合到一起就可以产生不同的效果,所以最重要的是要理解每个CSS的特性,善用CSS,才能激发更多创意。
本文介绍了5种实现阴影的方式,每种方式效果、兼容性不完全一致,需根据实际情况选择。
大千世界无奇不有,如有其他实现方式也非常欢迎评论区讨论。
转载自:https://juejin.cn/post/7410668201779396627