1.position: sticky
定制开发不知道大家平时业务开定制开发发中有没有碰到像上图定制开发一样的吸顶的需求:定制开发标题在滚动的时候,定制开发会一直贴着最顶上。
定制开发这种场景实际上很多:定制开发比如表格的标题栏、定制开发网站的导航栏、定制开发手机通讯录的人名首字定制开发母标题等等。定制开发如果让大家自己动手做的话,定制开发是不是会用 js 结合 css 来实现呢?定制开发以前确实是这样的,直到后来 position 定制开发属性新增了一个属性值 sticky ,定制开发前端程序员才迎来了小春天。
// css 部分.container { background-color: oldlace; height: 200px; width: 140px; overflow: auto; } .container div { height: 20px; background-color: aqua; border: 1px solid; } .container .header { position: sticky; top: 0; background-color: rgb(187, 153, 153);}// html 部分<div class="container"> <div class="header">Header</div> <div>1</div> <div>2</div> <div>3</div></div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
定制开发定制开发就这么简单?对,就这么简单,定制开发但是小伙伴们使用的时定制开发候要注意兼容性
2. :empty 选择器
定制开发平时开发的时候数据都定制开发是通过请求接口获取的,定制开发也会存在接口没有数据的情况。这个时候正常的做法是给用户一个提示,让用户知道当前不是出 bug 了,而是确实没有数据。
一般的做法是我们人为的判断当前数据返回列表的长度是否为 0,如果为 0 则显示一个 “暂无数据” 给用户,反之则隐藏该提示。写过 Vue 的小伙伴是不是经常这么做:
<div> <template v-if="datas.length"> <div v-for="data in datas"></div> </template> <template v-else> <div>暂无数据</div> </template></div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
但是有了 :empty 这个选择器后,你大可以把这个活交给 CSS 来干。
.container { height: 400px; width: 600px; background-color: antiquewhite; display: flex; justify-content: center; align-items: center;}.container:empty::after { content: "暂无数据";}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
通过 :empty 选中内容为空的容器,然后通过为空容器添加提示。是不是方便很多呢?
3. gap
小伙伴们日常开发中,都有用过 padding 和 margin 吧,margin 一般用做边距,让两个元素隔开一点距离,但是对于一些场景下,我们很难通过计算得到一个除的尽的值,比如 100px 我要让 3 个元素等分,且每个元素隔开 10px,这就很尴尬了。
没关系!我们可以用 gap 属性,gap 属性它适用于 Grid 布局、Flex 布局以及多列布局,并不一定只是 Grid 布局中可以使用。
比如我们要让每个元素之间隔开 20px, 那么使用 gap 我们可以这样:
display: flex | grid;gap: 20px;
- 1
- 2
4. : text
这个属性可能小伙伴们用的不多,有什么用呢?简单来说就是可以做一个带背景的文字效果:
图 1 + 图 2 = 图 3。是不是很惊艳呢?大家平时 background-clip 是不是都用来做一些裁切效果?in知道它还有个属性值是 text 吗?background-clip: text 用来做带背景的文字效果,相信大家平时浏览一些网站的时候都会看到类似的实现,实际上通过 CSS 我们也能做到这种效果,可不要傻傻的以为都是用制图工具做的。
<p>Lorem ......</p>p { color: transparent; background: url(https://media.giphy.com/media/Ju7l5y9osyymQ/giphy.gif) center/cover; background-clip: text;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
5. user-select
很多人不知道这个属性是什么意思。大家看看下图:
网页和 APP 有个不同点是,网页上的字是可以通过光标选中的,而 APP 的不行。
有的小伙伴可能会疑惑:那我网页上也用不着这个属性啊?
非也非也,我们知道现在很多新的技术产生,可以在 APP 上嵌套 webview 或者是网页,比如 Electron 做的 桌面端应用 ,大家没见过哪个桌面端应用是可以光标选中的吧?
而 user-select 属性可以 禁用光标选中 ,让网页看着和移动端一样。
6. :invalid 伪类
:invalid 表示任意内容未通过验证的 input 或其他 form 元素。什么意思呢?举个例子。
这是一个表单。
<form> <label for="url_input">Enter a URL:</label> <input type="url" id="url_input" /> <br /> <br /> <label for="email_input">Enter an email address:</label> <input type="email" id="email_input" required/></form>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
我们的需求是让 input 当值有效时,元素颜色为绿色,无效时为红色。
input:invalid { background-color: #ffdddd;}form:invalid { border: 5px solid #ffdddd;}input:valid { background-color: #ddffdd;}form:valid { border: 5px solid #ddffdd;}input:required { border-color: #800000; border-width: 3px;}input:required:invalid { border-color: #C00000;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
有了 :invalid 属性后,我们就可以不用 JS 也能实现校验提示的效果了。
7. :focus-within 伪类
:focus-within 表示一个元素获得焦点,或该元素的后代元素获得焦点,就会匹配上。啥意思呢?
话不多说,先看图:
// CSSform { border: 1px solid; width: 400px; height: 300px; display: flex; justify-content: center; align-items: center;}form:focus-within { box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.3); background-color: beige;}// HTML<form> <input type="text" id="ipt" placeholder="请输入..." /></form>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
8. mix-blend-mode:difference
mix-blend-mode: difference,意为差值模式
该混合模式会查看每个通道中的颜色信息,比较底色和绘图色,用较亮的像素点的像素值减去较暗的像素点的像素值。
与白色混合将使底色反相;与黑色混合则不产生变化。
通俗一点就是上方图层的亮区将下方图层的颜色进行反相,暗区则将颜色正常显示出来,效果与原图像是完全相反的颜色。
例子1
//css.mode { display: flex; justify-content: center; align-items: center; mix-blend-mode:difference;} .dark { position: relative; left: 6px; height: 24px; width: 24px; background-color: grey; border-radius: 50%;}.light { mix-blend-mode:difference; position: relative; left: -6px; height: 16px; width: 16px; border-radius: 50%; border: 4px solid grey;}//html<div class="mode"> <div class="dark"></div> <div class="light"></div></div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
例子2
<div class="main"></div>.main{ width: 100%; height: 100%; background: linear-gradient(45deg, #000 0, #000 50%, #fff 50%); position: relative; &::before{ content:'LOADING'; position: absolute; font-size: 50px; width: 100%; height: 100%; top: 40%; left: 20%; color: #fff; mix-blend-mode: difference; animation: move 3s infinite linear alternate; }} @keyframes move { 0% { transform: translateX(20%); } 100% { transform: translateX(-20%); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
9.counter
css也可以像js进行计算,当我们需要设置序号或者想知道某种情况出现的次数时,我们可以用一下属性
//counter-increment: record; /* 为计数器每次自增 1(默认) *///counter-increment: record 2; /* 为计数器每次自增 2 *///html<body> <h3>lalala</h3> <h3>lalala</h3> <h3>lalala</h3></body>//cssbody{ counter-reset: first; /* 创建一个计数器first*/}h3:before { content: counter(first)": " ;}h3 { counter-increment: first 2; /* 为计数器first每次增加2 */}//会得到结果//2:lala//4:lala//6:lala
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
10.clip-path
该属性用于截取元素的部分用于显示
polygon
- 值为多个坐标点组成,坐标第一个值是x方向,第二个值是y方向。
- 左上角为原点,右下角是(100%,100%)的点。
//cssbody { background-color: #000;} .fa { border: 1px solid #fff; color: yellowgreen; padding: 10px; margin: 10px;} .fa>div { width: 110px; height: 110px; background-color: yellowgreen; margin: 20px auto;} .polygon1 { clip-path: polygon(50% 0px, 100% 100%, 0px 100%)} .polygon2 { clip-path: polygon(0px 50%, 50% 0, 100% 50%, 50% 100%)} .polygon3 { clip-path: polygon(0% 60%, 20% 0%, 60% 0%, 40% 60%)}//html<div class="fa"> <p>polygon</p> <p>值为多个坐标点组成,坐标第一个值是x方向,第二个值是y方向。</p> <p>左上角为原点,右下角是(100%,100%)的点。</p> <div class="polygon1"></div> <div class="polygon2"></div> <div class="polygon3"></div></div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
circle
- 值为一个坐标点和半径组成。
- 左上角为原点,右下角是(100%,100%)的点。
- 定义半径的时候可以用at关键字来定义坐标。
//cssbody { background-color: #000;} .fa { border: 1px solid #fff; color: yellowgreen; padding: 10px; margin: 10px;} .fa>div { width: 110px; height: 110px; background-color: yellowgreen; margin: 20px auto;} .circle1 { clip-path: circle(50% at 50% 50%)} .circle2 { clip-path: circle(70% at 50% 50%)} .circle3 { clip-path: circle(30% at 10% 10%)}//html<div class="fa"> <p>circle</p> <p>值为一个坐标点和半径组成。</p> <p>左上角为原点,右下角是(100%,100%)的点。</p> <p>定义半径的时候可以用at关键字来定义坐标。</p> <div class="circle1"></div> <div class="circle2"></div> <div class="circle3"></div></div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
ellipse
- 值为椭圆的x轴半径,y轴半径,定位椭圆的坐标三部分组成。
- 左上角为原点,右下角是(100%,100%)的点。
- at关键字将半径和坐标分开。
//cssbody { background-color: #000;} .fa { border: 1px solid #fff; color: yellowgreen; padding: 10px; margin: 10px;} .fa>div { width: 110px; height: 110px; background-color: yellowgreen; margin: 20px auto;} .ellipse1 { clip-path: ellipse(30% 20% at 50% 50%)} .ellipse2 { clip-path: ellipse(20% 30% at 50% 50%)} .ellipse3 { clip-path: ellipse(60% 10% at 10% 10%)}//html<div class="fa"> <p>ellipse</p> <p>值为椭圆的x轴半径,y轴半径,定位椭圆的坐标三部分组成。</p> <p>左上角为原点,右下角是(100%,100%)的点。</p> <p>at关键字将半径和坐标分开</p> <div class="ellipse1"></div> <div class="ellipse2"></div> <div class="ellipse3"></div></div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
inset
- 值为(上 右 下 左 round 左上角radius 右上角radius 右下角radius 左下角radius)
- round前面的数值,表示的是距离,如果第一个值为25%,则表示图像在上面从25%开始绘制。
//cssbody { background-color: #000;} .fa { border: 1px solid #fff; color: yellowgreen; padding: 10px; margin: 10px;} .fa>div { width: 110px; height: 110px; background-color: yellowgreen; margin: 20px auto;} .inset1 { clip-path: inset(25% 0% 25% 0% round 0% 25% 0% 25%)} .inset2 { clip-path: inset(0% 25% 25% 0% round 25% 25% 25% 0%)} .inset3 { clip-path: inset(25% 25% 0% 0% round 0% 25% 0% 25%)}//html<div class="fa"> <p>inset</p> <p>值为(上 右 下 左 round 左上角radius 右上角radius 右下角radius 左下角radius)</p> <p>round前面的数值,表示的是距离,如果第一个值为25%,则表示图像在上面从25%开始绘制</p> <div class="inset1"></div> <div class="inset2"></div> <div class="inset3"></div></div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
clip-path生成器:http://tools.jb51.net/code/css3path
11.mask(遮罩)
核心:所谓遮罩,就是原始图片只显示遮罩图片非透明的部分。(一定要理解)
background代表元素图片,mask代表遮罩图片
例子1
.main{ width: 500px; height:500px; background: url('./background.png') no-repeat; background-size: 500px 500px; -webkit-mask-image: url('./mask.png'); mask-image: url('./mask.png'); -webkit-mask-size: 500px 500px; //mask-image可能无法使用,我们用其他的替换一下(用径向渐变画一个直径为250px的圆) //-webkit-mask: radial-gradient(transparent 250px, #000 250px) no-repeat; //mask: radial-gradient(transparent 250px, #000 250px) no-repeat;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
第一张图片为background(原始图片)
第二章图片代表mask(遮罩图片)
所以原始图片只显示大虾这张图片的非透明(也就是大虾本身)部分
例子2(做渐变)
.main{ width: 500px; height:500px; background: url('./background.png') no-repeat; background-size: 500px 500px; -webkit-mask: linear-gradient(90deg, #fff,transparent); mask: linear-gradient(90deg, #fff,transparent); -webkit-mask-size: 500px 500px;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
例子3(多张图片)
.main{ width: 500px; height:500px; background: url('./background.png') no-repeat; background-size: 500px 500px; position: relative; &::before{ position: absolute; content: ''; width: 500px; height: 500px; background: url('./overBackground.png'); background-size: 500px 500px; -webkit-mask: linear-gradient(45deg, #000 50%, transparent 50%); mask: linear-gradient(45deg, #000 50%, transparent 50%); -webkit-mask-size: 500px 500px; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
弹幕也是这种原理
可以分为三个图层
1.主播的电脑桌面(游戏画面和主播的实际人物)
2.弹幕
3,主播实际人物的遮罩层(人物部分为透明,其他部分为非透明)
以上述例子,弹幕为background,主播实际人物遮罩层为mask
例子4
.main{ width: 500px; height:500px; background: url('./background.png') no-repeat; background-size: 500px 500px; position: relative;}.main:hover::before { position: absolute; content: ""; width: 500px; height: 500px; background: url("./overBackground.png"); background-size: 500px 500px; animation: maskRotate 2s ease-in-out;}//@for是sass的方法,没有安装sass自行修改@keyframes maskRotate { @for $i from 0 through 100 { #{$i}% { mask: linear-gradient( 45deg, #000 #{$i + "%"}, transparent #{$i + 5 + "%"} ); -webkit-mask: linear-gradient( 45deg, #000 #{$i + "%"}, transparent #{$i + 5 + "%"} ); } }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
引用于:
https://juejin.cn/post/7155780555554947102
https://www.jb51.net/css/641182.html
https://blog.csdn.net/weixin_41897680/article/details/122688152