一些让人很哇塞的CSS实现 - filter属性

前言

最近阅读了张鑫旭老师的《CSS新世界》里面对一些css属性的运用很巧妙,属实打开了新世界的大门,这篇文章主要总结一下filter属性的运用,里面的例子主要来自书本或参考文章,经由自己一些改动实现;

完整代码可以关注公众号 前端一块砖, 公众号后台回复:filter,获取codepen地址

filter属性

filter,就是我们常说的滤镜,可以通过改变相关参数使元素出现模糊或颜色偏移等图形效果;

filter属性总共支持10个滤镜函数,我们来逐一介绍一下

blur

filter: blur(5px)

模糊,blur()函数支持任意长度值,但是不支持百分比值

blur()函数的参数值表示高斯函数的标准偏差值,可以理解为屏幕上互相融合的像素数量。因此,blur()函数的参数值越大,图像的模糊效果越明显

我们常见的毛玻璃效果就可以通过该函数实现,不过更合适的属性并不是filter 而是 backdrop-filter ; 它俩的语法几乎一模一样,区别在于 filter 是对当前元素运用滤镜效果,而 backdrop-filter 是让当前元素所在区域后面的内容应用滤镜效果,为了看到效果,必须使元素或其背景至少部分透明,见下例

背景图源: https://picsum.photos/
<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的效果

背景图源: https://wallhaven.cc/

为了避免文字内容受到滤镜模糊影响,我们可以将滤镜设置在伪元素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触发动画

背景图源: https://wallhaven.cc/
<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新世界》

[2] 巧用CSS filter,让你的网站更加酷炫!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容