前言
都说能用 CSS 尽量不要用 JS,一些合适的 CSS 甚至能让我们少写很多 JS,实现起来也更加简单。本文主要分享些好用的 CSS 技巧,接下来你将学到CSS变量的规则,函数与伪类在实践中的应用。
变量
声明规则
在声明时,变量名前需要加 --
,以表示为 CSS 变量。它和其他正常的属性没有太大区别,它的值可以是任何正常属性的值。所以 CSS 变量又叫做"CSS 自定义属性"。
body {
--main-color: #4d4e53;
--main-bg: rgb(255, 255, 255);
--logo-border-color: rebeccapurple;
--header-height: 68px;
--Header-height: 70px;
--content-padding: 10px 20px;
--base-line-height: 1.428571429;
--transition-duration: .35s;
--external-link: "external link";
--margin-top: calc(2vh + 20px);
}
需要注意的是变量名严格区分大小写,上面--header-height
和 --Header-height
为两个不同变量。
使用变量
读取变量使用 var()
函数,且在定义变量时也可以使用该函数:
div {
--main-color: #4d4e53;
--color: var(--main-color);
color: var(--color);
}
var()
函数还有第二个参数,该参数表示默认值,即变量不存在时,则使用默认值:
div {
color: var(--main-color, #7F583F);
}
第二个参数内部不处理逗号和空格,会把它们作为参数整体:
div {
font-family: var(--font-stack, "Roboto", "Helvetica");
padding: var(--content-padding, 20px 10 15px);
}
作用域
CSS 变量也有它自己的作用域,就像 JS 查找变量一样,首先查询自己的作用域,其次再逐层往上寻找。
:root {
--color: blue;
}
div {
--color: red;
}
.box {
--color: green;
}
* {
color: var(--color);
}
<div class="box">我是绿色</div>
<div>我是红色</div>
<span>我是蓝色</span>
虽然上面选择器使用的变量名是同样,但读取到值根据作用域来查找,所以每个元素的颜色也会不同。一般全局变量会放在 :root
中,以便任何选择器都能读取到。
JS 操作
在 JS 中提供了操作 CSS 变量的方法,这使得 CSS 变量可以根据不同的场景进行变化,更加的灵活。这些方法挂载在 Dom 的 style 属性上。
// 设置变量
document.body.style.setProperty('--color', '#7F583F');
// 读取变量
document.body.style.getPropertyValue('--color'); // '#7F583F'
// 删除变量
document.body.style.removeProperty('--color');
函数
calc()
calc()
可以说是开发中最常接触到的 CSS 函数,它主要用于动态计算 CSS 长度值。支持 + - * /
运算符,运算符左右必须有空格。
div {
width: calc(200px - -10%);
}
calc()
还能搭配 CSS 变量一起使用:
div {
--w: 20px;
width: calc(200px - var(--w));
}
除此之外还有一种应用场景,当 CSS 变量是一个纯数字时,可以使用该函数转为 CSS 长度单位:
div {
--w: 20;
width: calc(var(--w) * 1px);
height: calc(var(--w) * 5px);
}
attr()
attr()
用于获取选择元素的某个属性值,并用于其样式,但目前支持的仅有伪元素的 content 属性。
<p data-unit="km">89</p>
p[data-unit] {
font-size: 20px;
color: #333;
}
p[data-unit]::after {
content: attr(data-unit);
color: #999;
}
上面的应用场景好处在于,将文字聚焦到 html 中,维护起来可以一目了然,不至于从 html 再跳到 css 去修改伪元素的 content。
cubic-bezier()
cubic-bezier()
定义贝塞尔曲线,可用于 animation-timing-function
和 transition-timing-function
属性。一般场景下都会使用 css 自带的 ease
、ease-in
、ease-out
等动画曲线,贝塞尔曲线可以根据需求自定义不同的动画速度曲线。比如定义一个带有回弹效果的动画:
div {
transition: all 1s;
transition-timing-function: cubic-bezier(.72,.67,.3,1.18);
}
为了更好的调试出想要的效果,有两种方法:
第一种,在浏览器的控制台中,点击贝塞尔曲线的小图标调出调试面板,拖拽两个控制点,可以实施预览动画效果。
第二种,在线生成贝塞尔曲线:
drop-shadow()
drop-shadow()
函数将阴影效果应用于输入图像。开发中常用 box-shadow
来设置元素阴影,还有一种是 CSS3 提供的 drop-shadow()
阴影滤镜。它对比 box-shadow
的好处是能投影出不规则阴影。
<div class="box1">box-shadow</div>
<div class="box2">drop-shadow</div>
.box1{
box-shadow: 0 0 6px #ccc;
}
.box2{
filter: drop-shadow(0 0 6px #ccc);
}
可以看到使用 box-shadow
的元素,在小箭头处是没有阴影处理的,它只是基于盒子做投影。而 drop-shadow
就像是真实的阴影,元素是什么形状,阴影就是什么形状。
repeat()
repeat()
用于 grid 布局。当使用 grid-template-columns
定义相同单位的列会比较冗余,这时使用 repeat()
可以简化写法。
.container{
display: grid;
justify-content: space-between;
grid-template-columns: 150px 100px 150px 100px 150px 100px;
/* 简化写法 */
grid-template-columns: repeat(3, 150px 100px);
}
在不确定每行的个数时,使用 auto-fill
可以让 gird 自动计算,实现列表最后一行的左对齐。
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
.container{
--w: 150px;
display: grid;
justify-content: space-between;
grid-template-columns: repeat(auto-fill, var(--w));
grid-gap: 10px;
}
.item{
width: var(--w);
height: 120px;
background-color: lightskyblue;
}
伪类
:not
:not
匹配不符合一组选择器的元素。例如一个场景,每个列表项需要添加下边框线,一般最后一项是不需要的。通常我们会为每一项都设置下边框线,再单独设置最后一项的 border-bottom
为 0。使用 :not
也可以实现。
.item{
width: 200px;
height: 100px;
padding-bottom: 10px;
}
.item:not(:last-child) {
border-bottom: 1px solid #ccc;
}
上面表示除了最后一项,其他都加上 border-bottom
。
:target
:target
代表一个唯一的页面元素,其 id 与当前 URL 片段匹配。比如,地址为 loacalhost:3000#red,则选择中ID属性值为red的元素。或许可以应用到网页换肤功能中。
div {
display: inline-block;
width: 200px;
height: 200px;
}
#red:target {
background: lightpink;
}
#blue:target {
background: lightblue;
}
<body>
<div id="red">
<span>红色</span>
</div>
<div id="blue">
<span>蓝色</span>
</div>
<p>
<a href="#red">红色</a>
<a href="#blue">蓝色</a>
</p>
</body>
:empty
:empty
匹配没有子元素的元素。有时候列表的外层会包一层盒子,设置 padding 边距。当列表无数据返回时,外层盒子的 padding 会占用空间,使用 :empty
匹配无子元素时隐藏盒子,解决占用位置的问题。
.wrapper{
padding: 10px;
}
.wrapper:emtry{
display: none;
}