格好いいCSS

CSS基础知识拾遗(上)

没错,我又来开新坑了

本来打算消遣娱乐一下,但是这玩意太香了(

本系列是对《深入解析css》的摘录。如果想要了解更酷的CSS,希望去阅读原书。

今年的新书,东西不过时,我个人觉得讲的很好。

层叠

CSS,层叠样式表。层叠究竟是什么?我们将一系列规则称为层叠。其规则来自于三个层面:

  • 样式表的来源
  • 选择器的优先级
  • 源码顺序

这一系列规则会确定一个 层叠值 。可以认为这个层叠值是一个优先级。

接下来我们一一予以说明。

样式表的来源

浏览器对于html的语法,存在着默认的样式。我们成为用户代理样式表。

假如你写一个平凡无奇的网页,列表左边会有小圆点,h1又大又粗,a是黄色的..这些都是用户代理样式。

用户代理样式具有最低的优先级。随意写什么css都可以覆盖掉,所以不要担心。

在规则中,有一类特殊的规则:重要声明。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
ul li {
color: green !important;
}
#qwq li {
color: red;
}
</style>
</head>
<body>
<ul id="qwq">
<li> a </li>
<li> b </li>
</ul>
</body>
</html>

最终的结果会是绿色,因为一旦加了important之后,其优先级就会比作者其余自定义的所有样式都要高。

同时,如果用HTML的style属性写样式,优先级会比外部引入的css文件或是style标签内的样式要强。

总的来说,其优先级符合下面的排序:

  • !important标注的样式
  • 利用style属性给出的样式
  • 外部文件和style标签引用的样式
  • 用户代理样式表

选择器的样式优先级

选择器的优先级遵循ID、类、标签的顺序。例如下面四个选择器:

1
2
3
4
html body header h1 {}
body header.page-header h1{}
.page-header .title{}
#page-title {}

如果他们描述的是同一个元素的话,优先级是从低到高的。

具体来说,我们可以设置一个三元组<ID, 类, 标签>分别表示选择器的数目。根据这一顺序进行排序,最后所得的就是优先级。

对此,我们常常使用优先级的提升或者降低来修改顺序。具体来说,加一个标签或是将标签换成类,效果会很好。

一般来说,不建议使用!important,也最好尽可能回避标签。因为这会导致优先级过度提升,而不利于后续的进一步发展。

源码顺序

如果上述优先级都相同,那么最终的胜出者是源码位置比较靠后的标签。

这也是没办法的事情。毕竟青梅竹马胜不过天降。

这里就会涉及到一个很重要的问题:我们如何排列伪类?

对于超链接来说,一般使用的法则是LoVe/HAte,即link visited hover active ,这样一般不容易出现奇妙的锅。

继承

在DOM中,子结点可以对父级元素的 某些 属性继承。

除此之外,可以用inherit关键字来继承父元素的值。

例如

1
2
3
4
5
6
ul {
color: red;
}
ul li {
color: inherit;
}

通过强制继承可以保证子元素和父元素的行为一致。

有继承就应该存在不继承,对应的关键字是inherit。例如

1
2
3
4
5
6
ul {
color: red;
}
ul li {
color: initial;
}

字体就是红色。

简写属性

我们常常用到font: italic bold 18px/1.2 "Arial" 这样的缩写,然而。。这玩意有坑

举个例子:

1
2
3
4
5
6
h1 {
font-weight: bold;
}
.title {
font: 32px Helvetica, Arial, sans-serif;
}

这两个指向同一个元素。那么标题会加粗吗?

答案是否定的。

这是因为,font中默认将其他属性用normal或者其他方式填充。这个坑主要存在于font中,所以用font简写要千万小心。

还有一个就是简写属性的顺序问题,最常见的比如margin、padding。

其记忆口诀是TRouBLetop right bottom left 。而随着参数数量的减少,也变为

  • 三个参数:上、左右、下
  • 两个参数:上下、左右
  • 一个参数:上下左右

相对单位

在传统的网页设计中,我们常常使用px作为单位。因此,早年间网页的解决方案是创建一个紧凑的居中容器,利用像素来布局。然而随着时代的演进,800px不能满足人们的需要了。1024px?1280px?而手机出现之后,曾经安全的800px也不再安全。由此孕育出的就是相对单位的大普及。

em

1em取当前元素的字号。例如

1
2
3
4
5
6
7
8
9
10
11
.box {
padding: 1em;
border-radius: 1em;
background-color: lightgray;
}
.box-small {
font-size: 12px;
}
.box-big {
font-size: 16px;
}

这样,我们会得到两个padding和圆角都不一样的盒子。

我们还可以用em定义字号,其相对是由父元素的值决定。例如:

1
2
3
4
5
6
body {
font-size: 16px;
}
.qwq {
font-size: 1.2em;
}

如果qwq运用在了body里的子对象,其值就是$16 \times 1.2$ .

这里就会有几个问题产生:

(1)字号和其他元素同时存在

1
2
3
4
5
6
7
body {
font-size: 16px;
}
.qwq {
font-size: 1.2em;
margin: 1.2em
}

那么margin是多少?答案是$16 \times 1.2 \times 1.2$

所有的相对值都基于当前元素字号的计算结果。

(2)字体缩小

我们很常用到列表嵌套。例如下面的样式:

1
2
3
4
5
6
body {
font-size: 16px;
}
ul {
font-size: .8em;
}

那么假如有这样的东西

1
2
3
4
5
6
7
8
9
10
11
<ul>
<li>
<ul>
<li>
<ul>
<li>a</li>
</ul>
</li>
</ul>
</li>
</ul>

那么a的字号是多少?$16 \times 0.8^3$。

离谱。有没有解决办法呢?可以用

1
2
3
ul ul {
font-size: 1em;
}

解决,但是很不优雅。有没有更好的解决方法呢?使用rem

rem

rem是root em,也就是相对于根节点的大小。在上例中,我们只要设置ul的属性为0.8 rem就可以解决变小的情况。

常见的策略是这样的:

  • 用rem设置字号
  • 用px设置边框
  • 用em设置内外边距和圆角
  • 用百分比设置容器宽度

这里就会涉及到一个问题:如何设计默认字号?这里就要引出响应式设计的概念。浏览器的默认字号是16px,那么可以这样设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
:root {
font-size: 0.75em;
}
@media (min-width: 800px) {
:root {
font-size: 0.875em;
}
}
@media (min-width: 1200px) {
:root {
font-size: 1em;
}
}

就可以实现对不同窗口分别设计不同的默认字体。

是不是所有情况都适合用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
2
3
4
.square {
width: 100vmin;
height: 100vmin;
}

另一个很有趣的应用是计算字号:

1
2
3
:root {
font-size: calc(0.5em + 1vw);
}

这使得字号从11.75px过渡到20px.

无单位数值

以下三个属性是支持无单位数值的三个常见属性:

  • line-height
  • z-index
  • font-weight

其中比较特殊的是line-height属性。考察下面这个例子:

1
2
3
4
5
6
body {
line-hight: 1.2em;
}
.about {
font-size: 2em;
}

结果是什么?答案是显示重叠。这是因为,line-height直接继承了父元素的数值计算结果。而如果我们设置为无单位数值1.2,就可以正确显示。

# css, 前端

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×