重新认识伪类与伪元素

伪类、伪元素都属于 CSS 选择器体系。

伪类用于匹配真实 DOM 中满足特定状态、位置条件的已有元素;伪元素可以选中渲染层面的虚拟盒子,或是对已有 DOM 的文本片段做样式切割,这部分虚拟对象并不出现在 DOM 文档树中。

简单来说:伪类是给现有 DOM 元素增加筛选条件;伪元素可以作用于 DOM 树中没有对应节点的虚拟渲染对象,例如 ::before::after 生成的装饰盒子,或是段落的首字母、首行文本片段。

伪类是什么?

伪类是用来匹配处于特定状态的元素的选择器,例如 :first-child:hover

伪类的效果,就如同给满足条件的 DOM 元素动态附加了一个 class 类名,不需要修改 HTML 源码即可完成样式控制。

伪类语法:以单冒号 :开头。

结构伪类

常用结构伪类列表

也常称为 CSS3 结构类伪类,依靠元素在文档中的位置、层级关系进行匹配。

  • E:first-child:匹配父元素下第一个子元素,且该子元素必须是 E 标签。若父元素第一个子节点不是 E,则匹配失效。
  • E:last-child:匹配父元素的最后一个子元素,且该子元素类型为 E。
  • E:nth-child(an+b):匹配父元素下,位置序号满足表达式的子元素,同时该元素必须是 E。
  • E:nth-last-child(an+b):从兄弟元素末尾向前计数,匹配序号符合表达式且类型为 E 的子元素。
  • E:nth-of-type(an+b):在父元素中,按同标签类型排序,匹配第 n 个 E 类型元素,会跳过其他类型标签。
  • E:nth-last-of-type(an+b):从末尾向前,匹配父元素内第 n 个 E 类型元素。
  • E:first-of-type:匹配父元素下第一个 E 类型元素。
  • E:last-of-type:匹配父元素下最后一个 E 类型元素。
  • E:only-child:父节点仅有唯一子元素,并且这个子元素是 E。
  • E:only-of-type:父节点子元素中,仅有一个 E 类型标签,其他标签可以存在。
  • E:empty:匹配完全不包含子节点、也没有文本内容的 E 元素(空白文本节点也会让它匹配失败)。
  • :blank:实验性伪类,用于匹配尚未填写内容的表单控件(如空的 inputtextarea);现行浏览器均未实现。
  • :playing:匹配正在播放的音视频等媒体元素。
  • :paused:匹配处于暂停状态的音视频等媒体元素。
  • :root:文档根元素,等同于 <html>,选择器优先级高于普通 html
  • :scope:在全局样式表中使用,等价于 :root;在 @scope 规则内匹配该作用域的根元素;在 DOM API(querySelectorquerySelectorAllmatches)调用时,代表调用该方法的元素,作为选择器的查找上下文。
  • :target:匹配 URL hash(锚点片段)所指向 id 的元素。
  • :is(A,B,C):接收选择器列表,匹配列表中任意一条选择器命中的元素,用于精简冗长的选择器。权重取括号内最具体那一条。
  • :where(A,B,C):匹配规则与 :is() 相同,但权重始终为 0。
  • :not():否定伪类,匹配不满足括号内选择器条件的元素,也叫反选伪类。

:nth-child(an+b) 表达式规则

对全部兄弟子元素从 1 开始编号,筛选序号满足表达式 an+b 的元素(n 取值:0、1、2、3……)。

注意:子元素下标从 1 开始,不存在第 0 位;书写顺序必须 an 在前、b 在后,不能写为 b+an,否则整个选择器会被浏览器忽略,不会匹配任何元素

/* 第 3 行 */
tr:nth-child(3) {}
tr:nth-child(0n+3) {}

/* 第 4、7、10、13 行 */
tr:nth-child(3n+4) {}

/* 表格奇数行 */
tr:nth-child(2n+1) {}
tr:nth-child(odd) {}

/* 表格偶数行 */
tr:nth-child(2n) {}
tr:nth-child(even) {}

/* 匹配父容器下前 3 个 span */
span:nth-child(-n+3) {}

:not() 否定伪类

权重规则:not() 本身不增加选择器权重,整体权重由括号内部的选择器决定。

旧版浏览器不支持括号内传入多选择器、复杂选择器:

/* 旧版不支持,不能逗号传多条件 */
.element_box :not(.green, .red) {}

/* 拆成两个选择器后语义变成「或」,不是等价写法 */
.element_box :not(.green),
.element_box :not(.red) {}

/* 旧版不支持复杂选择器 */
:not(.box .item) {}

/* 这不是上一行的拆分等价写法:表示既不是 .box,也不是 .item */
:not(.box):not(.item) {}

逗号是「或」,连续连写才是「与」

/* 逗号代表「或」,满足其中一个条件就命中,两类元素依旧会被匹配 */
.element_box :not(.green),
.element_box :not(.red) {}

/* 连续拼接代表「与」,同时满足两个否定条件 */
.element_box :not(.green):not(.red) {}

祖先匹配

:not(article) p 无法实现仅排除 article 内部的 p。该选择器含义为:只要 p任意祖先不是 article 就会被选中。

<article>
  <section>
    <p></p>
  </section>
</article>

结果<section> 会满足 :not(article),导致 p 意外命中。

动态伪类(用户交互伪类)

这类伪类会跟随用户操作,状态动态发生改变,分为锚点伪类、用户行为伪类。

  • 锚点伪类
    • :link:未被访问过的链接;
    • :visited:已经访问过的链接;
  • 用户行为伪类
    • :hover:鼠标悬浮在元素上;
    • :active:鼠标按下瞬间的激活状态;
    • :focus:元素获得焦点(键盘、鼠标点击均可);
  • :any-link:匹配任意链接,相当于同时匹配 :link:visited

LVHA(爱恨原则):设置链接样式时,伪类书写顺序必须为:Link → Visited → Hover → Active,顺序错乱会导致后写的状态盖不住先写的状态。

UI 元素状态伪类

专门用于表单控件,匹配控件不同状态。

  • :enabled:控件处于可用可编辑状态;
  • :disabled:控件被禁用;
  • :checked:单选框、复选框处于勾选;
  • :optional:非必填表单控件;
  • :placeholder-shown:正在展示占位提示文字;
  • :read-only:元素内容只读,不可修改;
  • :read-write:元素内容允许编辑;
  • :required:必填表单控件。

CSS2、CSS3 的伪类

  • CSS2 伪类::first-child:link:visited:hover:active:focus:lang()
  • CSS3 新增大量结构伪类、逻辑伪类(:nth-child:not():target 等);Selectors Level 4 再引入 :is():where() 等。

伪元素是什么?

伪元素用来生成文档树中不存在的虚拟元素节点,像凭空新增 DOM 节点一样去设置样式,而不是给已有元素附加类。

例如:使用 ::before 在元素内容之前插入装饰内容,这些虚拟节点不会出现在 HTML DOM 树,无法通过 querySelector 获取。

伪元素语法标准双冒号 ::;为兼容旧 CSS2,浏览器兼容部分老伪元素的单冒号写法。

常用伪元素列表

  • ::before:元素原有内容之前生成虚拟盒子;
  • ::after:元素原有内容之后生成虚拟盒子;
  • ::first-letter:匹配块级内容的第一个字符;
  • ::first-line:匹配块级容器的第一行文本;
  • ::selection:匹配鼠标选中高亮的文本区域;
  • ::placeholder:表单输入框占位提示文字;
  • ::marker:列表项目符号(ulol 的圆点、序号);
  • ::backdrop:全屏模式下底层遮罩盒子;
  • ::slotted():匹配 Shadow DOM 中 <slot> 分发出去的元素;
  • ::cue:WebVTT 字幕样式;
  • ::grammar-error::spelling-error:浏览器标记的语法、拼写错误文本。

::before::aftercontent 属性

::before::after 必须配合 content 属性使用,才会生成虚拟盒子。

content 支持多种类型取值:

.target::after {
  content: "附加文本";         /* 字符串 */
  content: url("./icon.png"); /* 图片资源 */
  content: attr(data-tip);    /* 读取元素自定义属性 */
  content: counter(myIndex);  /* CSS 计数器 */
  content: normal;            /* 等同于 none,不生成伪元素 */
}

CSS2、CSS3 的伪元素

  • CSS2 伪元素:::before::after::first-letter::first-line
  • CSS3 及之后新增:::selection::placeholder::marker::slotted()::backdrop 等。

伪类与伪元素的区别

语法区别

  • CSS2:伪类、伪元素统一单冒号 :
  • CSS3 规范:伪类:单冒号 :;伪元素:双冒号 ::

备注:浏览器向后兼容,老伪元素 :before:after:first-letter:first-line 单双冒号均可识别;新增伪元素强制使用双冒号。

本质区别

  • 伪类:给已存在的真实 DOM 元素附加虚拟类名,改变已有元素匹配条件。等效于手动增加 class。
  • 伪元素:创建不在 DOM 树中的虚拟盒子,相当于新增一个看不见的元素。等效于手动新增 HTML 标签。

参考链接

MDN 伪类和伪元素

© lizhao all right reserved,powered by Gitbook文件修订时间: 2026-08-19 23:02:30

results matching ""

    No results matching ""