是否存在一个CSS选择器,可以选中页面中的第一个元素(分页符之后)?

前端开发 2026-07-10

我在这个站点已经看到过这个问题至少被提出过一次。然而,至今没有让人满意的答案,距现在已经过去了好几年。鉴于网页技术领域的变化速度,我想了解到2026年的情况。话说回来:

我有一个简单的HTML文档,由若干个 <h1><p> 元素组成。我想把该页面打印出来(纸张尺寸为 A4)或转换为PDF(使用相同的纸张尺寸)。该文档在打印或转换后会超过五页的 A4。尽管如此,打印和转换工作得相当好(使用基于Webkit的浏览器或WeasyPrint),除了下面描述的问题。

这是CSS的一部分:

@page {
  size: 21cm 29.7cm;
  margin: 15mm;
}

h1 {
  margin-top: 8mm;
}

目标是在页面顶部实现恰好 15 mm 的边距,且在任何情况下都要如此。这里所说的“任何情况下”特别指:无论页面上最先出现的内容是什么。

但目前如果一个 <h1> 正好是分页后新页面的第一个元素,顶部边距会是 23mm,而不是期望的 15mm

我已经努力寻找一个干净的(HTML或 CSS纯)解决方案,但没有结果。显然,@page 边距不会与 <h1> 边距发生折叠,这导致了这个问题。

我想到的两个可能的解决方案:

  • @page 的边距与普通HTML元素的边距发生折叠。
  • 使用CSS选取每个分页后的第一元素(即新页面上的第一个元素),并移除这些元素的顶部边距。

如上所述,我没有找到这样的选择器,也不知道如何将HTML元素的边距与页面边距折叠。

2026年的解决方案会是什么?

澄清 / 更新:

我也愿意接受纯JavaScript的解决方案,即使它会在浏览器屏幕上把布局弄乱。在我的特殊用例中,最重要的是PDF的排版。

解决方案

如果你的结构是,例如:

<h1 />
<p />
<p />
<h1 />
<p />
<p />
<p />
<p />
<h1 />
<p />
<p />

那么,与其为 h1 设置 margin-top,你可以为一个 p 设置 margin-bottom,它的下一个同级元素是 h1,方法如下:

p:has(+ h1) { margin-bottom: 8mm }

我创建并测试了一个更完整的示例:

<head>
  <style type="text/css">
    h1 { padding: 0; margin: 0; border: dotted 3px blue; }
    p  { padding: 0; margin: 0; border: dotted 3px red; height: 430px; }

    p:has(+ h1) { margin-bottom: 20px; }

    @media print {
      * { break-inside: avoid; }
    }
  </style>
</head>

<body>
  <h1>Title</h1>
  <p>Text</p>
  <h1>Title</h1>
  <p>Text</p>
  <p>Text</p>
  <h1>Title</h1>
  <p>Text</p>
  <p>Text</p>
  <p>Text</p>
  <p>Text</p>
  <p>Text</p>
  <p>Text</p>
  <h1>Title</h1>
  <p>Text</p>
  <p>Text</p>
</body>

在Windows上的Firefox 149.2版本中,我在打印预览里看到了下列结果,可能就是你想要的。红色小箭头标出margin-bottom生效的两个位置。

Firefox 打印预览

当然一个副作用是每个位于 h1 之前的 p 会变得稍微大一些,这可能会让它们刚好换到新的一页。你可能会觉得这样可以接受,也可能不可以接受。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章