约定:本文使用 jade 模板语言来表示简化的html结构
没接触过 jade 的同学,请看下面的小科普:
1 | <div class="father"> |
上面的html结构可用 jade 表示如下:
1 | div.father |
即:
- class用.表示
- id用#表示
- 属性值写在小括号里
- 用两个空格缩进来表示元素之间的层级关系
- // 表示注释
选择器种类
1.元素选择器
直接写元素名即可
1 | /* css code */ |
2.类选择器
以.开头
1 | // jade code |
1 | /* css code */ |
因为示例div带有两个类,因此还可以使用多个类选择,注意多个类之间不能有空格,不然就变成后代选择器了
1 | /* css code */ |
3. id选择器
以#开头1
2// jade code
span#child
1 | /* css code */ |
以上三个元素器其实是可以组合起来用的,如:
1 | p.class, |
这样的写法并不出错,但若非必要,并不推荐,理由是:
1. 浏览器根据css代码查找元素是从右到左查找的,也即先找到类为.class的元素,再看它是否为p元素。因此上述写法会增加浏览器的查找负担。
2.类/id选择器的速度都比元素选择器要快,所以如果可以使用类/id选择器来选择元素的话,何必再加多个元素选择,画蛇添足呢
3.选择不要“多得过分”。`html body header nav li a ` 像这样的选择器,看起来好像十分精确,但明显html与body是多余的,这样会降低浏览器查找效率的。一般而言,三四个类/元素的组合最佳。
4.实战表明,id选择器若非"情非得已"还是少用,多用类选择器与元素选择器(具体情况具体分析,记住id必须唯一)
4.属性选择器
使用[] 括号里面填写属性值,常用的有两种:
1 | //jade code |
1 | /* css code */ |
注意:
1.没有属性不等于某值的选择器,即 input[type!=”text”] 是行不通的
2.元素不指定属性则属性选择器选不到,故想选择input[type="text"]
时一定要显示指定input的type
3.input[type="text phone"]
这种写法是行不通的,只能老老实实地写input[type="text"],
input[type="phone"] {
}
5.根据文档结构选择
考虑下列文档结构
//jade code
body
header
ul
li
a(href="index.html") first link
li
a(href="about.html") second link
a#body-link(href="body.html") link in body
div#before-footer
footer
a(href="other.html") link in footer
5.1 选择后代
选择器之间带空格
1 | body a { |
5.2 选择孩子
使用 >
1 | body > a { |
5.3 选择相邻的兄弟
使用 + 选择下一个元素
1 | #before-footer + footer { |
5.4 选择后面所有的兄弟
使用 ~
如果元素之间间隔太远,使用 + 选择不到,可以使用 ~
1 | #body-link ~ footer { |
注意:
没有选择前面的兄弟的选择器
6.特殊选择器
特殊选择器分为伪类与伪元素。用于给文档元素添加特殊效果,增强表现力。
规范而言:
一个冒号开头的是伪类
两个冒号开头的是伪元素
6.1 伪类
伪类一般与行为/状态有关。可以认为是CSS选择器内置的类,与开发人员自定义的类区分开来(个人观点,帮助理解)
常用伪类
1 | :hover /*鼠标悬停时*/ |
把:first-child讲清楚,这个很容易被误解
考虑以下dom结构
1 | //jade code |
则 p:first-child 指的是#p1,
因为它意为:选择p元素,它是属于其父元素的第一个子元素
6.2 伪元素
伪元素因不存在于HTML文档中,故称为伪元素,与真正的元素区分开来
常用伪元素
::before
::after
注意:
1.以上两种伪元素在使用时,必须设置content属性,即使是空字符串 content:’’;也可以,否则是不会显示出来的
2.伪元素的初始位置是存在于真正的元素边框内部的
选择器权重
当出现多个选择器,或在使用UI框架想覆盖框架的样式时,选择器权重的知识成为关键。
1.特殊性
特殊性分为四个等级,越在前面就越高,当规则冲突时,特殊性最高的选择器胜出。
- 内联样式: 1,0,0,0
- ID选择器: 0,1,0,0
- 类选择/属性选择/伪类: 0,0,1,0
- 元素选择器/伪元素: 0,0,0,1
另: 结合符(> + ~)/通配符(*)不增加权重
来看一些例子帮助理解(为了直观,CSS代码写成一行,请勿在实践中模仿):
1 | h1{color:white;} 0,0,0,1 |
以上例子,越往下,选择器特殊性越高
2.重要声明
难道面对内联样式,不使用js,难道真的无法修改了吗?
不,我们还可以使用重要声明,即在普通声明的结束分号之前加上!important
:
1 | span.important |
1 | .important{ |
面对普通声明,重要声明总是胜出
重要声明一共有5级,权重由大到小排列如下:
1.读者的重要声明
2.开发人员的重要声明
3.开发人员的正常声明
4.读者的正常声明
5.用户代理的默认样式

3. 继承
基于继承机制,样式不仅应用到指定的元素,还会应用到它的后代元素
值不会向上传播.
只有一个例外:
body元素的背景样式可以传递到html元素,相应地可以定义画布.
继承的值根本没有特殊性,也即比0还要小.这一点绝不能等闲视之
这到底是什么意思呢?考虑下面的情况:
1 | div.article.font52 |
根据继承, p 元素继承了div的font52这个类,即字体大小为52px,
但由于使用的框架预设定了样式
1 | p { |
虽然权重很小,却也比继承的权重要大,因而元素 p的字体大小为14px
这就提醒我们:谨慎地使用通配符,小心地使用元素选择器,还有,不要太相信继承
另:
不能继承的值: 盒子模型(margin,padding,background), border
疑问:
但在实践中,我们会发现,如果设置了父元素的背景颜色,
如果不设置子元素的背景颜色,子元素背景色是与父元素的一致的,这难道不是继承?
使用控制台,查找子元素的样式规则,你的确找到不从父元素中继承的background-color属性。它其实是继承了来自浏览器的默认背景色:transparent(透明),因而看起来背景色与父元素的背景色一致。但这真不是继承。
4. 层叠
根据上面的知识,现在提出一个问题:
如果特殊性相同的选择器选中了同一个元素,那将会怎样呢?
“层叠样式表”这个名字可能会提供一点提示。CSS所基于的方法通过结合继承与特殊性,让样式层叠到一起的。其规则如下:
- 找出作用于给定元素的所有选择器
- 按声明重要性排序。声明来源有:开发人员,读者,用户代理(可简单理解为浏览器)默认样式。重要性声明胜出。
- 按特殊性排序。特殊性高的胜出。
- 按出现选择器出现顺序排序。一个声明出现在文档中越后面,则其权重越大。如果样式表中有导入样式表,一般认为出现在导入样式表中的声明在前,主样式表中的所有声明在后,也即权重越大。
以上是实践中会用到的CSS基础,希望能对大家有所帮助。