# 选择符
# 样式的基本规则
# 元素选择符
通常是 HTML 选择符,HTML文档中的元素是最基本的选择符。
html{}
div{}
2
# 声明和关键字
{}
表示规则的声明块,可以有多条样式声明,声明格式为 属性: 值;
。
属性或值有误则本条声明将被忽略。
属性的值如果可以是多个关键字,通常以空格分隔,有时以斜线(/)分隔。
属性值中可以使用斜线的有:
- font
- background
- border-image
- border-radius
- grid
- grid-area
- grid-column
- grid-row
- grid-template
- mask-border
以逗号分隔的有:声明多个背景图像,过渡属性和阴影时,以及函数参数比如线性渐变 linear-gradient()
和变形函数 translate();
。
.box {
box-shadow: inset -1px -1px white, 3px 3px 3px rgba(0, 0, 0, 0.2);
background-image: url(myimage.png), linear-gradient(180deg, #fff 0%, #000 100%);
transform: translate(100px, 200px);
}
a:hover {
transition: color, background-color 200ms ease-in 50ms;
}
2
3
4
5
6
7
8
# 群组
# 群组选择符
以逗号分隔多个选择符,逗号告诉浏览器,后面的规则要应用到这群选择符中。
h2, p, div {}
# 通用选择符 *
匹配所有元素,但通用选择符虽然方便,但是它的特制度是 0-0-0 ,而且由于目标是一切元素,可能会出现一些意想不到的后果。
# 在旧的浏览器中使用新元素
比如 IE8 中不识别 <main>
元素,可使用如下 js 代码让 IE8 知道此元素的存在。
document.createElement('main');
运行后,IE8 将匀速选择并为其添加样式。
# 类选择符和 ID 选择符
# 类选择符
元素设置 class
属性,属性值之前加上点(.)就是类选择符。
<p class="para"></p>
.para {
color: red;
}
2
3
元素选择符结合类选择符
p.para {
color: red;
}
2
3
ID、类、属性、伪类、伪元素选择符之前如果没有元素选择符,默认为通用选择符。则作用到所有包含此类选择符的元素上。
*.para {
color: red;
}
2
3
# 多个类
一个元素可以包含多个类,以空格分隔,并且不分先后顺序。
<div class="color size"></div>
.color {
color: red;
}
.size {
font-size: 16px;
}
2
3
4
5
6
# ID 选择符 #
元素设置 id
属性,属性值前加上 #
号就是 id 选择符。
<p id="para"></p>
#para {
color: red;
}
2
3
# 属性选择符
之前的 id 选择符和类选择符都是选择的元素属性的值。属性选择符根据元素的属性来选择。
大致分为:简单属性选择符,精准属性选择符,部分匹配属性值选择符,起始值属性选择符。
# 简单属性选择符
选择具有某个属性的元素,而不管属性的值是什么。
/* 具有 class 属性的元素就会被选择 */
div[class] {
color: red;
}
/* 所有具有 title 属性的元素都会被选择 */
[title] {}
/* 同时具有多个属性才被选择 */
a[href][title] {}
2
3
4
5
6
7
8
9
10
11
# 精准属性选择符
元素不但具有某个属性,还需要属性值匹配才选择。
div[class="warning"] {}
/* 属性值带空格时,选择符中必须保持一致 */
div[class="warning color"][title="hello"] {}
2
3
4
# 部分匹配属性值选择符
foo|="bar"
有foo
属性值,属性值就是bar
或以bar-
开头则会被选中foo~="bar"
有foo
属性值,属性值以空格分隔的一组词,其中某个词是bar
即可匹配foo*="bar"
有foo
属性值,属性值中包含bar
即可匹配foo^="bar"
有foo
属性值,属性值以bar
开头foo$="bar"
有foo
属性值,属性值以bar
结尾
# |=
如果开发一个 CSS 框架或库,没必要提供 btn btn-small btn-arrow btn-active
这样冗长的类。
<button class="btn-small-arrow-active">Click Me</button>
*[class|='btn'] {
border-radius: 5px;
}
2
3
# ~=
<p class="urgent warning">hello</p>
p[class~='warning'] {
color: red;
}
2
3
其实此写法与普通类选择符是等效的。比如 p.warning
和 p[class~="warning"]
等效。
那么为何除了类选择符,还需要这样的选择符呢?因为除了类以外的其他属性还可以使用,比如 title
属性。
img[title~='Figure'] {
border: 1px solid gray;
}
2
3
如果多个元素都有 title
属性,并且 title
中都包含 Figure
这个词,则均可匹配。
# *=
比如,希望选中所有链接地址中包含 abc.com
的元素
a[href*='abc.com'] {
font-weight: bold;
}
2
3
# ^=
匹配以某个字符串开头的属性值
img[alt^='Figure'] {}
# $=
匹配以某个字符串结尾的属性值
img[src$='.jpg'] {}
# 不区分大小写的标识符
CSS Selectors Level 4 为属性选择符引入了一个不区分大小写的选项。在结束的方括号前加上 i
。
比如,选择所有指向 PDF 文档的链接,但不确定是 .pdf 还是 .PDF ,可以写成:
a[href$='.PDF' i]
注意,这个 i
只针对属性值,不针对属性名。
# 根据文档结构选择
# 后代选择符
多个选择符使用空格连接,空格后的选择符是空格前选择符的后代,样式只作用在最后一个指定的后代身上。
div p {}
div p span em {}
2
3
4
注意,后代元素的层级间隔可以是无限的,并且它对元素的距离一无所知。两个元素的距离对是否应用样式规则没有影响。遇到特指度和相互抵消规则时这一点很重要。
<div class="outer">
<div class="inner">
<span>hello</span>
</div>
</div>
2
3
4
5
.inner span {
color: blue;
}
.outer span {
color: blue;
}
2
3
4
5
6
最终应用的颜色是蓝色,虽然 .outer
离 span
更近,但后代元素无感。
# 子元素选择符 >
不想选择任意层级后代元素,只想选择下一层级的子元素时使用。
<div>
<p></p>
</div>
2
3
/* 只选择 div 下的 直接子元素 p 元素 */
div > p {}
2
# 选择后续相邻兄弟元素 +
选择紧跟在某一个元素之后的某个同级元素。
<div></div>
<p></p>
2
div + p {}
# 选择后续不管是否相邻的兄弟元素 ~
Selectors Level 3 引入的后续兄弟选择符 ~
```html
<div></div>
<p></p>
<a></a>
<p></p>
<span></span>
<p></p>
2
3
4
5
6
7
div ~ p {}
将会把 div
之后的不管是否相邻的所有同级的 p 元素都选中。
# 伪类选择符 :
可以为文档中不一定真实存在的结构指定样式,或者为某些元素(甚至文档本身)的特定状态赋予幽灵类。
# 拼接伪类
/* 鼠标悬停在未访问过的连接上时 */
a:link:hover {
color: red;
}
/* 鼠标悬停在已访问过的连接上时 */
a:visited:hover {
color: maroon;
}
2
3
4
5
6
7
8
9
(伪类的)顺序无关紧要,a:hover:link
和 a:link:hover
的效果是一样的。
同样的,可以为特定语言的不同状态的链接设置不同的样式,例如德语:
a:link:hover:lang(de) {
color: gray;
}
a:visited:hover:lang(de) {
color: silver;
}
2
3
4
5
6
注意,不要拼接相互排斥的伪类,比如,一个链接不可能既是已访问又是未访问。a:link:visited
没有任何意义,匹配不了任何东西。
# 结构伪类
注意,伪类始终指代的是所依附的元素。
比如 div:first-child
和 div > :first-child
, 前者选中的而是 div 元素,而且这个 div 元素 必须是它的父元素中的第一个元素才会被选中。后者选中的是 div 元素中的 第一个子元素。
# 选择根元素 :root
在 HTML 中,根元素是 <html>
,但在其他比如 XML
中,根元素则不是。
:root {}
以上则可选中根元素,在 HTML 中它则会选中 <html>
元素。
# 选择空元素 :empty
元素只有真的为空才会被选中,没有空白,没有可见内容(如文本),没有子元素。
如果使用 *:empty { display: none; }
禁止显示所有空段落,但这里有个问题,img
和 input
这样的空元素也会被匹配,也就是说, img{}
和 img:empty{}
其实是一样的匹配效果,只是权重不同而已。
截止2017年末,:empty
是唯一一个在匹配元素的时候考虑文本节点的 CSS 选择器。所有 Selectors Level 3 的其他选择器都只考虑元素节点,而完全忽略文本节点——例如,前面讨论过的兄弟组合器
# 唯一子元素 :only-child
/ 唯一类型元素 :only-of-type
/* img 元素如果是父元素中的唯一子元素则会被选中 */
img:only-child {border: 1px solid black;}
/* 选择 a 元素的任意层级后代中,img 是唯一子元素的时候,选中 img 元素 */
a[href] img:only-child {border: 2px solid black;}
2
3
4
5
以下三种情况都可以被选中:
<a href="http://w3.org/"><img src="w3.png" alt="W3C"></a>
<a href="http://w3.org/"><span><img src="w3.png" alt="W3C"></span></a>
<a href="http://w3.org/">
A link to
<span>
the
<img src="w3.png" alt="">
web
</span>
site
</a>
2
3
4
5
6
7
8
9
10
11
12
13
如果是写为 a[href] > img:onlychild
则只会匹配以上的第一种情况。
唯一类型元素 :only-of-type
<a href="http://w3.org/"><b>•</b><img src="w3.png" alt="W3C"></a>
<a href="http://w3.org/"><span><b>•</b><img src="w3.png" alt="W3C"></span></a>
2
a[href] img:only-of-type {border: 5px solid black;}
当 img
作为所有兄弟元素中的唯一的元素类型时,则被选中。
注意,此处的唯一类型指的是唯一的元素类型。
# (倒数)第一个子元素 :first-child
/ :last-child
<div>
<p></p>
<span></span>
<a></a>
</div>
2
3
4
5
/* 当 p 元素是父元素的第一个子元素时选中 p 元素 */
p:first-child {}
/* 当 a 元素是父元素中的最后一个子元素时选中 a 元素 */
a:last-child {}
/* :first-child 和 :last-child 一同使用就等效于 :only-child */
p:first-child:last-child{}
/* 等效于 */
p:only-child{}
2
3
4
5
6
7
8
9
10
# (倒数)第一个某类型元素 :first-of-type
/ :last-of-type
:first-of-type
从前往后查找在父元素中第一次出现的某个类型的元素。
:last-of-type
从后往前倒序查找在父元素中第一次出现的某个类型的元素
<div>
<p></p>
<span></span>
<a></a>
<div></div>
</div>
2
3
4
5
6
/* 选中父元素中第一次出现的 span 元素 */
span:first-of-type {}
/* 选中父元素中倒数第一次出现的 a 元素 */
a:last-of-type {}
2
3
4
5
# (每)(倒数)第 n 个子元素 :nth-child(n)
/ :nth-last-child(n)
选中(倒数)第 n 个子元素,n 可以为任意整数。
:nth-child(1)
就等同于 :first-child
。
:nth-last-child(1)
就等同于 :last-child
。
括号中还可以使用公式: :nth-child(xn)
或 :nth-child(xn ± y)
,其中 x 和 y 是具体的整数,n 就是照写,±b 可选。:nth-last-child(n)
用法相同。
/* 选中父元素中偶数位出现的 p 元素 */
p:nth-child(2n) {}
/* 关键字形式的 偶数位 */
p:nth-child(even) {}
/* 选中父元素中奇数位出现的 p 元素 */
p:nth-child(2n + 1) {}
/* 关键字形式的 奇数位 */
p:nth-child(odd) {}
/* 选中父元素中第 5 个元素之后的 p 元素 */
p:nth-child(n + 5) {}
/* 选择效果相同,权重更高的表示方法 */
p:nth-child(4) ~ p {}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* 如果父元素中只有一个 li 元素,则宽度为 100% */
li:only-child {width: 100%;}
/* 是第一个且是倒数第二个,是第二个且是倒数第一个,则宽度分别为 50% */
li:nth-child(1):nth-last-child(2),
li:nth-child(2):nth-last-child(1) {width: 50%;}
/* 是第一个且是倒数第三个,是第一个且是倒数第三个之后的所有 li 元素,宽度分别问 33.33% */
li:nth-child(1):nth-last-child(3),
li:nth-child(1):nth-last-child(3) ~ li {width: 33.33%;}
/* 是第一个且是倒数第四个,第一个且是倒数第四个之后的所有 li 元素,宽度分别问 25% */
li:nth-child(1):nth-last-child(4),
li:nth-child(1):nth-last-child(4) ~ li {width: 25%;}
2
3
4
5
6
7
8
9
10
11
12
13
14
# (每)(倒数)第 n 个某类型子元素 :nth-of-type()
/ :nth-last-oftype()
用法基本和 :nth-child(n)
/ :nth-last-child(n)
相同,唯一的区别是此处会按照类型来计数。
# 动态伪类
动态伪类可以用于任何元素。以下只是列出经常用于 a 元素上。
# 超链接伪类 a:link
/ a:visited
a:link
应用到具有 href 属性,且未被访问过的 a 元素上
a:visited
应用到已被访问过的 a 元素上,但出于安全考虑,可设置的样式有限制。隐私保护限制只能对已访问链接设置颜色相关的属性,其他属性会被忽略。
a {}
和 a:link {}
看起来相同,但前者无论有没有 href 属性都会选中,后者必须有 href 属性才会被选中。
# 用户操作伪类 :focus
/ :hover
/ :active
:focus
选中获得焦点的元素
:hover
选中鼠标指针悬停所在的元素
:active
选中激活的元素,比如鼠标按下的时候的那个元素
以上这些伪类常用于超链接,比如:
a:link {color: navy;}
a:visited {color: gray;}
a:focus {color: orange;}
a:hover {color: red;}
a:active {color: yellow;}
2
3
4
5
伪类的顺序很重要,通常是 link-visited-hover-active
,后来改为了 link-visited-focus-hover-active
。后文解释为什么要注重顺序,以及那些场景可以更改使用顺序。
当想把文档中所有鼠标悬停的元素文本都更改颜色时,可以设置:
body *:hover{
color: red;
}
2
3
# 动态样式引起的问题
例如,可以将访问和未访问的链接设置为一种字体大小,并将其悬停链接设置较大的字体。
a:link, a:visited {font-size: 13px;}
a:hover, a:active {font-size: 20px;}
2
当鼠标指针悬停在锚上时,用户代理会增加锚的大小。 或者,由于 :active
设置,当用户在触摸屏上触摸它时。
支持此行为的浏览器必须在锚点处于悬停状态时重绘文档,这可能会迫使对链接后面的所有内容进行重排。
# UI 状态伪类
:enabled
允许输入的UI元素(例如表单中的input):disabled
不允许输入的UI元素(例如表单中被禁止输入的input):checked
已经被选中的单选或复选框,无论是文档自身选中的还是用户点击选中的:indeterminate
没有被选中的单选或复选框,此状态只能由 DOM 脚本设定,不能由用户触发:default
被默认选中的单选、复选框或下拉框:valid
用户输入合法数据的元素:invalid
用户输入不合法数据的元素:in-range
用户输入的数据在指定大小(min 和 max)范围内的元素:out-of-range
用户输入的数据不在指定大小范围内的元素:required
要求用户必须输入数据的元素:optional
不强制要求用户必须输入数据的可选元素:read-write
可编辑元素:read-only
只读元素
# 锚点伪类 :target
当 URL 包含片段标识符时,它所指向的文档被称为目标(在CSS中)。因此,可以使用 :target
伪类唯一地设置作为 URL 片段标识符目标的所有元素的样式。
比如访问的页面为 http://www.w3.org/TR/css3-selectors/#target-pseudo
,这个URL的用井号分割的伪部分就是片段标识符。如果引用的页面(http://www.w3.org/TR/css3-selectors/
)具有ID为target-pseudo
的元素,则该元素将成为片段标识符的目标。
:target
样式不会在这两种情况下应用:
如果页面是通过没有片段标识符的URL访问的
如果通过具有片段标识符的URL访问该页面,但是该标识符与文档中的任何元素都不匹配
但是,更有趣的是,如果文档中的多个元素可以由片段标识符进行匹配,例如,如果作者在同一文档中错误地包含了三个单独的 <div id ="target-pseudo">
实例,会发生什么?
CSS 无需解决此问题,主要取决于浏览器会选择一个还是三个元素,CSS 会将 :target
样式都应用于浏览器选中的有效目标。
# 语言伪类 :lang
/* 使用语言伪类设定样式 */
*:lang(fr) {font-style: italic;}
/* 使用属性选择符设定样式,元素必须设置了 lang 属性才能匹配 */
*[lang|="fr"] {font-style: italic;}
2
3
4
5
通常,在同样的选择时,伪类选择符比属性选择符更可靠。
# 否定伪类 :not()
:not()
伪类依附在某个元素上,括号中是简单的选择符。
简单选择符,指的是没有 祖辈 - 后代 关系的的选择符,比如元素、通用、属性、类、ID或伪类选择符等。
虽然括号中放通用选择符是合法的,但其实是没有意义的。比如 p:not(*)
选择不是任何元素的 p 元素。
另外,元素选择符的否定伪类括号中放元素选择符也没有意义,比如 p:not(p)
,p:not(div)
。
注意,:not()
的括号中只能使用一个选择符,不能使用群组,连接符,后代选择符等。
/* 选择不是 section 元素的元素之中的所有 table 元素 */
*:not(section) > table
/* 选择不是表头元素 thead 的元素之中的 tr 中的 th 元素 */
*:not(thead)> tr > th
2
3
4
5
:not()
伪类不能嵌套使用,比如 p:not(:not(p))
,括号中也不能使用伪元素,因为不是简单选择符。
:not()
可以串在一起使用,相当于 “也不是” 的意思。
*.link:not(li):not(p) {font-style: italic;}
# 伪元素选择符
在 CSS 2 中都伪类和伪元素都使用一个冒号,但现在伪元素改为了使用一对冒号,比如 ::first-line
。 应该始终保持使用一对冒号 ::
。
注意,所有伪元素只能出现在选择符的最后,比如 p::first-line em {}
是无效的。这也表明一个选择符只能有一个伪元素。
# 首字母伪元素 ::first-letter
选择任何非行内元素中文本的首字母,首字母前后的标点符号也会被包含选中。
常用于排版中的首字母大写或首字母下沉效果。
# 首行伪元素 ::first-line
用于选中元素中文本的的第一行。
# 对 ::first-letter
和 ::first-line
的限制
目前,只能用于块级元素上,例如 div
,p
等。不能应用到行内元素上。
允许伪元素使用的CSS属性
::first-letter | ::first-line |
---|---|
All font properties | All font properties |
All background properties | All background properties |
All text decoration properties | All margin properties |
All inline typesetting properties | All padding properties |
All inline layout properties | All border properties |
All border properties | All text decoration properties |
box-shadow | All inline typesetting properties |
color | color |
opacity | opacity |
# 前置、后置伪元素 ::before
/ ::after
/* 在 h2 元素之中,加入前置内容(此处为两个方括号),并将颜色设为银色 */
h2::before {
content: "]]";
color: silver;
}
/* 在 body 元素中,加入后置内容(此处为一段文本) */
body::after {
content: "The End.";
}
2
3
4
5
6
7
8
9
10
之后会对 ::before
和 ::after
进行更深入的研究。