是否存在一个CSS选择器,可以选中页面中的第一个元素(分页符之后)?
我在这个站点已经看到过这个问题至少被提出过一次。然而,至今没有让人满意的答案,距现在已经过去了好几年。鉴于网页技术领域的变化速度,我想了解到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生效的两个位置。
当然一个副作用是每个位于 h1 之前的 p 会变得稍微大一些,这可能会让它们刚好换到新的一页。你可能会觉得这样可以接受,也可能不可以接受。
