CSS :first-child 是一个结构化伪类选择器,它用于匹配作为其父元素第一个子元素的任何元素。简而言之,它选中了元素家族中的“长子”。这个选择器在清除列表间距、突出显示首个项目或为文章首段添加特殊样式等场景中非常有用。

1. :first-child 伪类的作用

:first-child 的核心作用是为一组同级兄弟元素中的第一个元素应用特殊样式

  • 移除初始间距: 例如,当所有列表项都有一个 margin-top 时,可以使用 :first-child 来移除第一个列表项的顶部外边距,使列表与上方内容对齐更美观。
  • 突出显示首个元素: 在一系列卡片或产品列表中,可以为第一个元素添加不同的背景或边框,以作突出展示。
  • 排版特殊处理: 为文章的第一个段落设置首字下沉(Drop Cap)或不同的字体样式。

2. 语法 (Syntax)

:first-child 的语法非常简单,直接附加在目标选择器之后。

  • 语法: selector:first-child { /* CSS 属性 */ }

  • 示例:

    /* 选中 ul 列表中的第一个 li 元素 */
    li:first-child {
      font-weight: bold;
    }
    

3. 核心要点::first-child vs. :first-of-type (关键区别)

这是 :first-child 最重要也最容易被误解的地方。

p:first-child 的真正含义是:“选择一个 p 元素,前提是这个 p 元素必须是它父元素的第一个子元素”。 它同时对元素类型 (p)位置(第一个子元素) 进行了判断。

  • :first-of-type 则不同,p:first-of-type 的含义是:“选择在同级元素中,第一个出现的 p 元素”,它只关心元素类型。

对比示例:

场景一: :first-child 生效
<article>
  <p>这是第一段。</p> <p>这是第二段。</p>
</article>
  • p:first-child 选中“这是第一段。”。
  • p:first-of-type 会选中“这是第一段。”。
场景二: :first-child 失效
<article>
  <h1>文章标题</h1>
  <p>这是第一段。</p> <p>这是第二段。</p>
</article>
  • p:first-child 不会选中任何元素,因为父元素 <article> 的第一个子元素是 <h1>,不是 <p>
  • p:first-of-type 仍然会选中“这是第一段。”,因为它是在 <article> 内出现的第一个 <p> 类型的元素。

结论: 当你不确定第一个子元素的类型时,或者你的 HTML 结构可能变化时,使用 :first-of-type 通常是更安全、更健壮的选择。

4. 浏览器兼容性

:first-child 是 CSS2.1 规范的一部分,它在所有浏览器(包括非常古老的 IE7+)中都具有完美的兼容性

5. 最佳实践与注意事项

  • 明确父子关系: :first-child 的判断始终是相对于其直接父元素。
  • first-of-type 更具弹性: 在大多数情况下,你的意图是“为某类元素的第一个添加样式”,此时 :first-of-type 更符合直觉且不易出错。
  • 现代布局中的替代方案 (gap): 在过去,:first-child (或 :last-child) 经常被用来移除列表项之间的多余间距。在现代的 Flexbox 和 Grid 布局中,推荐使用 gap 属性来定义项目之间的间距,它会自动处理边缘情况,无需再手动清除第一个或最后一个元素的 margin
    /* 传统方法 */
    .item { margin-top: 10px; }
    .item:first-child { margin-top: 0; }
    
    /* 现代方法 */
    .container {
      display: flex;
      flex-direction: column;
      gap: 10px; /* 自动在项目之间创建 10px 间距 */
    }
    

6. 完整示例 (Complete Example)

这个示例将清晰地对比 :first-child:first-of-type 的行为,并展示其在列表样式中的经典用法。

HTML (index.html):

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>CSS :first-child 伪类示例 v2.0</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <header><h1>CSS `:first-child` 伪类演示</h1></header>

    <main>
        <div class="example-section">
            <h2>`p:first-child` vs. `p:first-of-type` 对比</h2>
            
            <div class="demo-box">
                <h3>场景一: `p` 是第一个子元素</h3>
                <p>我是第一段 (first-child & first-of-type)</p>
                <p>我是第二段</p>
            </div>

            <div class="demo-box">
                <h3>场景二: `p` 不是第一个子元素</h3>
                <h4>这是一个标题</h4>
                <p>我是文章的第一段 (first-of-type only)</p>
                <p>我是文章的第二段</p>
            </div>
        </div>

        <div class="example-section">
            <h2>经典用法: 移除列表项的顶部边框</h2>
            <ul class="styled-list">
                <li>列表项 1</li>
                <li>列表项 2</li>
                <li>列表项 3</li>
                <li>列表项 4</li>
            </ul>
        </div>
    </main>
</body>
</html>

CSS (style.css):

/* 全局与布局样式 */
body { font-family: 'Segoe UI', sans-serif; margin: 0; background-color: #f0f2f5; color: #333; }
header { background-color: #0d6efd; color: #fff; padding: 20px; text-align: center; margin-bottom: 30px; }
main { max-width: 800px; margin: 0 auto; padding: 0 20px; }
.example-section { margin-bottom: 40px; background: #fff; padding: 20px; border-radius: 8px; }
.example-section h2 { margin-top: 0; }

/* 1. 对比 :first-child 和 :first-of-type */
.demo-box {
    border: 1px solid #ddd;
    padding: 15px;
    margin-bottom: 15px;
    border-radius: 5px;
}
.demo-box p {
    background-color: #e9ecef;
    padding: 10px;
}

/* 尝试用 :first-child 选中第一段 */
.demo-box p:first-child {
    background-color: #ffc107; /* 黄色 */
    border-left: 4px solid #fd7e14;
}

/* (可选,用于对比) 尝试用 :first-of-type 选中第一段 */
/* .demo-box p:first-of-type {
    background-color: #198754; 
    color: white;
}
*/


/* 2. 列表样式 */
.styled-list {
    list-style: none;
    padding: 0;
}
.styled-list li {
    padding: 15px;
    border-top: 1px solid #ced4da; /* 为所有 li 添加顶部边框 */
}

/* 关键: 移除第一个 li 的顶部边框 */
.styled-list li:first-child {
    border-top: none;
}

如何测试:

  1. 将上述代码分别保存到 index.htmlstyle.css 文件中。
  2. 在浏览器中打开 index.html
  3. 观察对比示例:
    • 在“场景一”中,第一个 <p> 元素变成了黄色背景,因为它既是 <p> 也是其父元素的第一个子元素,满足 p:first-child 的所有条件。
    • 在“场景二”中,第一个 <p> 元素没有变成黄色,因为它不是其父元素的第一个子元素(<h4> 才是)。这清晰地展示了 :first-child 的“陷阱”。你可以取消 CSS 文件中 :first-of-type 规则的注释,会看到两个场景中的第一个 <p> 都会被选中,从而证明了 :first-of-type 的不同行为。
  4. 观察列表用法: 在下方的列表中,你会看到一个没有顶部边框的、干净的列表开头。这是通过 :first-child 移除了第一个列表项的 border-top 实现的,是一种非常常见和实用的技巧。

其他推荐
小学初中1-9年级教辅资源大合集(长期更新) https://www.kdocs.cn/wo/sl/v11Pqvgj

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐