44

我有一个 HTML 4.01/CSS 2.1 文档,其中包含一个 H3 标题,后跟一个短(单行)段落块,然后是一个包含多个项目的无序列表:

<h3>Heading!</h3>

<p>Some things:</p>

<ul>
  <li>Thing one</li>
  <li>Thing B</li>
  <li>Thing 4</li>
</ul>

我的问题是,当我打印文档(或使用 将其呈现为 PDF wkhtmltopdf)时,有时会在标题之后、段落之前出现分页符,这看起来很傻。

有没有办法规定在页眉之后应立即避免分页符?(我不反对 HTML5/CSS3 解决方案,如果这能显着简化事情的话。)

注意:按照建议,我尝试使用 CSS 属性page-break-after: avoid不过,这在任何基于 WebKitMozilla的浏览器中都不起作用。

4

5 回答 5

85

这是一个非常hacky的解决方案,但它对我有用:

h1 {
    page-break-inside: avoid;
}
h1::after {
    content: "";
    display: block;
    height: 100px;
    margin-bottom: -100px;
}

基本上我创建了一个不可见的元素,它增加了它的大小<h1>而不影响它之后的内容。当page-break-inside: avoid被应用并且整个<h1>(包括hacky元素无法放入页面)时,浏览器被迫将其<h1>带到下一页。

于 2018-12-12T12:17:34.360 回答
22

由于 CSS 属性在任何基于 WebKitMozilla的浏览器page-break-after: avoid中都不起作用,因此请使用标题上方的标题和可接受的文本数量:page-break-inside: avoid

CSS

<style type="text/css">
    .nobreak {
        page-break-inside: avoid;
    }
</style>

HTML

<div class="nobreak">
    <h3>Heading!</h3>

    <p>Some things:</p>

</div>

    <ul>
      <li>Thing one</li>
      <li>Thing B</li>
      <li>Thing 4</li>
    </ul>
于 2012-02-11T08:34:49.760 回答
2

如果您使用 HTML 5<article><header>,这里有一个似乎适用于 Webkit、Blink 和 Gecko 的 hack(调整值8rem以满足您的需求):

article > header::before
{
    content: "";
    display: block;
    height: 8rem; /* pretend that the header is at least 8rem high so this header cannot fit near the end of page */
    margin-bottom: -8rem; /* however, reduce the margin the same amount so that the following content can stay in its usual place */
    page-break-inside: avoid;
    break-inside: avoid;
}

这是因为伪元素是从标题顶部::before向下呈现的,并且浏览器确实支持得足够好,可以实际保留页面末尾的空间。它还利用浏览器在实际测量所需空间时考虑无边距的事实。我不知道这是在任何规范中指定的,还是恰好与现实世界的浏览器行为相匹配。page-break-inside: avoid;height

其他一些答案建议使用::after,但根据我的经验,这可能会导致容器元素<article>开始在前一页上呈现的情况。使用::before似乎效果更好,并且容器元素的开始似乎也在移动。显然,如果您的包含元素没有可见边缘,则差异并不重要。

请注意,因为您只有一个伪元素::before,如果您想为::before. 此 hack 要求::before在其他内容下呈现但透明,因此它不能包含可见内容。

需要考虑的其他事项:

  • page-breaknor在表 ( ) 中page-break-inside不起作用,也不是。尚不清楚这是由部分浏览器实现还是由于 CSS 规范实际需要这样做造成的。在实践中,您需要使用所有父元素,否则分页符会在任何地方发生。display:tabledisplay:griddisplay:flexdisplay:block<html>
  • 您不能将保留空间限制为完整容器元素的高度。例如,如果<article>上例中的整体小于8rem高,则元素仍会跳到下一页,因为这种 hack8rem会在尝试适应<article>页面之前盲目地保留空间。

break-after:avoid然而,在实践中,这比page-break-after:avoid现实世界的浏览器支持更好。此外,对widowsand的支持orphans真的很差,所以你可能也想对<p>element 应用类似的 hack。我会建议2rem3rem为那些空间。

于 2021-07-06T10:25:04.093 回答
0

当只处理段落中的行时,您可以使用 CSS 中的widowsandorphans属性。但不幸的是,这不会将您的标题绑定到段落或列表。这是因为widows并且orphans不适用于块状元素(如标题)。请参阅CSS“孤儿”应该在行级还是块级运行?

我试过了,因为我遇到了同样的问题。当我从浏览器(在我的情况下为 Opera)打印页面时,它似乎有效,但当我使用 wkhtmltopdf 导出 PDF 时无效。

看起来像把我们不想分开的所有元素都放在一个div中,并用 来设置它的样式page-break-inside: avoid,就像在接受的答案中建议的那样。

在我必须显示一些标题和表格数据的情况下,我必须构建一个例程来查找标题,然后计算前面的一定数量的表格行并将标题和表格重新定位到一个 div 中。

于 2020-05-07T14:11:54.973 回答
0

我最近研究了 pdf 下载故事,其中包含表格格式的动态数据行,其中包括各种图表图像(使用的技术=>Angular + Spring + Thymleaf + Puppeteer)处理分页符的一些关键点

尝试使用<div></div>块而不是 HTML 表格

不要在您想要 page-break-inside: 避免(在子元素中使用浮动)的父容器上使用 display: flex

.child1{ 浮动:左;}

3.如果你在循环和page-break-inside中渲染div:避免;不工作你应该使用这个 CSS hack 来处理特定的 div

<div class="parent-container">
<div class="child1"></div>
<div class="child2"></div>
</div>
.parent-container{
 position: relative;
 page-break-inside: avoid;
} 
.parent-container::after {
content: "";
display: block;
height: 200px;
margin-bottom: -200px;
}
于 2021-07-04T16:43:04.857 回答