2

When printing from Chrome, I would like to avoid a page break between a heading and the following paragraph.

I achieved this for most documents with:

h1 {
   page-break-inside: avoid;
   page-break-after: avoid;
}

... and this moves a bunch of page-breaks, forcing the break to occur before the heading when necessary.

However this seems to fail when the break happens within the margin of the heading.

I can reproduce like this:

<html>
   <head>
     <style>
         h1 {
           border-style: solid;
           margin: 30px;
           page-break-inside: avoid;
           page-break-after: avoid;
         }
         p {
           background-color: grey;
         }
     </style>
   </head>
   <body>
     <h1>Lorem ipsum dolor sit amet</h1>
     <p>... consectetur adipiscing elit (etc)...</p>
     (Repeat to fill a page)
</html>

... shorten/lengthen the paragraph text until print-preview shows an unwanted page-break:

screenshot of unwanted page break

The CSS spec seems to say this shouldn't happen:

In the normal flow, page breaks can occur at the following places:

1) In the vertical margin between block-level boxes. When an unforced page break occurs here, the used values of the relevant 'margin-top' and 'margin-bottom' properties are set to '0'. When a forced page break occurs here, the used value of the relevant 'margin-bottom' property is set to '0'; the relevant 'margin-top' used value may either be set to '0' or retained.

...

  • Rule A: Breaking at (1) is allowed only if the 'page-break-after' and 'page-break-before' properties of all the elements generating boxes that meet at this margin allow it, which is when at least one of them has the value 'always', 'left', or 'right', or when all of them are 'auto'.

Is this working as it should? Or a bug in Chrome's CSS? Or a misunderstanding on my part?

Can I work around it somehow?

slim
  • 40,215
  • 13
  • 94
  • 127
  • What if you wrap both the `h1` and `p` tags with a div and add the `page-break-..` stuff to that div? – Rick Jun 25 '19 at 09:48
  • Maybe [this question](https://stackoverflow.com/questions/4884380/css-page-break-not-working-in-all-browsers) can offer some answers aswell. – Rick Jun 25 '19 at 09:56
  • Check this link, hope can help you. [here](https://superuser.com/questions/16560/firefox-avoid-splitting-images-and-lines-of-text-when-printing) – Gonzalo Jun 25 '19 at 10:03

1 Answers1

1

First (simple and safe) solution: Add a section/div element around h1 and first paragraph and set on it a page-break-inside: avoid. In example:

    <body>
       <div class="headline">
          <h1>A sample title</h1>
          <p>First paragraph bla bla blac....</p>
       </div>
       <p>Second paragraph...</p>
    </body>

with CSS:

    .headline {
        page-break-inside: avoid;
    }

Second solution: with some little change on html, and semantic section can do something like:

  <body>
    <div class="page">
      <section>
        <h1>
          A Simple Title
        </h1>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
        </p>
        ...
        <h1>Second title</h1>
        <p>Lorem....</p>
    </section>
  </body>

With CSS:

body {
  font: sans-serif;
}
.page {
  padding: 1em;
}
section {
  page-break-before: always;
}
section > p + h1 {
  page-break-before: always;
  page-break-after: avoid;
}
section > h1* + p {
  page-break-before: avoid;
}

You can see an example here: https://codesandbox.io/s/test-print-avoid-page-break-after-title-l4kbq

g.annunziata
  • 3,118
  • 1
  • 24
  • 25
  • 2
    So, implicit in this answer, is that Chrome's handling of page-break-after is broken? – slim Jun 25 '19 at 14:29
  • Probably yes. I think happen something like this: Chrome try to print each element separately and when try to print H1 there's space enough.*page-break-after: avoid* presume to check if **next** element has space enough OR this element must jump to next page and so next element. But this implies a lot of other checks: if next element CANNOT be printed without break (is big exactly like page) is another special case to consider, and so on... – g.annunziata Jun 25 '19 at 14:37