body :first-child(不是body:first-child,中间有空格)伪类选择器到底选中了什么元素?

:first-child 选中了什么

如题,在学习:first-child伪类的时候,我使用如下语法,但是产生的结果在预料之外。
codepen链接
html

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS选择器学习</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>

    <h1>CSS选择器学习示例</h1>

    <p class="highlight">这是一个带有 class="highlight" 的段落。</p>
    <p id="unique">这是一个带有 id="unique" 的段落。</p>
    <p>这是一个普通的段落。</p>
    <p>这是另一个普通的段落。</p>

    <div>
        <p>这是 `div` 内部的段落。</p>
    </div>

    <input type="text" placeholder="输入一些文字">
    <button>点击我</button>

</body>
</html>

css

body :first-child{
  background-color: red
}

按照:first-child语法,body :first-child选中的应该是body的第一个子元素,也就是

<h1>CSS选择器学习示例</h1>

结果选中了这个元素

 <div>
        <p>这是 `div` 内部的段落。</p>
    </div>

网上搜索无果,所以来这里提问了,body :first-child的选择逻辑是什么?

阅读 410
2 个回答

首先我非常不建议你写这种容易引起歧义的选择器,要么你就把通配符写全 body *:first-child。否则非常容易看岔了,body :first-childbody:first-child 就差一个空格,但含义完全不同。

其次你理解的“选中的应该是 body 的第一个子元素”,是对的。那么为什么没选中 h1 呢?我们 F12 看一下网页源码:

image.png

看到了吗?h1 并不是 body 的第一个子元素,在它前面被 WebIDE 插入了其他元素。

image.png

你把这坨都删掉就能看到效果了。

最后,body * 只要求 *body后代(Descendant),但并未要求是子元素(Child)、即一级后代。因此那个 p 既是 body 的后代,同时它也是其父元素的第一个子元素,因此 body *:first-child 选择器会匹配到它。

:first-childCSS 伪类选择器,用于选中某父元素下的第一个子元素。它的核心逻辑是:选择作为其父元素的第一个子元素的特定标签,而非“父元素下的第一个特定标签”。

1.基本用法

/* 选中所有作为父元素第一个子元素的 <p> 标签 */
p:first-child {
  color: red;
}

示例:

<div>
  <p>第一个子元素(会被选中)</p>  <!-- 红色 -->
  <p>第二个子元素</p>
</div>

<section>
  <h1>标题</h1>  <!-- 第一个子元素,但不是 <p>,不匹配 -->
  <p>段落</p>
</section>

必须满足两个条件:

  1. 目标元素是父元素的第一个子元素。
  2. 目标元素匹配选择器前的标签(如 p:first-child 中的 <p>)。

你给的示例中,<p>标签作为<div>标签下的第一个子元素因此也会被选中的。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题