伪类伪元素

9 阅读3分钟

一、核心定义与本质区别

1. 伪类(Pseudo-classes)

  • 定义:用于选中已有元素处于某种状态时的样式,状态由用户行为或元素状态决定(非物理存在的类)。
  • 本质修饰已有元素的某个状态,类似为元素添加临时“类名”。
  • 示例:hover(鼠标悬停)、:active(点击激活)、:checked(表单选中)。

2. 伪元素(Pseudo-elements)

  • 定义:用于在已有元素的内容前后插入虚拟元素,这些元素并非真实DOM节点,而是CSS渲染的产物。
  • 本质创建新的虚拟元素并附加到选中元素,类似appendChild()prependChild()的效果。
  • 示例::before(内容前插入)、::after(内容后插入)、::first-line(首行样式)。

二、语法与规范差异

1. 符号区分(关键考点)

  • 伪类:使用单冒号:)+ 状态关键词,如:hover:nth-child(2)
  • 伪元素:CSS3规范要求使用双冒号::)+ 元素关键词,如::before::selection
    • 例外::first-letter::first-line等旧版伪元素仍可兼容单冒号,但建议统一用双冒号。

2. W3C规范演进

  • CSS2.1:未严格区分伪类与伪元素,均使用单冒号(如:before)。
  • CSS3:明确用双冒号标识伪元素(::before),单冒号保留给伪类,避免语法歧义。

三、功能场景与实例对比

1. 伪类:状态化样式控制

  • 典型场景

    • 交互反馈:按钮悬停:hover、链接访问状态:visited
    • 表单状态::focus(获取焦点)、:disabled(禁用);
    • 结构筛选::nth-child(odd)(奇数行)、:first-child(首个子元素)。
  • 代码示例

    /* 按钮悬停变红色 */
    button:hover {
      color: red;
    }
    /* 选中的复选框样式 */
    input:checked {
      border-color: green;
    }
    

2. 伪元素:虚拟内容插入

  • 典型场景

    • 装饰性元素:用::before::after绘制箭头、边框;
    • 文本样式:::first-letter首字母大写、::selection选中文本高亮;
    • 清除浮动:::after配合content: ''; clear: both;
  • 代码示例

    /* 元素前添加图标 */
    .icon::before {
      content: '📌'; /* 必须指定content属性 */
      margin-right: 5px;
    }
    /* 段落首行变色 */
    p::first-line {
      color: blue;
    }
    

四、性能与渲染差异

1. 对DOM的影响

  • 伪类:不修改DOM结构,仅添加样式,性能消耗低;
  • 伪元素:虚拟元素需浏览器渲染,相当于增加“隐式DOM节点”,但无需操作真实DOM。

2. 使用限制

  • 伪类:可链式叠加(如a:hover:active);
  • 伪元素:每个选择器中最多出现一次,且需放在伪类之后(如div::before:hover)。

五、问题

1. 为什么伪元素要用双冒号?单冒号不行吗?

  • CSS3为区分伪类与伪元素,强制伪元素使用双冒号(::),避免语法歧义。例如:
    • div:first-child(伪类:选中首个子元素);
    • div::first-child(语法错误,因first-child是伪类,应使用单冒号)。
      旧版浏览器兼容单冒号(如div:before),但新标准建议统一用双冒号以符合规范。
2. 伪元素的content属性必须存在吗?

  • ::first-line::first-letter等少数情况外,必须存在。例如:
    .box::before {
      content: ''; /* 空字符串是合法值,否则伪元素不显示 */
      display: block;
      width: 10px;
      height: 10px;
    }
    
    若省略content,多数浏览器会忽略该伪元素(Firefox除外,但仍建议显式声明)。
3. 伪类和伪元素可以同时使用吗?

  • 可以,且需遵循“伪元素在伪类之后”的顺序。例如:
    /* 悬停时元素后的伪元素变色 */
    .btn:hover::after {
      color: red;
    }
    

六、总结

  • 伪类:单冒号,表状态,选已有元素的某个状态;
  • 伪元素:双冒号,创内容,在元素前后插虚拟节点;
  • 核心差异:伪类改状态,伪元素增内容,语法符号是关键。