CSS伪类&伪元素

3,105 阅读12分钟

定义

为什么引入伪类,伪元素

css 引入伪类和伪元素概念是为了格式化文档树以外的信息。

也就是说,伪类和伪元素是用来修饰不在文档树中的部分,比如,一句话中的第一个字母,或者是列表中的第一个元素

什么是 伪类

伪类用于当已有元素处于的某个状态时,为其添加对应的样式,这个状态是根据用户行为而动态变化的。虽然它和普通的 css 类相似,可以为已有的元素添加样式,但是它只有处于 dom树无法描述的状态下才能为元素添加样式,所以将其称为伪类

伪类是一个冒号(:)后跟伪类的名字构成的,有时候名字后面还会有一个放在括号里的值(:nth-child)

什么是 伪元素

伪元素是一种虚拟的元素CSS把它当成普通HTML元素看待。之所以叫伪元素,就因为它们在文档树DOM中并不实际存在。换句话说,我们不会在HTML中包含伪元素,只会通过CSS来创建伪元素

伪元素是一个冒号还是两个冒号

简单回答:多数情况下,都行。

CSS3 规范中的要求使用双冒号 (::) 表示伪元素,以此来区分伪元素和伪类,。除了IE8及以下版本,所有浏览器都支持两个冒号的伪元素表示法。

有些伪元素只能使用两个冒号,像::backdrop

建议使用单冒号表示法,原因也是向后兼容,CSS3 标准要求伪元素使用双冒号的写法,但也依然支持单冒号的写法

什么时候使用(不使用)生成的内容

通过CSS生成内容需要用到CSS属性content和伪元素:before:after

其中的“内容”(content可是纯文本,也可以是一个容器,通过CSS操作来显示某种图形或者装饰性元素。

重要的内容不要使用生成的内容,原因如下:

  1. 屏幕阅读器读不到它
  2. 无法选中
  3. 如果为了装饰而在生成内容中使用了多余的内容,那么支持CSS生成内容的屏幕阅读器会大声地把它读出来,导致用户体验更差

伪类

css伪类.png

状态伪类

通常出现在用户执行某个操作的情况下; linkvisitedhoveractivefocus

顺序:lvha 不能乱

a:link { color: blue } /* 未访问链接 */
a:visited { color: purple } /* 已访问链接 */
a:hover { font-weight: bold } /* 用户鼠标悬停 */
a:active { color: lime } /* 激活链接 */

:FOCUS

:focus用于选择已经通过指针设备、触摸或键盘获得焦点的元素,在表单里使用得非常多

a:focus {
    color: green;
}
input:focus {
    background: #eee;
}

结构化伪类

结构化伪类选择通过其他选择符无法选择文档树DOM中的其他信息

:first-child 选择父元素的第一个子元素

li:first-child {
    color: orange;
}

:last-child 选择父元素的最后一个子元素

li:last-child {
    color: orange;
}

:first-of-type 选择父元素容器内任意类型子元素的第一个元素

第一个li元素和第一个span元素的文本才是红色的

:last-of-type 选择父元素容器内任意类型子元素的最后一个元素

最后一个li元素和最后一个span元素的文本才是橙色的

<ul>
    <li>Lorem ipsum dolor sit amet. <span>Lorem ipsum dolor sit amet.</span> <span>This text will be orange.</span></li>
    <li>Lorem ipsum dolor sit amet.</li>
    <li>This text will be orange.</li>
</ul>
ul :first-of-type {
    color: red;
}

ul :last-of-type {
    color: orange;
}

:nth-child 根据元素在标记中的次序选择相应的元素

首先找到所有当前元素的兄弟元素,然后按照位置先后顺序从1开始排序,选择的结果为CSS伪类:nth-child括号中表达式(an+b)匹配到的元素集合(n=0,1,2,3...)

:nth伪类都接受一个参数,这个参数是一个公式。公式可以是一个整数,或者关键字oddeven,或者形如an+b的结构。

  • a是一个数值(整数)
  • n就是n
  • +是运算符,可以是加号+或减号-
  • b也是一个整数,但只有使用了运算符的时候才会用到
<ol>
    <li>Alpha</li>
    <li>Beta</li>
    <li>Gamma</li>
    <li>Delta</li>
    <li>Epsilon</li>
    <li>Zeta</li>
    <li>Eta</li>
    <li>Theta</li>
    <li>Iota</li>
    <li>Kappa</li>
</ol>

选择第2个子元素,结果Beta会变成橙色:

ol :nth-child(2) {
    color: orange;
}

从第2个子元素起,隔一个选一个,结果Beta、Delta、Zeta、Theta和Kappa会变成橙色

ol :nth-child(2n) {
    color: orange;
}

选择所有偶数个子元素

ol :nth-child(even) {
    color: orange;
}

从第6个子元素起,隔一个选一个,结果Zeta、Theta和Kappa会变成橙色:

ol :nth-child(2n+6) {
    color: orange;
}

:nth-of-type:nth-child类似

主要区别是它更具体了,只针对特定类型的元素

所有容器内的第2个p元素将为橙色

<article>
    <h1>Heading Goes Here</h1>
    <p>Lorem ipsum dolor sit amet.</p>
    <a href=""></a>
    <p>This text will be orange.</p>
</article>
p:nth-of-type(2) {
    color: orange;
}

:nth-last-child 从后往前选择元素

用法和:nth-child完全一样

:NTH-LAST-OF-TYPE

从后往前数,其余跟:nth-of-type一样

:only-child选择父元素中唯一的子元素

第一个ul只有一个子元素,因此该子元素将变成橙色。第二个ul有多个子元素,因此其子元素不会受:only-child伪类影响

<ul>
    <li>This text will be orange.</li>
</ul>

<ul>
    <li>Lorem ipsum dolor sit amet.</li>
    <li>Lorem ipsum dolor sit amet.</li>
</ul>
ul :only-child {
    color: orange;
}

:only-of-type 选择同级中类型唯一的元素

:only-child类似,但针对特定类型的元素,让选择符有了更强的意义。

第一个ul只有一个li元素,因此其文本将为橙色:

<ul>
    <li>This text will be orange.</li>
</ul>

<ul>
    <li>Lorem ipsum dolor sit amet.</li>
    <li>Lorem ipsum dolor sit amet.</li>
</ul>
li:only-of-type {
    color: orange;
}

:target 通过元素的ID及URL中的锚名称选择元素

当浏览器中的URL#target结尾时,IDtarget的文章将被选中

http://awesomebook.com/#target
<article id="target">
    <h1><code>:target</code> pseudo-class</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit!</p>
</article>
:target {
    background: yellow;
}

:not伪类也叫取反伪类,选择与参数不匹配的元素

它通过括号接受一个参数,一个“选择符”。实际上,这个参数也可以是另一个伪类。

这个伪类可以连缀使用,但不能包含别的:not选择符

<ul>
    <li class="first-item">Lorem ipsum dolor sit amet.</li>
    <li>Lorem ipsum dolor sit amet.</li>
    <li>Lorem ipsum dolor sit amet.</li>
    <li>Lorem ipsum dolor sit amet.</li>
</ul>

除了类为.first-itemli之外的li元素的文本都是橙色的:

li:not(.first-item) {
    color: orange;
}
“连缀”两个:not伪类

应用下面的CSS规则,除了类为.first-item的li和最后一个li,其他li都会有黄色背景和黑色文本:

li:not(.first-item):not(:last-of-type) {
    background: yellow;
    color: black;
}

验证伪类

虽然本节介绍的伪类都用于表单元素,但其中有的伪类也可以用于其他HTML元素。

:checked 选择被勾选或选中的单选按钮、多选按钮及列表选项

当复选框被选中时,与其相邻的<label> 元素的背景会变成黄色

<input type="checkbox"/>
<label>我同意</label>
input:checked + label {
    background: yellow;
}

:default 从表单中一组类似元素里选择默认的元素

例如:提交按钮总是表单的默认按钮

<form action="#">
    <button>重置</button>
    <button type="submit">提交</button>
</form>
:default  {
    background: yellow;
}

:disabled 择禁用状态的表单元素

name输入框处于禁用状态,因此会半透明:

<input type="text" id="name" disabled>
:disabled {
    opacity: .5;
}

:enabled 选择启用的元素

所有表单元素默认都是启用的,除非在标记中添加了disabled属性

:enabled {
    opacity: 1;
    border: 1px solid green;
}

:empty 选择不包含任何内容的空元素

只要包含一个字母、其他HTML元素,甚至一个空格,都不算空。

  • 第一个元素中包含文本,因此背景不会变成橙色
  • 第二个元素包含一个空格,空格也是内容,因此也不会有橙色背景
  • 第三个元素中什么也没有(空的),因此背景为橙色
  • 最后一个元素中只有一个HTML注释(也是空的),因此也有橙色背景。
<div>This box is orange</div>
<div> </div>
<div></div>
<div><!-- This comment is not considered content --></div>
div {
  background: orange;
  height: 30px;
  width: 200px;
}

div:empty {
  background: yellow;
}

: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;
}

:out-of-range 选择有范围且值超出指定范围的元素

在下面的例子中,输入元素支持输入1~12。输入值超出这个范围内,会触发橙色边框

<input id="months" name="months" type="number" min="1" max="12">
input[type=number]:out-of-range {
    border: 1px solid orange;
}

:indeterminate 选择单选按钮或复选框在页面加载时没有被勾选的

比如,页面加载后,一组单选按钮中没有默认或预先勾选的,或者一个复选框已经通过JavaScript设置为indeterminate状态。

<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>
:indeterminate + label {
    background: orange;
}

:valid 选择输入格式符合要求的表单元素

email输入框中的电子邮箱格式输入正确,会生效,将出现1像素的绿色边框:

input[type=email]:valid {
    border: 1px solid green;
}

:invalid 选择输入格式不符合要求的表单元素

email输入框中的电子邮箱格式不正确时,将出现橙色边框:

input[type=email]:invalid {
    background: orange;
}

:optional 选择表单中非必填的输入字段

只要输入字段中没有required属性,就会被:optional伪类选中

在下面的例子中,这个数值字段是可以选填的,因此其中的文本将为灰色:

<input type="number">
:optional {
    color: gray;
}

:read-only伪类选择用户不能编辑的元素

:disabled伪类相似,标记中使用的属性决定了使用哪个伪类。

文本框有一个readonly属性,因此会被:read-only伪类选中,文本将为灰色:

<input type="text" value="I am read only" readonly>
input:read-only {
    color: gray;
}

:read-write伪类选择用户可以编辑的元素

适用于有contenteditable属性的HTML元素。

有时候,可以与:focus伪类一块使用以增强用户体验

点击div元素就可以编辑其中的内容,为此可以应用特殊的样式,让用户知道自己可以编辑其中的内容:

<div class="editable" contenteditable>
    <h1>Click on this text to edit it</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit!</p>
</div>
:read-write:focus {
    padding: 5px;
    border: 1px dotted black;
}

:required伪类选择有required属性的表单元素

除了通过标签中的星号(*)提示必填,也可以通过这个伪类为输入字段应用样式

输入框有required属性,通过这个伪类为它应用特殊样式:

<input type="email" required>
:required {
    color: black;
    font-weight: bold;
}

:scope伪类适用于style标签中有scoped属性的情形

如果页面中某一部分的style标签里没有scoped属性,那么:scope伪类会一直向上查找,直到html元素,即当前样式表的默认作用范围

在下面的例子中,第二个section中有一个scoped样式表,因此这个section中的文本会变成斜体:

article>
    <section>
        <h1>Lorem ipsum dolor sit amet</h1>
        <p>Lorem ipsum dolor sit amet.</p>
    </section>
    <section>
        **<style scoped>
                        :scope {
                            font-style: italic;
                        }
                  </style>**
        <h1>This text will be italicized</h1>
        <p>This text will be italicized.</p>
    </section>
</article>

语言伪类

语言伪类与页面中包含的文本相关,与图片、视频等媒体无关

包含::dir:lang

其他伪类

:root 选择文档中最高层次的父元素

HTML中,:root伪类选择的就是html元素。但在SVGXML等标记语言中,它可能选择不同的元素。

以下规则为HTML文档中最高层次的父元素html添加背景颜色:

:root {
    background: orange;
}

:fullscreen 选择在全屏模式下显示的元素 (提案阶段)

不适用于用户按F11进入的全屏模式,只适用于通过JavaScript Fullscreen API切换进入的全屏模式,通常由父容器中的图片、视频或游戏来调用

伪元素

css伪元素.png

::BEFORE/:BEFORE

:before伪元素与:after类似,都可以为其他HTML元素添加内容(文本或图形)。同样,这里的内容并不实际存在于DOM中,但可以像存在一样操作它们。需要在CSS中声明content属性。

通过这个伪元素生成的内容不能通过其他选择符选中

content属性 中的空格也算数

<h1>Ricardo</h1>
h1:before {
    content: "Hello "; /* 注意Hello后面有一个空格 */
}
// 效果 “Hello ”后面的空格也算数
Hello Ricardo! 

::AFTER/:AFTER

这个伪元素添加的任何内容都无法通过其他选择符选中

<h1>Ricardo</h1>
h1:after {
    content: ", Web Designer!";
}
//效果
Ricardo, Web Designer!

::BACKDROP (提案阶段)

::backdrop伪元素是在全屏元素后面生成的一个盒子,与:fullscreen伪类连用,修改全屏后元素的背景颜色。

::backdrop伪元素必须用双冒号。

::FIRST-LETTER/:FIRST-LETTER 选择一行文本第一个字符

如果相应行前面包含图片、视频或表格元素,那么不会影响选择第一个字符

这个伪元素非常适合对段落进行排版,有了它就不必用图片或其他技巧了

这个伪元素也可以选中:before伪元素生成的第一个字符

h1:first-letter  {
    font-size: 5em;
}

:first-line选择元素的第一行,只适用于块级元素,行内元素不适用

即使一段文本有多行,也会选中第一行

p:first-line {
    background: orange;
}

::selection选择文档中被高亮选中的部分

基于Gecko的浏览器要求使用前面:::-moz-selection

在一条规则中同时使用带前缀不带前缀::selection是不行的,要分别写

::-moz-selection {
    color: orange;
    background: #333;
}

::selection  {
    color: orange;
    background: #333;
}

::placeholder伪元素选择表单元素中通过placeholder属性设置的占位文本(提案阶段)

也可以写成::input-placeholder

参考文档:www.jianshu.com/p/9086114e0…