我有一个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>
我的问题是,当我打印文档(或使用wkhtmltopdf
将其呈现为PDF)时,有时会在标题之后,在段落之前发生分页,这看起来非常愚蠢。
有没有办法规定在标题后应立即避免分页? (我不反对HTML5 / CSS3解决方案,如果这样可以显着简化事情。)
注意:以下建议,我尝试使用CSS属性page-break-after: avoid
。但是,这并不适用于任何基于WebKit或Mozilla的浏览器。
答案 0 :(得分:16)
由于CSS属性page-break-after: avoid
无法在任何基于WebKit或Mozilla的浏览器中使用,因此请在标题上使用page-break-inside: avoid
以及可接受的文本数量:
<style type="text/css">
.nobreak {
page-break-inside: avoid;
}
</style>
<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>
答案 1 :(得分:9)
这是一个非常棘手的解决方案,但对我有用:
h1 {
page-break-inside: avoid;
}
h1::after {
content: "";
display: block;
height: 100px;
margin-bottom: -100px;
}
基本上,我创建了一个不可见元素,该元素增加了<h1>
的大小,而不会影响其后的内容。当应用page-break-inside: avoid
且整个<h1>
(包括hacky元素无法放入页面)时,浏览器被迫将<h1>
携带到下一页。
答案 2 :(得分:0)
仅处理段落中的行时,可以在CSS中使用widows
和orphans
属性。但是不幸的是,这不会将您的标题绑定到段落或列表。这是因为widows
和orphans
不适用于块状元素(如标头)。参见Should CSS "orphan" operate at line or block level?
由于遇到了同样的问题,我尝试了。当我从浏览器中打印页面(在我的情况下是Opera)时,它似乎起作用了,但是当我使用wkhtmltopdf导出PDF时,它却没有起作用。
就像将所有我们不想分离的元素放入div
并用page-break-inside: avoid
设置样式一样,就像接受的答案中所建议的那样。
在我必须显示一些标头和表格数据的情况下,我必须构建一个例程,该例程查找标头,然后对前面的一定数量的表行进行计数,并将标头和表重新定位为一个div。
答案 3 :(得分:0)
我最近研究了 pdf 下载故事,它具有表格格式的动态数据行,其中包括各种图表图像(技术使用 =>Angular + Spring + Thymleaf + Puppeteer)处理分页符的一些关键点< /p>
尝试使用<div></div>
块而不是 HTML 表格
不要在你想要分页符的父容器上使用 display: flex: avoid(use float in child element)
.child1{ 浮动:左; }
3.如果你在循环中渲染div和page-break-inside:避免;不工作你应该使用这个 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;
}
答案 4 :(得分:0)
如果您使用 HTML 5 <article>
和 <header>
,这里有一个似乎适用于 Webkit、Blink 和 Gecko 的黑客(调整值 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-break
和 page-break-inside
在表 (display:table
)、display:grid
和 display:flex
中不起作用。尚不清楚这是由部分浏览器实现还是由于 CSS 规范实际需要这样做造成的。实际上,您需要将 display:block
用于最多 <html>
的所有父元素,否则会在任何地方发生分页。<article>
小于 8rem
高,该元素仍然会跳到下一页,因为这种 hack 甚至在尝试适应之前就盲目地为 8rem
预留了空间页面上的 <article>
。然而,由于现实世界的浏览器支持,这在实践中比 break-after:avoid
或 page-break-after:avoid
效果更好。此外,对 widows
和 orphans
的支持真的很差,因此您可能也想对 <p>
元素应用类似的技巧。我建议为这些空间提供 2rem
或 3rem
空间。