long time no see, 又是好久没有写博客了, 之前的博客全是写一写原理啊, 框架思想啊, 算法啥的, 今天趁着周末, 咱们来点不一样的, 可能很多同学对于css的感知还停留在style is just style的阶段, 不过这几年css虽然迭代的慢, 但是也算是出来了不少比较nice的新特性, 我们一起来看看喽
在本文中我们主要探究以下属性:
- filter
- box-reflect
- css variable
- aspect-ratio
- gap
filter
顾名思义,
filter的意思就是滤镜, 滤镜咱都知道吧, 整个自拍 可不得加个滤镜美颜啥的, 什么黑白, 彩色, 复古滤镜, 滤镜其实就是控制一个元素的颜色产生偏移(说通俗点就是给你换色), 知道了含义, 我们大概来看看滤镜应该怎么玩
这玩意可以填的属性比较多, 我们一个一个来玩玩
filter: blur(): 模糊
当我们给一个元素添加filter: blur(模糊像素值)的时候, 他会给该元素实现一个高斯模糊的效果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>css new features</title>
<style>
body {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #f5f5f5;
}
/* filter: blur */
.container {
width: 400px;
height: 400px;
background-color: #000;
/* 关键就在于这行代码, 如果没有这行代码, 我们都知道页面会是一个什么效果 */
filter: blur(10px);
}
</style>
</head>
<body>
<div class="container""></div>
</body>
</html>
当添加了filter: blur以后, 效果如下
blur的参数值越高, 模糊程度越高, 参数值越低, 模糊程度越低
功能知道了, 那么我们可以用这个属性来干嘛呢? 最常见的就是企业级开发中的毛玻璃效果
<!-- 还是和之前一样的代码, 我们给container加点背景 -->
...
<style>
.container {
width: 380px;
height: 210px;
background-color: #000;
filter: blur(2px);
background-image: url(https://game.gtimg.cn/images/lol/act/img/skin/big134005.jpg);
background-position: center;
background-repeat: no-repeat;
background-size: cover;
text-align: center;
color: #fff;
line-height: 210px;
font-size: 24px;
font-weight: bold;
font-family: Consolas;
}
</style>
...
效果如下了, 以前我们处理毛玻璃效果真的是js逻辑搞一大堆, 或者还需要UI出图, 现在一个css属性给你搞定, 灰常nice
不过其实我们还会发现一个问题, 当我们在container元素中加入文字的时候, 文字也一起被模糊掉了, 如果我们不想要这样的效果应该怎么办呢? 聪明的同学就知道用after和before进行定位覆盖, 这个是没毛病的, 但是css官方也想到了这个点, 所以他们推出了backdrop-filter属性, 顾名思义: 这个属性是叫做backdrop, 那么他是给指定backdrop-filter的元素加上一层滤镜, 使得元素后面的东西产生模糊, 所以他不能加给自身, filter可以可以模糊自身, backdrop-filter不行, 要注意这一点哈
...
<style>
.container {
...
/* filter: blur(2px); 我们注释掉这行代码 */
...
}
/* 同时给filter-box进行backdrop过滤 */
.filter-box {
width: 100%;
height: 100%;
backdrop-filter: blur(6px);
}
</style>
...
<!-- 所以我们必须得改一下结构 -->
<div class="container"">
<div class="filter-box">hello, world</div>
</div>
...
这时候效果如下, 是不是非常的nice
filter: grayscale(): 灰度
我们拍了一张照片以后, 有时可能会把照片变成黑白照片有木有, 而filter: grayscale正是帮我们做这个事情的, 我们来看看使用场景吧
grayscale()的参数值是一个百分比, 百分比越高, 灰度值越高(灰度值越高, 就越接近黑白)
用这个属性, 我们可以实现一些hover过后黑白照片变彩色的效果, 类似于给一个激活状态, 来看看例子
实现效果如下, 真的没毛病
filter: hue-rotate(): 色相变更
什么叫色相变更哈, 我们不是专业的UI人员, 粗浅理解的话你可以认为色相变更就是色值的变换(比如从红色到绿色就是色相变更), 过去, 我们如果要实现一个盒子, 无限的变换颜色, 我们需要在JS逻辑中采集生成随机的rgb色值吧, 现在, 有了hue-rotate, 我们翻身做主人了, 我们来看看色相变更的强大之处
...
<style>
.container {
width: 200px;
height: 200px;
background-color: green;
animation: hueRotateAnimate 6s linear infinite;
}
@keyframes hueRotateAnimate {
0% {
filter: hue-rotate(0)
}
100% {
filter: hue-rotate(360deg);
}
}
</style>
...
<div class="container">
</div>
实现效果如下, 是不是很炫酷, 很nice, 不知道大家有没有看到过华为的充电效果, 其实那个就是用filter: hue-rotate实现的
filter: contrast(): 对比度
对比度这个东西我相信大家也不陌生了吧, 对比度越高, 色彩差异越大, 对比度越低, 色彩差异越小, 当对比度为0的时候 我们可以直接来看个效果
...
<style>
.container {
width: 200px;
height: 400px;
position: relative;
display: flex;
}
.container .building-bg,
.container .real-building {
width: 100%;
height: 100%;
background-position: center;
background-repeat: no-repeat;
background-size: contain;
background-image: url(./oldBuilding .png);
}
.building-bg {
/* 我们将左侧的div 背景的对比度设置为0 */
filter: contrast(0);
}
</style>
<div class="container"">
<div class="building-bg"></div>
<div class="real-building"></div>
</div>
...
上面的代码, 本质上两个div都是同一个背景, 但是出来的效果如下
那么利用这个效果我们可以干啥呢, 不知道大家有没有做过那种不规则图形的边框, 真的非常难搞, 多数情况下, 这个都是由UI出图, 我们直接用, 但是有了这个属性, 我们自己也可以搞定, 我们改一下上面的样式代码
.container {
width: 200px;
height: 400px;
position: relative;
}
.container .building-bg,
.container .real-building {
width: 100%;
height: 100%;
background-position: center;
background-repeat: no-repeat;
background-size: contain;
background-image: url(./古楼\ .png);
}
.building-bg {
filter: contrast(0);
}
/* 主要增加这一段 */
.container .real-building {
position: absolute;
top: 4%;
left: 4%;
width: 92%;
height: 92%;
}
出来的效果如下, 是不是非常的nice
filter: url(): svg滤镜(这个用的少, 但是非常强大 )
我们知道svg是一个非常强大的东西, 这哥们可以帮我们绘制很多图形乃至icon出来, filter: url的强大之处就是他可以让你将svg作为滤镜值, 这里你可能还不太理解, 前提是这要基于你对svg的认知足够多的前提下
下面我要做一个例子, 这个例子需要一些前置知识, 你可以去学习学习, 或者你可以直接越过filter: url这一块, 因为他平时用的实在是不多, 但是因为他非常非常强大, 可以做出非常炫酷的特效, 所以笔者还是拿出来说说
前置知识如下:
- svg标签: developer.mozilla.org/en-US/docs/…
- FeTubulence 标签: developer.mozilla.org/en-US/docs/…
- filter标签: developer.mozilla.org/en-US/docs/…
- animate标签: developer.mozilla.org/en-US/docs/…
我们来写一段代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ring of Fire</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #000;
}
.circle {
position: relative;
width: 600px;
height: 600px;
filter: url(#wavy) blur(1px);
}
.circle::before {
content: "";
position: absolute;
top: 100px;
left: 100px;
bottom: 100px;
right: 100px;
border: 20px solid #fff;
border-radius: 50%;
box-shadow: 0 0 50px #0f0,
0 0 50px #0f0 inset;
animation: changeColorAnimate 5s linear infinite;
}
.circle::after {
content: "";
position: absolute;
top: 100px;
left: 100px;
bottom: 100px;
right: 100px;
border: 20px solid #fff;
border-radius: 50%;
box-shadow: 0 0 50px #fff,
0 0 50px #fff inset;
}
svg {
width: 0;
height: 0;
}
@keyframes changeColorAnimate {
0% {
filter: hue-rotate(0deg)
}
100% {
filter: hue-rotate(360deg)
}
}
</style>
</head>
<body>
<div class="circle"></div>
<div class="circle"></div>
<svg>
<filter id="wavy">
<feTurbulence x="0" y="0" baseFrequency="0.009" numOctaves="5" seed="2">
<animate attributeName="baseFrequency" dur="60s" values="0.02;0.005;0.02" repeatCount="indefinite" />
</feTurbulence>
<feDisplacementMap in="SourceGraphic" scale="30" />
</filter>
</svg>
</body>
</html>
他实现的效果如下, 兄弟, 这个你说炫不炫酷 牛不牛逼, 这个也是结合了一部分我们上面的知识
其实整个filter的属性还有很多, 我这里只举例了一些最常用而且帮助最大的, 实际上我们知道对于滤镜还有很多操作, 比如曝光度, 饱和度, 透明度等等操作, 而这些操作filter都给我们集成了不同的属性值, 大家感兴趣的可以去mdn自行查阅
filtermdn链接: developer.mozilla.org/en-US/docs/…
同时, 我们必须关注的就是filter的一个兼容情况
box-reflect
不知道大家有没接触过倒影的需求, 在一些需要比较视觉效果丰富的产品上, 可能会看到, 而box-reflect就是来帮我们实现这个功能的, 虽然他还是一个experiment阶段的东西, 不过这也是一个未来功能的趋势, 而且实在是方便, 目前w3c官方也纳入了草案
该属性是接收几个参数, 类似于border:
- 第一个参数: 投影的方向(
above,below,left,right四个值可选) - 第二个参数: 投影和实物之间的距离
- 第三个参数: 这个参数不得了, 他控制了投影是什么东西(这意味着投影可不一定投出来的是实物的倒影啊, 他完全可以是其他的什么图片)
...
<style>
.container {
width: 200px;
height: 200px;
background-color: #000;
-webkit-box-reflect: below 1px linear-gradient(transparent, #000);
/* 第三个参数你也可以填url(你要显示的路径), 非常的nice和好用 */
}
</style>
<div class="container"">
</div>
...
页面效果如下, 我们就可以看到一个倒影了
那利用这个玩意, 我们再结合一些其他的东西, 能干啥呢, 这能干的事情还真的挺多的, 就看你乐不乐意去想了, 一些类似于Netflix官网的字体闪烁倒影效果不就信手拈来了
...
<style>
body {
display: flex;
justify-content: center;
align-items: center;
background-color: rgb(94, 29, 29);
min-height: 100vh;
}
.container {
font-family: Menlo;
font-size: 6rem;
color: rgb(138, 15, 15);
width: 100%;
text-align: center;
letter-spacing: 15px;
-webkit-box-reflect: below 1px linear-gradient(transparent, #000);
line-height: 5rem;
animation: animate 5s linear infinite;
font-weight: bold;
}
@keyframes animate {
0%, 18%, 20%, 50.1%, 60%, 65.1%, 80%, 90.1%, 92% {
color:rgb(138, 15, 15);
text-shadow: none;
}
18.1%, 20.1%, 30%, 50%, 60.1%, 65%, 80.1%, 92.1%, 90%, 100% {
color: #fff;
text-shadow: 0 0 10px firebrick,
0 0 20px firebrick,
0 0 40px firebrick,
0 0 80px firebrick,
0 0 160px firebrick;
}
}
</style>
...
<div class="container">Netflix</div>
...
...
实现的效果如下, 是不是很炫酷, 很nice
box-reflect的一个支持情况如下
css variable
less和sass乃至post-css我相信大家都是不陌生的, 他们主要解决了一个什么问题呢? 最重要的就是一个css的写法还有css变量的问题, 可能还有的会用到css module的情况, 而w3c官方也早就注意到了这些, 这不, css 变量就来了
...
<style>
...
:root {
/* 在:root下声明的变量, 全局皆可通用 */
--container-bg-color: #07252d;
}
.container {
/* 而在container内部声明的变量, 只能在container容器中使用, 这个没毛病吧 */
--container-bg-color:red;
width: 200px;
height: 200px;
/* 我们使用var语法来使用变量 */
background-color: var(--container-bg-color);
}
</style>
这个时候一个红色的div盒子就产生了, 我们知道像类似于less, sass等都需要构建工具的配合, 而且他们是使用的js对文件的io处理, 这会比较大的影响开发时的热更新性能, 如果css官方能够支持这玩意, 那其实真的挺香的
同样, css variable的支持程度如下
aspect-ratio
我们来设想一个场景, 假设产品经理和你说, 我们现在做的是移动端, 这个父级的容器我不管外界屏幕尺寸怎么变化, 你始终要给我保持16:9的一个显示区域
这个需求到手虽然谈不上裂开哈, 但是如果我们使用的是Vue或者React的话, 我们就需要使用computed或者useMemo去实时计算一些值了, 这样其实就增加了我们一定的逻辑复杂度, aspect-ratio就是为了这种场景存在的
<style>
...
.container {
/* 当我们使用aspect-ratio的时候就是希望他根据尺寸的变化而变化, 所以我们不用给固定的高 */
width: 100%;
background-image: url(https://game.gtimg.cn/images/lol/act/img/skin/big51010.jpg);
background-repeat: no-repeat;
background-size: cover;
aspect-ratio: 16 / 9;
}
...
</style>
...
<div class="container"></div>
这个时候我们就会发现, 无论我们的视口尺寸怎么变化, 整个container区域始终保持这一个16:9的尺寸, 这个是你过去用css怎么都办不到的
同时我们还可以对aspect-ratio进行媒体查询, 我们可以选择在不同的视口比例下我们要怎么去显示内容, 在没有aspect-ratio的时候, 我们做的对视口的响应式一般都是对具体的px范围区间做约束, 而有了aspect-ratio的媒体查询以后, 针对移动端我们的约束就更加的精准了
/* 针对不同的视口尺寸, 使用最精准的样式控制 */
@media (aspect-ratio: 16/9) {
div {
background: #9af;
}
}
@media (aspect-ratio: 4/3) {
div {
background: #9ff;
}
}
aspect-ratio的兼容性如下
gap
大家日常肯定遇到过这样的需求: 有很多元素, 我们需要将它们规规整整的排齐, 类似于淘宝的商品, 然后产品又希望他们之间都来点间距, 过去我们实现这样的效果, 无非就是flex布局加flex子元素的margin, 其实这样会有很多问题, 需要我们写更多的代码去弥补掉这些问题, 现在我们可以使用gap
<style>
.container {
display: flex;
width: 400px;
height: 600px;
border-radius: 8px;
border: 2px solid gray;
justify-content: space-between;
/* gap给间距 */
gap: 2%;
padding: 1%;
box-sizing: border-box;
/*
注意哈, 当flex容器里有多行的时候, 你的align-items就不会生效了
必须使用align-content
*/
align-content: baseline;
flex-wrap: wrap;
}
.container div {
width: 48%;
aspect-ratio: 2 / 1;
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
.Vayne {
background-image: url(https://game.gtimg.cn/images/lol/act/img/skin/big67014.jpg);
}
.Cassiopeia {
background-image: url(https://game.gtimg.cn/images/lol/act/img/skin/big69003.jpg);
}
.Caitlyn {
background-image: url(https://game.gtimg.cn/images/lol/act/img/skin/big51010.jpg);
}
.Azir {
background-image: url(https://game.gtimg.cn/images/lol/act/img/skin/big268005.jpg);
}
.Oriana {
background-image: url(https://game.gtimg.cn/images/lol/act/img/skin/big61007.jpg);
}
</style>
...
<div class="container"">
<div class="Cassiopeia"></div>
<div class="Caitlyn"></div>
<div class="Vayne"></div>
<div class="Azir"></div>
<div class="Oriana"></div>
</div>
...
实现的效果如下, 几乎可以说不费吹灰之力就实现了一个自适应的流式布局
gap的一个兼容性如下
写在最后, 其实css的新特性还是有很多的, 今天就写到这儿, 笔者要去扫地去了, 希望这些东西能够对大家的日常开发产生帮助和少走弯路, 话说回来, 我们自身也需要不断的对新事物保持探索和好奇, 新的东西总归是更好的, 保持好奇心和学习能力也是不被行业淘汰的基本素质, 笔者也会在下周分享中篇, 下下周分享下篇~ 一起加油