1 概述
1.1为什么CSS选择器很强
CSS为样式服务,重表现,轻逻辑。
1.2CSS选择器世界的一些基本概念
1.2.1选择器、选择符、伪类和伪元素
选择器: 是CSS语句块前的标签、类名等,如body{font:menu}
中的body
选择符:后代选择符空格(),子选择符箭头(>),相邻兄弟选择符加号(+),随后兄弟选择符弯弯(~),列选择符双管道(||)。
(详见第4章)
伪类:与用户行为有关,前面有一个:
的,如:hover
伪元素:前面有两个冒号的
1.2.2CSS选择器的作用域
有局部作用域
Shadow DOM与局部作用域实例页面
1 | <p>我是一个普通的<p>元素,我的背景色是?</p> |
1 | // 创建 shadow DOM |
1.2.3 CSS选择器的命名空间
命名空间:namespace
作用:避免冲突
(了解即可)
1.3无效CSS选择器特性与实际应用
使用新的CSS选择器时,为了避免浏览器之间不同的支持程度,因此最好分开书写。
例外:浏览器可以识别以-webkit-私有前缀开头的伪元素
2 CSS选择器的优先级
2.1CSS优先级规则概览
级别越高,优先级越高:
- 0级:通配选择器(*)、选择符{
+
,>
,~
,空格,||
}、逻辑组合伪类:not(),:is(),:where
- 1级:标签选择器
body{},p{}
- 2级:类选择器
.foo{}
属性选择器[foo]{}
、伪类:hover{}
- 3级:id选择器
#foo{}
- 4级:style属性内联
<div style="color:#000000">
- 5级:!important顶级优先级
2.2深入CSS选择器优先级
2.2.1 CSS选择器优先级的计算规则
0级选择器:优先级数值+0;1级选择器:优先级数值+1;2级选择器:优先级数值+10;3级选择器:优先级数值+100;
优先级数值一样:遵循“后来居上”原则,后渲染的优先级高。这是相对于整个页面文档,所以css文件的引入顺序也很重要。
- 增加CSS优先级的技巧
- 重复选择器自身
.foo.foo{}
- 借助必然会存在的属性选择器
.foo[class]{}
- 重复选择器自身
2.2.2 256个选择器的越级现象
256个标签选择器的优先级大于类名选择器,因为出现了溢出。
3 CSS选择器的命名
3.1CSS选择器是否区分大小写
-选择器类型 | -示例 | -是否对大小写敏感 |
---|---|---|
标签选择器 | div{} | 不敏感 |
属性选择器-纯属性 | [attr] | 不敏感 |
属性选择器 | [attr=val] | 属性值敏感 |
类选择器 | .container{} | 敏感 |
ID选择器 | #foo{} | 敏感 |
3.2CSS选择器命名的合法性
类名选择器和ID选择器不能以数字开头
.\31-foo{}
<span class="1-foo">string</span>
以字符开头的选择器需要转义
支持中文字符和中文标点符号
支持emoji表情
3.3CSS选择器的命名是一个哲学问题
3.3.1长命名还是短命名
使用短命名
3.3.2单命名还是组合命名
- 使用前缀将常见的单词模块保护起来,避免冲突。
- 前缀最好是项目缩写。
- 一个项目的前缀最好统一。
3.3.3面向属性的命名和面向语义的命名
小项目使用面向语义的命名方式,大项目采用面向属性的命名和面向语义的命名结合。
面向属性的命名:
1 | .dn { display: none;} |
面向语义的命名则是根据应用元素所处的上下文来命名的。
1 | .header { background-color: #333; color:#fff;} |
3.4CSS选择器设计的最佳实践
3.4.1不要使用ID选择器
缺陷:
- 优先级太高,不利于覆盖和修改
- 可以使用属性选择器
[id="csId"]
- 可以使用属性选择器
- 和JavaScript耦合,产生bug
3.4.2不要嵌套选择器
会限制HTML的结构,不利于后期修改HTML,调整层级和位置。
错误示例:
1 | .nav a {} |
正确用法:使用无嵌套的类名选择器
3.4.3不要歧视面向属性的命名
3.4.4正确使用状态类名
3.4.5最佳实践汇总
- 命名
- 命名最好使用小写,用
-
或_
连接 - 不推荐驼峰命名,驼峰命名留给JavaScript DOM
- 组合个数控制在5个以下
- 设置统一前缀
- 命名最好使用小写,用
- 选择器类型选择
- 推荐用属性选择器代替id选择器
4 CSS选择符
4.1后代选择符空格( )
4.1.1对CSS后代选择符可能错误的认识
e.g
1 | <div class="lightblue"> |
4.1.2对JavaScript中后代选择符可能错误的认识
4.2子选择符箭头(>)
4.2.1子选择符和后代选择符的区别
子选择符只会匹配第一代子元素,后代选择符会匹配所有的后代。
4.2.2适合使用子选择符的场景
尽量不使用
子选择符会限制HTML的层级关系
使用场景:
- 状态类名控制
- 标签受限
- 层级位置判断
4.3相邻兄弟选择符加号(+)
只能选择相邻的兄弟元素,且只是选择后面一个兄弟。
4.3.1相邻兄弟选择符的相关细节
忽略文本节点
忽略注释
4.3.2实现类似:first-child的效果
.cs-li + p{color:#424242}
所有p元素都带cs-li属性,则只有第一个<p>
中的文字没有颜色设置。
4.3.3众多高级选择器技术的核心
配合伪类实现交互效果,如
1 | 用户名:<input><span class="cs-tips">不超过10个字符</span> .cs-tips{ |
4.4随后兄弟选择符弯弯(~)
4.4.1和相邻兄弟选择符区别
随后兄弟选择符会匹配后面所有的兄弟元素。
4.4.2为什么没有前面兄弟选择符
浏览器解析HTML是从前往后,从外往里进行。如果有前面兄弟选择符 ,网页呈现速度将大大减慢,浏览器会出现长时间的白板。
4.4.3如何实现前面兄弟选择符的效果
设置位置,将后面兄弟的位置设置在前面兄弟的前面。
flex布局实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<div class="cs-flex">
<input class="cs-input"><label class="cs-label">用户名</label>
</div>
.cs-flex{
display:inline-flex;
flex-direction: row-reverse;
}
.cs-input{
width:200px;
}
.cs-label{
width:64px;
}
:focus ~ .cs-label{
color:darkblue;
text-shadow: 0 0 1px;
}float浮动实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<div class="cs-float">
<input class="cs-input"><label class="cs-label">用户名</label>
</div>
.cs-float{
width:264px;
}
.cs-input{
float:right;
width:200px;
}
.cs-label{
display: block;
overflow:hidden;
}
:focus ~ .cs-label{
color:darkblue;
text-shadow: 0 0 1px;absolute绝对定位实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20.cs-absolute{
width:264px;
position:relative;
}
.cs-input{
margin-left: 64px;
width:200px;
}
.cs-label{
position:absolute;
left:0;
}
:focus ~ .cs-label{
color:darkblue;
text-shadow: 0 0 1px;
}
<div class="cs-absolute">
<input class="cs-input"><label class="cs-label">用户名</label>
</div>direction属性实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17.cs-direction{
direction: rtl;
}
.cs-direction .cs-label,.cs-direction .cs-input{
direction: ltr;
}
.cs-label{
display:inline-block;
}
:focus ~ .cs-label{
color:darkblue;
text-shadow: 0 0 1px;
}
<div class="cs-direction">
<input class="cs-input"><label class="cs-label">用户名</label>
</div>
4.5快速了解列选择符双管道(||)
5 元素选择器
5.1元素选择器的级联语法
元素选择器是唯一不能重复自身的选择器
级联使用时,元素选择器必须写在最前面。
5.2标签选择器二三事
5.2.1标签选择器混合其他选择器的优化
5.2.2标签选择器与自定义元素
5.3特殊的标签选择器:通配选择器
6 属性选择器
6.1 ID选择器和类选择器
语法不同
优先级不同
唯一性与可重复性
类可以重复使用,但id选择器要使用需要写完所有的id
1
2
3
4<button id="cs-button cs-button-primary">main</button>
#cs-button\20cs-button-primary{}
/*或者*/
[id~="cs-button"]
6.2属性值直接匹配选择器
- [attr]
- [attr=”val”]
- [attr~=”val”]
- [attr|=”val”]
6.2.1详细了解4种选择器
[attr]
- 只要包含了指定的属性就匹配,不关心属性的值
[attr=”val”]
- 属性值需要完全匹配
- 不区分单双引号
- 引号可以省略
- 属性值包含空格,则需要转义或者老老实实使用引号
[attr~=”val”]
属性值单词完全匹配选择器
属性值单词完全匹配选择器非常适合包含多种组合属性值的场景,例如,某元素共有9种 定位控制:
1
2
3
4
5
6
7
8
9<div data-align="left top"></div>
<div data-align="top"></div>
<div data-align="right top"></div>
<div data-align="right"></div>
<div data-align="right bottom"></div>
<div data-align="bottom"></div>
<div data-align="left bottom"></div>
<div data-align="left"></div>
<div data-align="center"></div>此时,最佳实践就是使用属性值单词完全匹配选择器:
1
2
3
4
5[data-align] { left: 5Ot;top:508;}
[data-align~="top"] { top: O;}
[data-align~="right"] { right:0;}
[data-align~="bottom"] { bottom: O;}
[data-align~="left"]{ left:0;}
[attr|=”val”]
- 属性值起止片段完全匹配选择器,属性的值要么是“val”,要么以”val”开头
6.2.2AMCSS开发模式简介
6.3属性值正则匹配选择器
- [attr^=”val”] 前匹配
- [attr$=”val”] 后匹配
- [attr*=”val”] 任意匹配
6.3.1详细了解3种选择器
- [attr^=”val”]
- 表示匹配attr属性值以字符val开头的元素
- 可以匹配中文,如果没有空格,则引号可以省略
- [attr$=”val”] 后匹配
- 表示匹配attr属性值以字符val结尾的元素
- [attr*=”val”] 任意匹配
- 表示匹配attr属性值包含字符val的元素
6.3.2 CSS属性选择器搜索过滤技术
1 | <input type="search" id="input" placeholder="输入城市名称或拼音" /> |
6.4忽略属性值大小写的正则匹配运算符
使用字符i或I作为运算符,可以忽略属性值大小写。
7 用户行为伪类
7.1 手型经过伪类:hover
- 不适用于移动端
- 在桌面端很常用
7.1.1 体验优化与:hover延时
1 | <table> |
7.1.2 非子元素的:hover显示
1 | <a href>图片链接</a> |
transition
对display
无过渡效果,对visibility
有过渡效果
7.1.3 纯:hover显示浮层的体验问题
使用:focus
避免用户没有鼠标,无法触发:hover
的情况
7.2激活状态伪类:active
7.2.1:active伪类概述
7.2.2按钮的通用:active样式技巧
- 适用于移动端开发
- 使用
box-shadow
处理反馈 - 使用线性渐变
linear-gradient
- 使用
7.3焦点伪类:focus
7.3.1:focus伪类匹配机制
只能匹配特定的元素,如
- 非disable状态的表单元素,如
<input>
输入框,<select>
下拉框,<button>
按钮 - 包含
<herf>
的<a>
元素 <summary>
<area>
7.3.2:focus伪类与outline
设置ontline:none
后,最好添加一个样式,如border-color:HighLight
,防止用户使用键盘输入时没有响应。
7.3.3 CSS:focus伪类与键盘无障碍访问
7.4整体焦点伪类:focus-within
7.4.1 :focus-within和:focus伪类的区别
:focus:当前元素处于聚焦样式才会匹配
:focus-within:当前元素或任意子元素处于聚焦样式会匹配
7.4.2 :focus-within实现无障碍访问的下拉列表
1 | <div class="cs-bar"> |
7.5键盘焦点伪类:focus-visible
鼠标访问时不会有焦点轮廓,但键盘tab键访问时会有。
1 | <style> |
8 URL定位伪类
8.1链接历史伪类:link和:visited
8.1.1深入理解:link
:link匹配页面上链接没有访问过的<a>
元素
8.1.2 怪癖最多的CSS伪类:visited
支持的CSS属性有限
支持子选择器
没有半透明
只能重置,不能凭空设置
1
2
3
4
5
6
7
8<a href>link</a>
/*不会出现背景色*/
a{color:blue}
a:visited{color:red;background:grey}
/*会出现背景色*/
a{color:blue;background:write}
a:visited{color:red;background:grey}无法获取:visited的设置和呈现的色值
8.2超链接伪类:any-link
- 匹配所有设置了href的链接元素
- 匹配所有匹配
:link
:visited
的元素
8.3目标伪类:target
8.3.1:target与锚点
8.3.2:target交互布局技术简介
8.4目标容器伪类:target-within
9 输入伪类
9.1输入控件状态
9.1.1可用状态与禁用状态伪类:enabled和:disabled
9.1.2读写特性伪类:read-only和:read-write
9.1.3占位符显示伪类:placeholder-shown
9.1.4默认选项伪类:default
9.2 输入值状态
与单选框和复选框相关:
1 | <input type="radio"><input type="checkbox"> |
9.2.1选中选项伪类:checked
1 | input:checked{ |
相当于
input[checked]{box-shadow:0 0 0 2px red;}
9.2.2不确定值伪类:indeterminate
9.3输入值验证
9.3.1有效性验证伪类:valid和:invalid
9.3.2 范围验证伪类:in-range 和:out-of-range
9.3.3可选性伪类:required和:optional
9.3.4用户交互伪类:user-invalid和空值伪类:blank
10 树结构伪类
10.1:root伪类
10.1.1:root伪类和<html>
元素
root伪类表示文档根元素
10.1.2:root伪类的应用场景
滚动条出现时页面不跳动
1
2
3
4
5
6
7
8
9
10
11
12
13/*IE 8*/
html{
overflow-y:scroll;
}
/*IE 9+*/
:root{
overflow-x:hidden;
}
:root body{
position :absolute;
width: 100vw;
overflow:hidden;
}定义CSS变量
10.2:empty伪类
匹配空标签元素
匹配前后闭合的替换元素
匹配非闭合元素
10.2.1对:empty伪类可能的误解
- 元素内有注释则不匹配
- 元素内有空格或标签或换行则不匹配
- 元素内有注释则不匹配
10.2.2超实用超高频使用的:empty伪类
- 字段缺失智能提示
10.3 子索引伪类
10.3.1 :first-child伪类和:last-child伪类
:first-child
伪类匹配第一个子元素
:last-child
伪类匹配最后一个子元素
10.3.2 :only-child伪类
匹配没有任何兄弟的元素
1 | <!-- 1. 只有加载图片 --> |
10.3.3 :nth-child()伪类和:nth-last-child()伪类
:nth-child()伪类 从前面开始匹配
:nth-last-child()伪类 从后面开始匹配
下面来看一些示例,快速了解一下各种类型的参数的含义。tr:nth-child(odd)
:匹配表格的第1,3,5行,等同于tr:nth-child(2n+1)
。
tr:nth-child (even)
:匹配表格的第2,4,6行,等同于tr:nth-child(2n)
。
:nth-child(3)
:匹配第3个元素。:nth-child(5n)
:匹配第5,10,15,..个元素。其中5=5x1,10=5x2,15=5x3
:nth-child(3n+4)
:匹配第4,7,10,.个元素。其中4=(3x0)+4,7=(3x1)+4, 10=(3x2)+4..
:nth-child(-n+3):
匹配前3个元素。因为-0+3=3,-1+3=2,-2+3-1.
li:nth-child(n):
匹配所有的<1i>元素,就匹配的元素而言和li标签选择器一 模一样,区别就是优先级更高了。实际开发总是避免过高的优先级,因此没有任何理 由这么使用。li:nth-child(1):
匹配第一个
li:first-child
匹配的作用一样, 区别就是后者的兼容性更好,因此,也没有任何这么使用的理由,使用:first-child
代替它。li:nth-child(n+4):nth-child(-n+10):
匹配第4~10个<li>
元素,这个就 属于比较高级的用法了。例如,考试成绩是前3名的有徽章,第4名到第10名高亮显 示,此时,这种正负值组合的伪类就非常好用。10.4匹配类型的子索引伪类
10.4.1 :first-of-type伪类和:last-of-type伪类
:first-of-type 匹配当前标签类型元素的第一个
:last-of-type伪类 匹配当前标签类型元素的最后一个
10.4.2 :only-of-type伪类
:only-of-type伪类 匹配唯一的标签类型元素
10.4.3 :nth-of-type()伪类和:nth-last-of-type()伪类
:nth-of-type()伪类 匹配指定索引的当前标签元素
11 逻辑组合伪类
11.1否定伪类:not()
匹配与括号内的选择器匹配不上的元素,如
:not(p)
匹配不是<p>
的元素
可以不断级联,如input:not(disable):not(read-only){}