CSS编码技巧
尽量减少代码重复
代码可维护性的最大要素是尽量减少改动时要编辑的地方
比如,当我们需要改变一个按钮的字号,就得同时调整行高。而行高并没有反映出它跟字号的关系,因此我们通常需要算出字号改变之后的行高是多少。所以,当某些值相互依赖时,应该把他们相互关系用代码表达出来
font-size: 20px;
line-height: 1.5;
代码易维护 vs 代码量少
给一个元素添加一条10px的边框,但左侧不加边框
border-width: 10px 10px 10px 0;
或者:
border-width: 10px;
border-left-width: 0;
相比之下,第二条显然可读性更好,且更容易维护
CSS中有史以来的第一个变量
currentColor
没错,其实很多已有属性都具有类似的行为。比如,你没有给边框指定颜色,他就会自动的从文本颜色哪里得到颜色。
继承
说到继承,大家都很熟悉却很少用到它。
input, select, button {
font: inherit;
}
其实,在我们做提示框的小箭头啊使用伪类的时候非常有用:
.arrow-wrap {
position: relative;
}
.arrow-wrap::before {
content: '';
position: absolute;
top: 0;
left: 0;
background: inherit;
border: inherit;
}
这样,提示框的小箭头从父元素那里获取了背景色和边框样式
预处理器也不是完美无缺的
Stylus、Sass、Less都是常用的CSS预处理器
CSS文件体积和复杂度失控:在代码编译后很可能出现一些未知的问题
调试难度增加:控制台看见的并不是你写的源码
延时:通常需要一秒的时间把源码翻译成CSS
它们有它们自己的bug:因为预处理器也是人写的,也会有bug
原声特性通常比预处理器提供的版本要强大的多,因为他们是动态的(可以通过脚本操纵CSS)
比如,预处理器不知如何完成100% - 50px
这样的计算,因为在页面真正被渲染之前,百分比值是无法解析的。而原生CSS的calc()
在计算这样的表达式时没有任何压力。
背景与边框
半透明边框
在进入主题之前,我发现自己对于color
这个属性其实了解的很少。通常描述颜色只会用到关键字red
,或十六进制的rgb#ffffff
,实际上颜色可以有以下几种表示方法:
使用一个关键字
red
使用RGB立体坐标系统,以
#
加十六进制或rgb()
和rgba()
函数表达式的形式(红绿蓝+透明度)使用HSL圆柱坐标系统,以
hsl()
和hsla()
函数表达式的形式(色相饱和度明度 + 透明度)
实现一个半透明边框
我们通常这样写:
border: 10px solid hsla(0,0%,100%,.5)
background: white;
实际上,上面代码中背景会将这个半透明边框完全覆盖
隆重介绍一下这个属性background-clip
,这个属性的初始值是border-box
,意味着背景会被元素的border-box
裁掉。如果不希望背景侵入边框所在范围,需要把值设置为padding-box
,使用内边距外沿裁切背景。
border: 10px solid hsla(0,0%,100%,.5)
background: white;
background-clip: padding-box;
上面代码完美实现了半透明边框
多重边框
box-shadow 方案
我们通常使用box-shadow
实现阴影,不为人知的是,它接受第四个参数,扩张半径。通过指定正值或负值可以让投影面积加大或者减小。
background: yellowgreen;
box-shadow: 0 0 0 10px #655;
上面代码实现了一个宽度为10的实线边框,border
属性完全可以实现同样的效果,但是box-shadow
牛批的地方在于它支持逗号分隔语法,我们可以创建任意数量的投影。比如在这个实线边框外再加一个边框:
border: yellowgreen;
box-shadow: 0 0 0 10px #655,
0 0 0 15px deeppink;
但是,这个实线边框(扩张阴影)是逐层叠加的,所以实际上这个deeppink
的边框我们能看到的宽度是5px(15px - 10px = 5px)。
甚至你可以继续累加阴影效果:
border: yellowgreen;
box-shadow: 0 0 0 10px #655,
0 0 0 15px deeppink,
0 2px 5px 15px rgba(0,0,0,.6);
需要注意的是:投影行为和边框不完全一致,因为它不会影响布局,也不会受到box-sizing
影响。另一点是,它只是一个阴影,所以也不会影响鼠标事件
outline 方案
某些情况,如果只需要两层边框,就可以先设置一层常规边框,再加上outline
(描边)。这种方法的一大优点在于边框样式十分灵活(虚线),而box-shadow
方案只能模拟实线边框。
实现上面效果可以这样写:
background: yellowgreen;
border: 10px solid #655;
outline: 5px solid deeppink;
局限:只适用于双层边框
灵活的背景定位
background-position 的扩展语法方案
background-origin 方案
以上两种方案了解掌握,目前项目中背景图片的使用场景很少。通常是对元素的绝对定位。
calc()方案
calc()
函数在项目中使用频率比较高,通常用来计算一些动态的长度。比如给一个页面的header固定高度,计算内容部分的值就可以用到calc()
header{
height: 100px;
}
main {
height: calc(100% - 100px)
}
不要忘记在calc()
函数内部的-
运算符两侧各加一个空白符,否则会产生解析错误。
边框内圆角
场景:我们需要一个容器,只在内侧有圆角,而边框或描边的四个角在外部仍然保持直角的形状
通常这么写:
I have a nice subtle inner rounding, don’t I look pretty?
.wrap {
background: #655;
padding: .8em;
}
.wrap > div {
background: tan;
border-radius: .8em;
padding: 1em;
}
这样写没什么毛病,就是需要使用两个元素
如果只用一个元素实现,那么这样写:
background: tan;
border-radius: .8em;
padding: 1em;
box-shadow: 0 0 0 .6em #655;
outline: .6em solid #655;
这种写法得益于两个事实:
1、描边并不会跟着圆角走(因此显示出直角)
2、box-shadow
会跟着圆角走(实线的圆角边框)
因此,这两个条件叠加在一起达到了我们想要的效果
为box-shadow
指定的扩张至不一定要和描边宽度相同,只要是满足空缺的宽度即可
条纹背景
前置知识:linear-gradient 函数用于创建一个表示两种或多种颜色线性渐变的图片
场景:假设我们有一条基本的垂直线性渐变,颜色从#fb3
过渡到#58a
background: linear-gradient(#fb3, #58a)
当我们给这两个颜色一个区域比方说,就会变成这样:
background: linear-gradient(#fb3 50%, #58a 50%)
看起来完全不渐变了呢,那是因为如果多个色标具有相同的占比,它们会产生一个无限小的过滤区域,从效果上看,颜色会突然变化,而不是一个平滑渐变的过程。就像两块实色各占据一半的面积。
结合background-size
就可以创建条纹背景啦,因为背景在默认情况下是重复平铺的
background: linear-gradient(#fb3 50%, #58a 50%);
background-size: 100% 100px;
垂直条纹
垂直条纹的代码跟水平条纹几乎是一样的,差别主要在于:我们需要在开头加上一个额外参数来指定渐变方向。最后再把background-size
的值颠倒一下:
background: linear-gradient(to right, #fb3 50%, #58a 50%);
background-size: 100px 100%;
斜向条纹
repeating-linear-gradient()
和repeating-radial-gradient()
形状
自适应的椭圆
重新认识border-radius
,它有一个鲜为人知的真相,单独指定水平和垂直半径,用一个/
分隔这两个值。我们可以利用这个特性创建椭圆:
border-radius: 100px / 75px;
但是,这段代码存在一个很大的缺陷,只要元素尺寸发生变化,border-radius
的值就会跟着改变。
所以,border-radius
最好使用百分比值。这个百分比值会基于元素尺寸进行解析,即宽度用于水平半径解析,而高度用于垂直半径的解析。
border-radius: 50%;
持续更新。。。