51

I have a bunch of paragraphs on a page:

<p> ... </p>
<p> ... </p>
<p> ... </p>

The CSS rule for those paragraphs is:

p {
    margin: 20px 0;
    page-break-inside: avoid;
}

Live demo: http://jsfiddle.net/KE9je/2/show/

If I understand the page-break-inside property correctly, the above should ensure that no paragraph is split between two pages. (A paragraph is either displayed on the "current" page, or if it doesn't fit completely, it's moved to the next page.)

This doesn't seem to work in Chrome. Open the demo, right-click the page, choose "Print...". You'll see a print preview - the fifth paragraph is split between page 1 and 2.

What am I doing wrong? How can I make this work in Chrome?


Šime Vidas
  • 182,163
  • 62
  • 281
  • 385

16 Answers16

48

Actually, it DOES work in Chrome, and the solution is really silly!!

Both the parent and the element onto which you want to control page-breaking must be declared as:

position: relative;

Check out this fiddle (or in fullscreen)

This is true for:

page-break-before
page-break-after
page-break-inside

However, controlling page-break-inside in Safari does not work (in 5.1.7, at least)

I hope this helps!!!

Web_Designer
  • 72,308
  • 93
  • 206
  • 262
Peter
  • 1,236
  • 10
  • 10
  • 2
    Actually, it seems that Chrome has implemented `page-break-inside`. My original demo (from my answer) works now in Chrome `:D` – Šime Vidas Sep 12 '12 at 20:01
  • 1
    Indeed, `page-break-inside` does work in Chrome (as long as you don't declare `position: absolute; ` on either the element or its parent, but it does not work in _Safari_ (at least the 5.x versions) - Cheers! – Peter Sep 13 '12 at 08:37
  • 1
    I have no idea how you figured it out, but it solved the page break issues I had using wkhtmltopdf - thanks! – Rico Leuthold Sep 11 '13 at 10:27
  • 1
    It does not work for table rows (display:table-row); page-break-* works only for block elements (display: block). To avoid wrapping table rows, you must set the row as block and keep the cells as table-cell. But it breaks the table layout if there is not enough space. Alternatively you can try Flexbox (display: flex) – Radek Pech Nov 23 '14 at 13:27
  • 8
    Does not work for me on a div despite the suggested CSS {display: block; position: relative;page-break-before: auto;page-break-after:auto;page-break-inside: avoid;}. There must be another nuance – Stan Nov 22 '16 at 19:18
  • This still works for me... Note that the fiddle is in an iframe; you have to click the [**fullscreen**](http://fiddle.jshell.net/petersphilo/QCvA5/5/show/light/) link to the fiddle... @Stan: remember that the **parent** must _also_ be `position: relative; ` – Peter Feb 05 '18 at 10:51
  • 1
    FYI I had to add CSS to multiple parents for it to work, as my html structure is pretty complex. I added `position: relative; page-break-inside: avoid; display: block;` to every single element up the parent path until it fixed the problem. I progressively removed them once I solved it, in order to apply them only where they *need* to be applied – AlexMorley-Finch Apr 10 '18 at 14:12
  • I have tried adding position as relative but it is not working . may i know is there anything causing issue for this? ( working in firefox but no in chrome) – macha devendher May 30 '18 at 12:19
  • 19
    Seems like having `display: flex` doesn't support `page-break-inside` properties. Changing the display type to `block` worked for me! – rehman_00001 Feb 11 '19 at 06:06
  • 1
    I have tried to add `position: relative` and `display: block` to all elements with their parents up to the `body` and it didin't work. Chrome is the new IE. :-/ edit: what did work was to set `position: relative !important` and `display: block !important` to all of those elements and then it worked. – Vladimir Jovanović Jul 30 '19 at 10:04
  • Adding position: relative and display: block for all parent div elmens helped to avoid breaking images. A strange behaviour. – Pavlo Maistrenko Jul 10 '20 at 17:59
14

This worked best for me:

.no-page-break {
   display: inline-block;
   width: 100%;
   page-break-inside: avoid;
}

You can also specify the height if needed.

Ivan Rogic
  • 149
  • 1
  • 4
9

I've been fighting with this for a while and as well as follow the advice in the other answers I had to make sure that the element and all parent elements had the styling Display: block;.

Ryan Searle
  • 1,597
  • 1
  • 19
  • 30
  • 1
    Close, but I actually found that I needed `display: inline-table` – bigsee Aug 24 '18 at 10:14
  • 5
    After an hour wasted on various other sites and StackOverflow questions, this was it – the _container_ of the element that I wanted to avoid breaking had `display: flex;`. I wouldn't have figured this out till the end of eternity on my own. Thanks! – Dániel Kis-Nagy Aug 11 '20 at 12:55
  • 1
    @DánielKis-Nagy you're my savior. I spent an hour as well as you, and replacing display flex to float: left helped me, everything is working now. Thank you – Oro Jul 12 '22 at 09:24
6

I know this is an old question but Chrome has changed since it was originally answered and this may help.

It looks like page-break-inside:avoid works in Chrome based on the height of the element, so if you are floating a bunch of elements in a div, page-break-inside:avoid will not work.

It's possible to get around this by explicitly defining the height the element you don't want broken up. jQuery example:

$('#page_break_inside_avoid_element').height($('#page_break_inside_avoid_element').height());
JSP64
  • 1,454
  • 1
  • 16
  • 26
  • “height of your desired element” - Which one, the paragraphs which I don’t want to be broken up, or their container element? – Šime Vidas Sep 17 '15 at 23:45
  • @ŠimeVidas - clarified per your comment. – JSP64 Sep 18 '15 at 15:04
  • I’ve made a new demo: https://output.jsbin.com/fuvazi/quiet From what I can tell, `page-break-inside: avoid` works in Chrome now. I did not specify any heights. – Šime Vidas Sep 18 '15 at 16:51
  • Yeah that will work fine. I'm talking about cases where the `page-break-inside: avoid` is a div that has other divs inside it, and those inside divs are floated. – JSP64 Sep 19 '15 at 15:32
  • 1
    Hm, I wouldn’t float in a print layout, at least not the main paragraphs. If the page uses floats, I’d revert them in the print stylesheet. – Šime Vidas Sep 19 '15 at 20:37
  • I found I had similar issues, which seemed to come from the fact that some elements had a fixed height. Setting the height to 'auto' for print seemed to fix the issue. – Shaun Cockerill Apr 13 '18 at 07:46
5

I recently worked on the pdf download story which was having dynamic rows of data in table format which include various charts images(tech used=>Angular + Spring + Thymleaf + Puppeteer) Some of the key points for handling page-breaks

  1. Try to use <div></div>blocks instead of HTML tables

  2. Do not use display: flex on the parent container on which you want page-break-inside: avoid(use float in child element)

    .child1{ float: left; }

3.If you are rendering div in loop and page-break-inside: avoid; not working You should use this CSS hack to work on a particular 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;
}
Saransh Dhyani
  • 397
  • 3
  • 9
5

According to SitePoint, Chrome is not supported here, only Opera (and IE 8 buggy)...

http://reference.sitepoint.com/css/page-break-inside

Other references:

http://www.webdevout.net

http://www.reddit.com/r/css/comments/jdeim/pagebreakinside_avoid_doesnt_work/

Stack Overflow threads:

Cross-browser support of `page-break-inside: avoid;`

"page-break-inside: avoid "- does not work

Google Chrome Printing Page Breaks

Which browsers support page break manipulation using CSS and the page-break-inside element?

Google Chrome Forum:

http://www.google.com/support/forum

I will not post the W3Schools link (due to general unreliability) but they also state it's only supported in Opera, for whatever it's worth.

Community
  • 1
  • 1
Sparky
  • 98,165
  • 25
  • 199
  • 285
  • "Chrome versions up to and including 3 don’t support this property." – magritte Oct 09 '11 at 21:08
  • The first link tests Chrome 2 (it's now on version 14) and the second link makes no mention of Chrome. – Clive Oct 09 '11 at 21:09
  • The Wiki Comparison page says it's implemented in Webkit: [http://en.wikipedia.org/wiki/Comparison_of_layout_engines_(Cascading_Style_Sheets)](http://en.wikipedia.org/wiki/Comparison_of_layout_engines_(Cascading_Style_Sheets)) – Šime Vidas Oct 09 '11 at 21:10
  • @ŠimeVidas: Definitely, others report it working here: http://stackoverflow.com/questions/1630819/google-chrome-printing-page-breaks – Clive Oct 09 '11 at 21:11
  • @Šime Vidas, your experience seems to indicate that the MDN is mistaken. – Sparky Oct 09 '11 at 21:16
  • @Šime Vidas, What explains reputable sources saying that only Opera (and maybe IE 8) support this? – Sparky Oct 09 '11 at 21:21
  • @ŠimeVidas - Does seem to need a `page-break-after:` setting. – Alohci Oct 09 '11 at 21:25
  • @ŠimeVidas, I found a possible workaround on the Chrome Wiki for version 14 by adding `margin: 0px;`. See my updated answer. – Sparky Oct 09 '11 at 22:53
  • @Sparky672 But I don't want `page-break-after: always` for each paragraph. That would result in only one paragraph per page... – Šime Vidas Oct 09 '11 at 23:07
  • @ŠimeVidas, Yeah, it's not looking good for a solution. Lots of complaints about it but no practical workarounds. – Sparky Oct 09 '11 at 23:14
3

Check if the parent container display is not inline-block!! If so, then it will never work! I waste few hours to figure it out.

Works in Chrome 87

2

For Bootstrappers, be aware that page-break-inside or others may not (highly) work under container or row or other classes of bootstrap even if you change manually the position property. When I exclude container and row, it worked like a charm!

ninbit
  • 530
  • 6
  • 24
2

I solved it: my problem was "a" parent div (not "the" parent div) set as display: flex.

I set it to display: block and it works.

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
crinzy
  • 31
  • 1
1

What worked for me (in both FFox & Chrome, that is)

.container {
  column-gap: .4em;
  columns: 3;
  padding: .4em;
}

.contained {
  page-break-before: avoid;
  page-break-inside: avoid;
  page-break-after: always;
}

And that's it ; I didn't need position.

yPhil
  • 8,049
  • 4
  • 57
  • 83
1

check if the parent(or top level container) display is flex ; remove it and try again; it works for me in chrome71

2tuzi
  • 46
  • 4
1

Here is how I solved this while writing a css for printing.

For example, you put some pictures in an HTML file like this:

<div class="bottom">
    <figure>
        <img src="img01.jpg" alt="Front View">
        <figcaption>Front View</figcaption>
        </figure>
    <figure>
        <img src="img02.jpg" alt="Rear View">
        <figcaption>Rear View</figcaption>
    </figure>
</div>

And write the css like this:

.bottom figure{
  page-break-inside: avoid;
}

Sometimes it won’t work as you expect, because the default value of display for most elements is block or inline, which is not ‘page-break friendly’. I usually change it like this:

.bottom{
    display: contents;
}

This aims to disappear the container, making the child elements children of the element the next level up in the DOM.

As for your question, I suggest you to have a look at the display mode of the container of the paragraph to see whether it is set to block. If so, change it to contents and try again.

I hope this help.

Charles
  • 463
  • 4
  • 9
1

After a huge digging, it seems to be a very silly, annoying and simple issue. The key to fixing this issue is:

First, let's define what's parent and child.

  • Child: It's the element that we need to prevent/avoid cutting through in-between pdf pages
  • Parent: It's the direct parent/container of the child

Now we have the parent and the child very obvious, the next step is to give both parent and child some easy-to-implement rules. so let's do that

  • Parent rules

    display: block;

  • Child rules

    display: block; position: relative: page-break-inside: avoid;

That's it!

1

I just tested this with a larger paragraph in IE9, Chrome 14 and Firefox 7, and it looks like only IE9 works as expected. You might have to resort to adding page breaks manually where you want them with

page-break-after:always

Of course that's only any good to you if you know the content length in advance.

magritte
  • 7,396
  • 10
  • 59
  • 79
  • I'm baffled why Chrome and Firefox wouldn't implement this. It's such an old feature... – Šime Vidas Oct 09 '11 at 22:03
  • @ŠimeVidas Yeah, weird eh. The spec here http://www.w3.org/TR/css3-page/#allowed-pg-brk suggests it should work. In fact Chrome and Firefox appear to violate Rule D since p is a block level element. – magritte Oct 09 '11 at 22:23
0

It Works for me, like this:

.print{position: absolute;}
.print p{page-break-inside: avoid}
0

Also page-break-inside: avoid may not work if one of parent elements has fixed height (say height: 1000px). I guess that's because browser is trying to fit content in specified height first and only then thinks about page breaking.

Changing to height: 100% fixed it for me.

nidu
  • 549
  • 2
  • 18