前言
最近阅读了张鑫旭老师的《CSS新世界》里面对一些css属性的运用很巧妙,属实打开了新世界的大门,这篇文章主要总结一下filter属性的运用,里面的例子主要来自书本或参考文章,经由自己一些改动实现;
完整代码可以关注公众号 前端一块砖, 公众号后台回复:filter,获取codepen地址
filter属性
filter,就是我们常说的滤镜,可以通过改变相关参数使元素出现模糊或颜色偏移等图形效果;
filter属性总共支持10个滤镜函数,我们来逐一介绍一下
blur
filter: blur(5px)
模糊,blur()函数支持任意长度值,但是不支持百分比值
blur()函数的参数值表示高斯函数的标准偏差值,可以理解为屏幕上互相融合的像素数量。因此,blur()函数的参数值越大,图像的模糊效果越明显
我们常见的毛玻璃效果就可以通过该函数实现,不过更合适的属性并不是filter
而是 backdrop-filter
; 它俩的语法几乎一模一样,区别在于 filter 是对当前元素运用滤镜效果,而 backdrop-filter 是让当前元素所在区域后面的内容应用滤镜效果,为了看到效果,必须使元素或其背景至少部分透明,见下例
<div class="container">
<div class="drop-box">
<p>backdrop-filter: blur(10px)</p>
</div>
<div class="filter-box">
<p>filter: blur(1px)</p>
</div>
</div>
/* ...other css */
.drop-box {
background-color: rgba(255, 255, 255, 0.3);
border-radius: 5px;
text-align: center;
backdrop-filter: blur(10px);
padding: 20px 40px;
}
.filter-box {
background-color: rgba(255, 255, 255, .7);
border-radius: 5px;
text-align: center;
filter: blur(1px);
padding: 20px 40px;
}
可以看到filter使得文字内容也模糊了,而 backdrop-filter 符合我们的预期效果;但 backdrop-filter
目前在火狐上还有兼容性问题,下面这个例子🌰我们用filter来实现backdrop-filter的效果
为了避免文字内容受到滤镜模糊影响,我们可以将滤镜设置在伪元素before上,动画效果和背景都通过伪元素实现
<ul class="cards">
<li class="card">
<h4 class="title">GenJi</h4>
<p class="content">龍神の剣を喰え!</p>
</li>
<li class="card">
<h4 class="title">Ana Amari</h4>
<p class="content">该睡觉咯.</p>
</li>
<li class="card">
<h4 class="title">Torbjörn</h4>
<p class="content">他强任他强<br>我玩托比昂. </p>
</li>
</ul>
/* ...other css */
.card {
width: 220px;
height: 300px;
border-radius: 8px;
padding: 0 24px;
position: relative;
cursor: pointer;
}
.card::before {
z-index: -1;
content: '';
position: absolute;
/* 逻辑属性,相当于 top: 0; right: 0; bottom: 0; left: 0; 的缩写 */
inset: 0;
background-color: pink;
background-size: cover;
background-position: center;
border-radius: 12px;
filter: blur(0px) opacity(1);
transition: .2s linear;
}
.card:nth-child(1)::before {
background-image: url(https://th.wallhaven.cc/small/mp/mplmy1.jpg);
}
.card:nth-child(2)::before {
background-image: url(https://th.wallhaven.cc/small/6q/6q228x.jpg);
}
.card:nth-child(3)::before {
background-image: url(https://th.wallhaven.cc/small/gj/gj99ye.jpg);
}
/* 通过css选择器选出非hover的.card元素 */
.cards:hover>.card:not(:hover)::before {
/* 给其伪类同时添加模糊、透明度和明暗度的滤镜 */
filter: blur(5px) opacity(0.8) brightness(0.8);
}
/* 对于hover的元素,其伪类增强饱和度,尺寸放大 */
.card:hover::before {
filter: saturate(1.2);
transform: scale(1.05);
}
brightness
filter: brightness(2.4)
亮度,上面👆的例子我们已经用到过了,参数值支持数值和百分比值,不传参默认取1,参数为0表示没有亮度,元素呈纯黑色
brightness可以用来模拟电影谢幕效果,这里我们用hover触发动画
<div class="container">
<div class="text">
<p>该睡觉咯.</p>
</div>
</div>
.container::before {
z-index: -1;
content: '';
inset: 0;
position: absolute;
background-image: url(https://w.wallhaven.cc/full/6q/wallhaven-6q228x.png), linear-gradient(rgb(219, 166, 166), rgb(0, 0, 172));
background-size: cover;
}
/* 我们等背景图加载完再手动通过hover触发动画 */
.container:hover::before {
/* forwards表示当动画完成后,保持最后一帧的状态 */
animation: fade-away 2.5s linear forwards;
}
.container:hover>.text {
animation: show 2s cubic-bezier(.74, -0.1, .86, .83) forwards;
}
.text {
line-height: 55px;
color: #fff;
font-size: 36px;
text-align: center;
opacity: 0;
}
/* 背景变暗动画 */
@keyframes fade-away {
30% {
filter: brightness(1);
}
100% {
filter: brightness(0);
}
}
/* 文字出现动画 */
@keyframes show {
20% {
opacity: 0;
}
100% {
opacity: 1;
}
}
drop-shadow
filter: drop-shadow(4px 4px 8px blue);
filter: drop-shadow(x偏移, y偏移, 模糊大小, 色值);
投影,drop-shadow用来给元素设置符合真实世界阴影规则的投影效果;相比于box-shadow,它不支持阴影扩展,不支持内阴影,不支持累加投影;但不同于box-shadow只会在盒子的四周留下阴影,它能使盒子中镂空或透明的部分也出现阴影轮廓
<div class="container">
<div class="item" style="border-bottom-color: pink; transform: rotateZ(0);"></div>
<div class="item" style="border-bottom-color: lightblue; transform: rotateZ(60deg);"></div>
<div class="item" style="border-bottom-color: slateblue; transform: rotateZ(120deg);"></div>
<div class="item" style="border-bottom-color: slategrey; transform: rotateZ(180deg);"></div>
<div class="item" style="border-bottom-color: olive; transform: rotateZ(240deg);"></div>
<div class="item" style="border-bottom-color: salmon; transform: rotateZ(300deg);"></div>
</div>
/* ...other css */
.item {
display: block;
height: 0;
width: 4px;
border-width: 0 4px 80px 4px;
border-style: none solid solid;
border-color: transparent;
position: absolute;
transform-origin: bottom;
}
.container {
display: inline-flex;
justify-content: center;
width: 160px;
height: 160px;
transform-origin: center;
animation: rotateAnimate 10s linear infinite forwards;
filter: drop-shadow(1px 1px 5px black)
}
@keyframes rotateAnimate {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
上面这个例子中,我们通过css边框实现了一个类似风车的东西?我们可以看到,使用drop-shadow
后的阴影轮廓是围绕元素中的非透明区域的;而如果我们使用的是box-shadow,阴影轮廓就会是矩形的
[图片上传失败...(image-8661ce-1654243934506)]
grayscale
filter: grayscale(50%)
灰度,灰度表示以黑色为基准色,根据图像原来的颜色,以不同饱和度的黑色来显示图像;灰度有两个非常实用的应用场景:
图标点亮
filter: grayscale(1);
一般情况下我们需要准备彩色和灰色两份图标来表示点亮和未点亮状态,而使用grayscale滤镜可以实现置灰效果,少准备一份图标;
网页置灰
某些特殊节日我们可能需要将网站首页置灰,通过灰度滤镜,一行代码就能快速实现
body {
filter: grayscale(1);
}
hue-rotate
filter: hue-rotate(90deg)
色调旋转,参数值为角度,hue-rotate()函数可以调整元素的色调,但饱和度和亮度保持不变;运用该滤镜可以快速实现相同风格的颜色效果,比我们自己调试出来的亮红配亮绿靠谱
button {
background-color: lightblue;
border-color: white;
}
button:nth-child(2) {
filter: hue-rotate(60deg)
}
button:nth-child(3) {
filter: hue-rotate(120deg)
}
button:nth-child(4) {
filter: hue-rotate(180deg)
}
button:nth-child(5) {
filter: hue-rotate(240deg)
}
button:nth-child(6) {
filter: hue-rotate(300deg)
}
invert
filter: invert(1);
反相,invert可以让元素的亮度和色调同时反转,参数值支持数值和百分比值,invert配合hue-rotate可以在不太重要的页面快速实现深色模式
<div class="card">
<h4>Some Words</h4>
<img src="https://picsum.photos/id/1080/6858/4574" alt="">
</div>
/* 通过媒体查询判断当前用户代理是设置是否处在黑暗模式 */
@media (prefers-color-scheme: dark) {
body {
background-color: #000;
/* 将页面所有内容反相,调整色调以符合深色模式效果 */
filter: invert(1) hue-rotate(180deg);
}
/* 图片内容反相后就不是原图了,因此我们对图片再次反相以恢复原来的样子 */
img {
filter: invert(1) hue-rotate(180deg);
}
}
这里我们可以在谷歌浏览器地址栏输入 chrome://flags/
,搜索 dark
,找到 Auto Dark Mode for Web Contents
打开实验中的黑暗模式,重启浏览器,就可以验证效果啦
saturate
filter: saturate(230%)
饱和度,参数值支持数值和百分比值,不传值则默认为1;饱和度用来控制图片中含色成分和消色成分(灰色)的比例,饱和度越高,含色成分越高,饱和度越低,消色成分越高,饱和度为0时表现为灰度效果,等同于 grayscale(1)
sepia
filter:sepia(60%)
褐色,参数支持数值和百分比值,默认值是0;当参数值为1时表现为深褐色,可以用来实现老照片的效果;
contrast
filter: contrast(200%)
对比度,参数值支持数值和百分比值 , 默认值为1;值为0的时候表示无对比度,图片会变成一个灰色色块,色值#808080;
opacity
filter: opacity(25%)
透明度,与opacity属性基本一致,不推荐使用
完整代码可以关注公众号 前端一块砖, 公众号后台回复:filter,获取codepen地址
参考
[1]《css新世界》