# pseudo伪类伪元素
TIP
CSS introduces the concepts of pseudo-elements and pseudo-classes to permit formatting based on information that lies outside the document tree.
TIP
- 伪类用于当已有元素处于的某个状态时,为其添加对应的样式,这个状态是根据用户行为而动态变化的
比如说,当用户悬停在指定的元素时,我们可以通过:hover 来描述这个元素的状态。虽然它和普通的 css 类相似,可以为已有的元素添加样式,但是它只有处于 dom 树无法描述的状态下才能为元素添加样式,所以将其称为伪类。 - 伪元素用于创建一些不在文档树中的元素,并为其添加样式
比如说,我们可以通过:before 来在一个元素前增加一些文本,并为这些文本添加样式。虽然用户可以看到这些文本,但是这些文本实际上不在文档树中。
# 使用伪元素实现超实用的图标库
# isnot
# not
非选择,排除括号内的其它元素
最简单的例子,用CSS将div内,在不改变html的前提下,除了P标签,其它的字体颜色变成蓝色,
<div>
<span>我是蓝色</span>
<p>我是黑色</p>
<h1>我是蓝色</h2>
<h2>我是蓝色</h2>
<h3>我是蓝色</h3>
<h4>我是蓝色</h4>
<h5>我是蓝色</h5>
</div>
2
3
4
5
6
7
8
9
之前的做法
div span,div h2,div h3, div h4,{
color: blue;
}
2
3
not写法
div:not(p){
color: blue;
}
2
3
从上面的例子可以明显体会到not伪类选择器的作用
下面升级一下,问:将div内除了span和p,其它字体颜色变蓝色
div:not(p):not(span){
color: blue;
}
2
3
还有更为简洁的方法,如下,但是目前兼容不太好,不建议使用
div:not(p,span){
color: blue;
}
2
3
# is
将header和main下的p标签,在鼠标hover时文字变蓝色
<header>
<ul>
<li><p>鼠标放上去变蓝色</p></li>
<li><p>鼠标放上去变蓝色</p></li>
</ul>
<p>正常字体</p>
</header>
<main>
<ul>
<li><p>鼠标放上去变蓝色</p></li>
<li><p>鼠标放上去变蓝色</p></li>
<p>正常字体</p>
</ul>
</main>
<footer>
<ul>
<li><p>正常字体</p></li>
<li><p>正常字体</p></li>
</ul>
</footer>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
之前的做法
header ul p:hover,main ul p:hover{
color: blue;
}
2
3
is写法
:is(header, main) ul p:hover{
color: blue;
}
2
3
从上面的例子大概能看出is的左右,但是并没有完全体现出is的强大之处,但是当选择的内容变多之后,特别是那种层级较多的,会发现is的写法有多简洁,拿MDN的一个例子看下
之前的写法
/* Level 0 */
h1 {
font-size: 30px;
}
/* Level 1 */
section h1, article h1, aside h1, nav h1 {
font-size: 25px;
}
/* Level 2 */
section section h1, section article h1, section aside h1, section nav h1,
article section h1, article article h1, article aside h1, article nav h1,
aside section h1, aside article h1, aside aside h1, aside nav h1,
nav section h1, nav article h1, nav aside h1, nav nav h1 {
font-size: 20px;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
is写法
/* Level 0 */
h1 {
font-size: 30px;
}
/* Level 1 */
:is(section, article, aside, nav) h1 {
font-size: 25px;
}
/* Level 2 */
:is(section, article, aside, nav)
:is(section, article, aside, nav) h1 {
font-size: 20px;
}
2
3
4
5
6
7
8
9
10
11
12
13
WARNING
随着嵌套层级的增加,is的优势越来越明显
# 伪类与伪元素的区别
举例说明
<ul>
<li>我是第一个</li>
<li>我是第二个</li>
</ul>
2
3
4
- 1、如果想要给第一项添加样式,可以在为第一个
<li>添加一个类,并在该类中定义对应样式:
<ul>
<li class="first-item">我是第一个</li>
<li>我是第二个</li>
</ul>
2
3
4
li.first-item {
color: orange
}
2
3
如果不用添加类的方法,我们可以通过给设置第一个<li> 的:first-child 伪类来为其添加样式。这个时候,被修饰的<li> 元素依然处于文档树中。
li:first-child {
color: orange
}
2
3
- 2、下面是另一个简单的 html 段落片段:
<p>Hello World, and wish you have a good day!</p>
如果想要给该段落的第一个字母添加样式,可以在第一个字母中包裹一个<span> 元素,并设置该 span 元素的样式
<p><span class="first">H</span>ello World, and wish you have a good day!</p>
.first {
font-size: 5em;
}
2
3
如果不创建一个<span> 元素,我们可以通过设置<p> 的:first-letter 伪元素来为其添加样式。这个时候,看起来好像是创建了一个虚拟的<span> 元素并添加了样式,但实际上文档树中并不存在这个<span> 元素。
p:first-letter {
font-size: 5em;
}
2
3
从上述例子中可以看出
伪类与伪元素的区别
伪类的操作对象是文档树中【已有的元素】,而伪元素则创建了一个【文档树外的元素】。因此,伪类与伪元素的区别在于:有没有创建一个文档树之外的元素。
# 伪元素是使用单冒号还是双冒号
单冒号还是双冒号
CSS3 规范中的要求使用双冒号 (::) 表示伪元素,以此来区分伪元素和伪类,比如::before 和::after 等伪元素使用双冒号 (:😃,:hover 和:active 等伪类使用单冒号 (:)。除了一些低于 IE8 版本的浏览器外,大部分浏览器都支持伪元素的双冒号 (:😃 表示方法。
然而,除了少部分伪元素,如::backdrop 必须使用双冒号,大部分伪元素都支持单冒号和双冒号的写法,比如::after,写成:after 也可以正确运行。
Please note that the new CSS3 way of writing pseudo-elements is to use a double colon, eg a::after { ... }, to set them apart from pseudo-classes. You may see this sometimes in CSS. CSS3 however also still allows for single colon pseudo-elements, for the sake of backwards compatibility, and we would advise that you stick with this syntax for the time being.
# 伪类与伪元素的具体用法-伪类
# 状态
| 状态类伪类 | 含义 |
|---|---|
| 1 :link | 选择未访问的链接 |
| 2 :visited | 选择已访问的链接 |
| 3 :hover | 选择鼠标指针浮动在其上的元素 |
| 4 :active | 选择活动的链接 |
| 5 :focus | 选择获取焦点的输入字段 |
# 结构化
- 1 :not——一个否定伪类,用于匹配不符合参数选择器的元素。
<ul>
<li class="first-item">一些文本</li>
<li>一些文本</li>
<li>一些文本</li>
<li>一些文本</li>
</ul>
2
3
4
5
6
如下例,除了第一个<li> 元素外,其他<li> 元素的文本都会变为橙色。
li:not(.first-item) {
color: orange;
}
2
3
- 2 :first-child——匹配元素的第一个子元素。
- 3 :last-child——匹配元素的最后一个子元素。
- 4 :first-of-type——匹配属于其父元素的首个特定类型的子元素的每个元素。
如下例,第一个<li> 元素和第一个<span> 元素的文本会变为橙色。
<ul>
<li>这里的文本是橙色的</li>
<li>一些文本 <span>这里的文本是橙色的</span></li>
<li>一些文本</li>
</ul>
2
3
4
5
ul :first-of-type {
color: orange;
}
2
3
- 6 :nth-child——根据元素的位置匹配一个或者多个元素,它接受一个
an+b形式的参数,an+b匹配到的元素示例如下:
nth-child
1n+0,或 n,匹配每一个子元素。
2n+0,或 2n,匹配位置为 2、4、6、8… 的子元素,该表达式与关键字 even 等价。
2n+1 匹配位置为 1、3、5、7… 的子元素、该表达式与关键字 odd 等价。
3n+4 匹配位置为 4、7、10、13… 的子元素。
选择第二个元素,”Beta” 会变成橙色:
ol :nth-child(2) {
color: orange;
}
2
3
选择位置序号是 2 的倍数的元素,”Beta”, “Delta”, “Zeta”, “kappa” 会变成橙色:
ol :nth-child(2n) {
color: orange;
}
2
3
选择位置序号为偶数的元素:
ol :nth-child(even) {
color: orange;
}
2
3
选择从第 6 个开始,位置序号是 2 的倍数的元素,”Zeta”, “Theta”, “Kappa” 会变成橙色:
ol :nth-child(2n+6) {
color: orange;
}
2
3
- 7 :nth-last-child——与:nth-child 相似,不同之处在于它是从最后一个子元素开始计数的。
- 8 :nth-of-type——nth-child 相似,不同之处在于它是只匹配特定类型的元素。
如下例,第二个<p> 元素会变为橙色。
<article>
<h1>我是标题</h1>
<p>一些文本</p>
<a href=""><img src="images/rwd.png" alt="Mastering RWD"></a>
<p>这里的文本是橙色的</p>
</article>
2
3
4
5
6
p:nth-of-type(2) {
color: orange;
}
2
3
- 9 :nth-last-type——与 nth-of-type 相似,不同之处在于它是从最后一个子元素开始计数的。
- 10 :only-child——当元素是其父元素中唯一一个子元素时,:only-child 匹配该元素。
<ul>
<li>这里的文本是橙色的</li>
</ul>
<ul>
<li>一些文本</li>
<li>一些文本</li>
</ul>
2
3
4
5
6
7
8
ul :only-child {
color: orange;
}
2
3
- 11 :only-of-type——当元素是其父元素中唯一一个特定类型的子元素时,:only-child 匹配该元素。
- 12 :target——当 URL 带有锚名称,指向文档内某个具体的元素时,:target 匹配该元素。
如下例,url 中的 target 命中 id 值为 target 的 article 元素,article 元素的背景会变为黄色。
URL:http://example.com/#target
<article id="target">
<h1><code>:target</code> pseudo-class</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit!</p>
</article>
2
3
4
:target {
background: yellow;
}
2
3
# 表单相关
- 1 :checked——:checked 匹配被选中的 input 元素,这个 input 元素包括 radio 和 checkbox。
<input type="checkbox"/>
<label>我同意</label>
2
input:checked + label {
background: yellow;
}
2
3
- 2 :default——:default 匹配默认选中的元素,例如:提交按钮总是表单的默认按钮。
如下例,只有提交按钮的背景变成了黄色。
<form action="#">
<button>重置</button>
<button type="submit">提交</button>
</form>
2
3
4
:default {
background: yellow;
}
2
3
- 3 :disabled——:disabled 匹配禁用的表单元素。
如下例,被禁用 input 输入框的透明度会变成 50%。
<input type="text" disabled/>
:disabled {
opacity: .5;
}
2
3
- 4 :empty——:empty 匹配没有子元素的元素。如果元素中含有文本节点、HTML 元素或者一个空格,则:empty 不能匹配这个元素。
如下例,:empty 能匹配的元素会变为黄色。
第一个元素中有文本节点,所以其背景不会变成黄色;
第二个元素中有一个空格,有空格则该元素不为空,所以其背景不会变成黄色;
第三个元素中没有任何内容,所以其背景会变成黄色;
第四个元素中只有一个注释,此时该元素是空的,所以其背景会变成黄色;
<div>这个容器里的背景是橙色的</div>
<div> </div>
<div></div>
<div><!-- This comment is not considered content --></div>
2
3
4
div {
background: orange;
height: 30px;
width: 200px;
}
div:empty {
background: yellow;
}
2
3
4
5
6
7
8
9
- 5 :enabled——:enabled 匹配没有设置 disabled 属性的表单元素。
- 6 :in-range——:in-range 匹配在指定区域内元素。
如下例,当数字选择器的数字在 5 到 10 是,数字选择器的边框会设为绿色。
<input type="number" min="5" max="10">
input[type=number] {
border: 5px solid orange;
}
input[type=number]:in-range {
border: 5px solid green;
}
2
3
4
5
6
7
- 7 :out-of-range——与:in-range 相反,它匹配不在指定区域内的元素。
- 8 :indeterminate——indeterminate 的英文意思是“ 不确定的”。当某组中的单选框或复选框还没有选取状态时,:indeterminate 匹配该组中所有的单选框或复选框。
如下例,当下面的一组单选框没有一个处于被选中时,与 input 相邻的 label 元素的背景会被设为橙色。
<ul>
<li>
<input type="radio" name="list" id="option1">
<label for="option1">Option 1</label>
</li>
<li>
<input type="radio" name="list" id="option2">
<label for="option2">Option 2</label>
</li>
<li>
<input type="radio" name="list" id="option3">
<label for="option3">Option 3</label>
</li>
</ul>
2
3
4
5
6
7
8
9
10
11
12
13
14
:indeterminate + label {
background: orange;
}
2
3
- 9 :valid——:valid 匹配条件验证正确的表单元素。
如下例,当 email 输入框内的值符合 email 格式时,输入框的边框会被设为绿色。
<input type="email"/>
input[type=email]:valid {
border: 1px solid green;
}
2
3
- 10 :invalid——:invalid 与:valid 相反,匹配条件验证错误的表单元素。
- 11 :optional——:optional 匹配是具有 optional 属性的表单元素。当表单元素没有设置为 required 时,即为 optional 属性。
如下例,第一个 input 的背景不会被设为黄色,第二个 input 的背景会被设为黄色。
<input type="text" required />
<input type="text" />
2
:optional {
background: yellow;
}
2
3
- 12 :required——:required 与:optional 相反匹配设置了 required 属性的表单元素。
- 13 :read-only——:read-only 匹配设置了只读属性的元素,表单元素可以通过设置“readonly” 属性来定义元素只读。
如下例,input 元素的背景会被设为黄色。
<input type="text" value="I am read only" readonly>
input:read-only {
background-color: yellow;
}
2
3
- 14 :read-write——:read-write 匹配处于编辑状态的元素。input,textarea 和设置了 contenteditable 的 HTML 元素获取焦点时即处于编辑状态。
如下例,input 输入框和富文本框获取焦点时,背景变成黄色。
<input type="text" value="获取焦点时背景变黄"/>
<div class="editable" contenteditable>
<h1>点击这里可以编辑</h1>
<p>获取焦点时背景变黄</p>
</div>
2
3
4
5
6
:read-write:focus {
background: yellow;
}
2
3
- 15 :scope(处于试验阶段)——:scope 匹配处于 style 作用域下的元素。当 style 没有设置 scope 属性时,style 内的样式会对整个 html 起作用。
目前支持这个伪类的浏览器只有火狐。
# 语言相关
- 1 :dir(处于实验阶段)——:dir 匹配指定阅读方向的元素,当 HTML 元素中设置了 dir 属性时该伪类才能生效。现时支持的阅读方向有两种:ltr(从左往右)和 rtl(从右往左)。目前,只有火狐浏览器支持:dir 伪类,并在火狐浏览器中使用时需要添加前缀 (
-moz-dir())。
<article dir="rtl">
<p>التدليك واحد من أقدم العلوم الصحية التي عرفها الانسان والذي يتم استخدامه لأغراض الشفاء منذ ولاده الطفل.</p>
</article>
2
3
article :-moz-dir(rtl) {
color: orange;
}
/* unprefixed */
article :dir(rtl) {
color: orange;
}
2
3
4
5
6
7
8
- 2 :lang——:lang 匹配设置了特定语言的元素,设置特定语言可以通过为了 HTML 元素设置 lang=”” 属性,设置 meta 元素的 charset=”” 属性,或者是在 http 头部上设置语言属性。
实际上,lang=”” 属性不只可以在 html 标签上设置,也可以在其他的元素上设置。
# CSS3伪类:valid和:invalid实现表单校验
- 1、
:valid用于匹配输入值为合法的元素 - 2、
:invalid用于匹配输入值为非法的元素 - 3、
required属性规定必需在提交之前填写输入字段 - 4、
pattern属性规定用于验证输入字段的正则表达式
注意:
:valid/:invalid选择器只作用于能指定区间值的元素,例如 input 元素中的 min 和 max属性,及正确的 email 字段, 合法的数字字段等。
required属性适用于以下<input>类型:text, search, url, telephone, email, password, date pickers, number, checkbox, radio 以及 file。当然textarea也可以。
- :valid、:invalid示例
<style>
input{
display: block;
padding: 0 20px;
outline: none;
border: 1px solid #ccc;
width: 150px;
height: 40px;
transition: all 300ms;
}
// input内容合法,边框颜色是绿色
input:valid {
border-color: green;
box-shadow: inset 5px 0 0 green;
}
// input内容非法,边框颜色是红色
input:invalid {
border-color: red;
box-shadow: inset 5px 0 0 red;
}
</style>
<input type="text" placeholder="请输入你的手机" pattern="^1[3456789]\d{9}$" required>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- required示例
<form>
<input type="text"
placeholder="请输入你的手机"
pattern="^1[3456789]\d{9}$"
required
>
<button type="submit">提交</button>
</form>
2
3
4
5
6
7
8
# 伪元素
- 1 ::before/:before——:before 在被选元素前插入内容。需要使用 content 属性来指定要插入的内容。被插入的内容实际上不在文档树中。
<h1>World</h1>
h1:before {
content: "Hello ";
}
2
3
- 2 ::after/:after——:after 在被元素后插入内容,其用法和特性与:before 相似。
- 3 ::first-letter/:first-letter——:first-letter 匹配元素中文本的首字母。被修饰的首字母不在文档树中。
- 4 ::first-line/:first-line——:first-line 匹配元素中第一行的文本。这个伪元素只能用在
块元素中,不能用在内联元素中。
p:first-line {
background: orange;
}
2
3
- 5 ::selection——::selection 匹配用户被用户选中或者处于高亮状态的部分。在
火狐浏览器使用时需要添加-moz 前缀。该伪元素只支持双冒号的形式。
::-moz-selection {
color: orange;
background: #333;
}
::selection {
color: orange;
background: #333;
}
2
3
4
5
6
7
8
9
- 6 ::placeholder——::placeholder 匹配占位符的文本,只有元素设置了 placeholder 属性时,该伪元素才能生效。
该伪元素不是 CSS 的标准,它的实现可能在将来会有所改变,所以要决定使用时必须谨慎
- 7 ::backdrop(处于试验阶段)——::backdrop 用于改变全屏模式下的背景颜色,全屏模式的默认颜色为黑色。该伪元素只支持双冒号的形式
# 亲子悬停效果
.section-title:before {
content: "";
width: 20px;
height: 20px;
background: blue;
/* Other styles */
}
.section-title:hover:before {
transform: scale(1.2);
}
2
3
4
5
6
7
8
9
10
11