CSS基础知识拾遗(上)
没错,我又来开新坑了
本来打算消遣娱乐一下,但是这玩意太香了(
本系列是对《深入解析css》的摘录。如果想要了解更酷的CSS,希望去阅读原书。
今年的新书,东西不过时,我个人觉得讲的很好。
层叠
CSS,层叠样式表。层叠究竟是什么?我们将一系列规则称为层叠。其规则来自于三个层面:
- 样式表的来源
- 选择器的优先级
- 源码顺序
这一系列规则会确定一个 层叠值 。可以认为这个层叠值是一个优先级。
接下来我们一一予以说明。
样式表的来源
浏览器对于html的语法,存在着默认的样式。我们成为用户代理样式表。
假如你写一个平凡无奇的网页,列表左边会有小圆点,h1又大又粗,a是黄色的..这些都是用户代理样式。
用户代理样式具有最低的优先级。随意写什么css都可以覆盖掉,所以不要担心。
在规则中,有一类特殊的规则:重要声明。例如:
1 | <!DOCTYPE html> |
最终的结果会是绿色,因为一旦加了important之后,其优先级就会比作者其余自定义的所有样式都要高。
同时,如果用HTML的style
属性写样式,优先级会比外部引入的css文件或是style
标签内的样式要强。
总的来说,其优先级符合下面的排序:
!important
标注的样式- 利用
style
属性给出的样式 - 外部文件和
style
标签引用的样式 - 用户代理样式表
选择器的样式优先级
选择器的优先级遵循ID、类、标签的顺序。例如下面四个选择器:
1 | html body header h1 {} |
如果他们描述的是同一个元素的话,优先级是从低到高的。
具体来说,我们可以设置一个三元组<ID, 类, 标签>
分别表示选择器的数目。根据这一顺序进行排序,最后所得的就是优先级。
对此,我们常常使用优先级的提升或者降低来修改顺序。具体来说,加一个标签或是将标签换成类,效果会很好。
一般来说,不建议使用!important
,也最好尽可能回避标签。因为这会导致优先级过度提升,而不利于后续的进一步发展。
源码顺序
如果上述优先级都相同,那么最终的胜出者是源码位置比较靠后的标签。
这也是没办法的事情。毕竟青梅竹马胜不过天降。
这里就会涉及到一个很重要的问题:我们如何排列伪类?
对于超链接来说,一般使用的法则是LoVe/HAte
,即link visited hover active
,这样一般不容易出现奇妙的锅。
继承
在DOM中,子结点可以对父级元素的 某些 属性继承。
除此之外,可以用inherit关键字来继承父元素的值。
例如
1 | ul { |
通过强制继承可以保证子元素和父元素的行为一致。
有继承就应该存在不继承,对应的关键字是inherit
。例如
1 | ul { |
字体就是红色。
简写属性
我们常常用到font: italic bold 18px/1.2 "Arial"
这样的缩写,然而。。这玩意有坑
举个例子:
1 | h1 { |
这两个指向同一个元素。那么标题会加粗吗?
答案是否定的。
这是因为,font中默认将其他属性用normal或者其他方式填充。这个坑主要存在于font中,所以用font简写要千万小心。
还有一个就是简写属性的顺序问题,最常见的比如margin、padding。
其记忆口诀是TRouBLe
:top right bottom left
。而随着参数数量的减少,也变为
- 三个参数:上、左右、下
- 两个参数:上下、左右
- 一个参数:上下左右
相对单位
在传统的网页设计中,我们常常使用px作为单位。因此,早年间网页的解决方案是创建一个紧凑的居中容器,利用像素来布局。然而随着时代的演进,800px不能满足人们的需要了。1024px?1280px?而手机出现之后,曾经安全的800px也不再安全。由此孕育出的就是相对单位的大普及。
em
1em取当前元素的字号。例如
1 | .box { |
这样,我们会得到两个padding和圆角都不一样的盒子。
我们还可以用em定义字号,其相对是由父元素的值决定。例如:
1 | body { |
如果qwq
运用在了body
里的子对象,其值就是$16 \times 1.2$ .
这里就会有几个问题产生:
(1)字号和其他元素同时存在
1 | body { |
那么margin是多少?答案是$16 \times 1.2 \times 1.2$
所有的相对值都基于当前元素字号的计算结果。
(2)字体缩小
我们很常用到列表嵌套。例如下面的样式:
1 | body { |
那么假如有这样的东西
1 | <ul> |
那么a的字号是多少?$16 \times 0.8^3$。
离谱。有没有解决办法呢?可以用
1 | ul ul { |
解决,但是很不优雅。有没有更好的解决方法呢?使用rem
rem
rem是root em,也就是相对于根节点的大小。在上例中,我们只要设置ul
的属性为0.8 rem
就可以解决变小的情况。
常见的策略是这样的:
- 用rem设置字号
- 用px设置边框
- 用em设置内外边距和圆角
- 用百分比设置容器宽度
这里就会涉及到一个问题:如何设计默认字号?这里就要引出响应式设计
的概念。浏览器的默认字号是16px,那么可以这样设置:
1 | :root { |
就可以实现对不同窗口分别设计不同的默认字体。
是不是所有情况都适合用rem做字体单位呢?对于CSS来说,答案显然是否。
假设我们有三个箱子,大小不一样,但却字相对于箱子来说大小一样。那么我们可以这样实现:
1
2
3
4
5
6
7
8
9
10
11
12> .panel {
> font-size: 1rem;
> padding: 1em;
> border: 1px solid #999;
> border-radius: 0,5em;
> }
> .panel > h2 {
> margin-top: 0;
> font-size: 0.8em;
> font-weight: bold;
> }
>
那么假如我们需要一大一小两个箱子,只需要这样:
1
2
3
4
5
6
7> .panel.largeBox {
> font-size: 1.2rem;
> }
> .panel.smallBox {
> font-size: 0.8rem;
> }
>
由于em的相对性,我们的目标就实现了。
视口相对单位
相对于浏览器视口,我们有如下四个单位:
- vh:1/100的视口高度
- vw:1/100的视口宽度
- vmin:视口宽、高较小一方的1/100
- vmax:视口宽、高较大一方的1/100
一个很有趣的应用是设置一个大正方形,要求最大化:
1 | .square { |
另一个很有趣的应用是计算字号:
1 | :root { |
这使得字号从11.75px过渡到20px.
无单位数值
以下三个属性是支持无单位数值的三个常见属性:
- line-height
- z-index
- font-weight
其中比较特殊的是line-height属性。考察下面这个例子:
1 | body { |
结果是什么?答案是显示重叠。这是因为,line-height直接继承了父元素的数值计算结果。而如果我们设置为无单位数值1.2
,就可以正确显示。