268

I'm writing a plug-in for a piece of software that takes a big collection of items and pops them into HTML in a WebView in Cocoa (which uses WebKit as its renderer, so basically you can assume this HTML file is being opened in Safari).

The DIVs it makes are of dynamic height, but they don't vary too much. They're usually around 200px. Anyway, with around six-hundred of these items per document, I'm having a really rough time getting it to print. Unless I get lucky, there's an entry chopped in half at the bottom and top of every page, and that makes actually using printouts very difficult.

I've tried page-break-before, page-break-after, page-break-inside, and combinations of the three to no avail. I think it might be WebKit not properly rendering the instructions, or maybe it's my lack of understanding of how to use them. At any rate, I need help. How can I prevent the cutting-in-half of my DIVs when printing?

DOK
  • 32,337
  • 7
  • 60
  • 92
joeylange
  • 2,873
  • 2
  • 17
  • 7

12 Answers12

478

Using break-inside should work:

@media print {
  div {
    break-inside: avoid;
  }
}

It works on all major browsers:

  • Chrome 50+
  • Edge 12+
  • Firefox 65+
  • Opera 37+
  • Safari 10+

Using page-break-inside: avoid; instead should work too, but has been exactly deprecated by break-inside: avoid.

Nino Filiu
  • 16,660
  • 11
  • 54
  • 84
Dmitri Farkov
  • 9,133
  • 1
  • 29
  • 45
  • 10
    It **should** work. But it doesn't. See http://en.wikipedia.org/wiki/Comparison_of_layout_engines_%28Cascading_Style_Sheets%29#Grammar_and_rules for browser support. – Greg Jun 26 '12 at 09:24
  • 1
    Works in Safari 6 :) _which is in developer preview now_ – Linus Unnebäck Jul 21 '12 at 17:14
  • 1
    Works in Chrome V 27.0.1453.116 – T. Brian Jones Jun 29 '13 at 02:22
  • 5
    Works in Netscape too. Thanks! –  May 08 '15 at 07:57
  • 4
    Why you need media print? Is it the same if media print is not used and rule is applied directly on div? – FrenkyB Nov 26 '16 at 07:53
  • @FrenkyB you are in right, this rue is applicable only on print viewport therefore it's not mandatory to keep it within media query – vzr Mar 24 '17 at 12:16
  • For all new browser this solution works. See https://caniuse.com/#search=page-break-inside – Naun Lemos May 15 '19 at 12:10
  • 3
    according to MDN, bage-break-inside is replaced with break-inside, but neither of these two is a living standard yet. best would be to use both for better support. Links: https://developer.mozilla.org/en-US/docs/Web/CSS/page-break-inside https://developer.mozilla.org/en-US/docs/Web/CSS/break-inside – Soul Reaver Mar 20 '20 at 11:00
35

page-break-inside: avoid; gave me trouble using wkhtmltopdf.

To avoid breaks in the text add display: table; to the CSS of the text-containing div.

I hope this works for you too. Thanks JohnS.

Edit: Suggest to add this within media block to not break existing styles. ie

@media print {
  div.my-div {
    display: table
  }
}
Pants
  • 2,563
  • 1
  • 20
  • 34
Bonjowi
  • 351
  • 3
  • 5
  • 8
    I had almost given up on the unexplained spaces that appeared here and there when using `page-break-before: always;` on `
    ` elements. Searched through an ocean of SO Posts, articles, official docs and whatnot. Nothing helped. But you, my friend, finally came with what I exactly needed! Can't thank you enough, man!! I wish I could get you a coffee at least, much love from India!
    – Jay Dadhania Sep 17 '18 at 20:35
  • THIS IS THE ANSWER. I suggest however, adding it inside a `media` block – Pants Jul 03 '22 at 20:23
22

Only a partial solution: The only way I could get this to work for IE was to wrap each div in it's own table and set the page-break-inside on the table to avoid.

NotMe
  • 87,343
  • 27
  • 171
  • 245
  • 4
    Beautiful! You're a champion; I've been looking for a way to do this in _wkhtmltopdf_, which doesn't support `page-break-inside: avoid;` properly. Finally I have a decent workaround. – Dave Aug 11 '11 at 16:24
  • 3
    Tested page-break-inside in wkhtmltopdf in version 0.11 and it works. – cmc Feb 20 '12 at 17:23
  • Tested with wkhtmltopdf 0.12.2.1. Div inside tables no longer needed, just put page-break-inside: avoid on div selector. Works! – Paul Marti Sep 02 '15 at 03:09
10

page-break-inside: avoid; does not seem to always work. It seems to take into account the height and positioning of container elements.

For example, inline-block elements that are taller than the page will get clipped.

I was able to restore working page-break-inside: avoid; functionality by identifying a container element with display: inline-block and adding:

@media print {
    .container { display: block; } /* this is key */

    div, p, ..etc { page-break-inside: avoid; }
}

Hope this helps folks who complain that "page-break-inside does not work".

Eric Wendelin
  • 43,147
  • 9
  • 68
  • 92
8

I had to deal with wkhtmltopdf too.

I'm using Bootstrap 3.3.7 as Framework and need to avoid page break on .row element.

I did the job using those settings:

.myContainer {
    display: grid;
    page-break-inside: avoid;
}

No need to wrap in @media print

mbutomax
  • 81
  • 1
  • 4
  • This is the answer! however, it will work better with `@media print` but that depends on requirement. – Mr. Pyramid Feb 23 '21 at 07:07
  • Same setup, but using Bootstrap 5 instead. This one worked for me. I didn't need to use `@media print`. Thank you! – MorganR Mar 14 '23 at 12:17
7

In my case I managed to fix the page break difficulties in webkit by setting my selected divs to page-break-inside:avoid, and also setting all elements to display:inline. So like this:

@media print{
* {
    display:inline;
}
script, style { 
    display:none; 
}
div {
    page-break-inside:avoid;
}

}

It seems like page-break-properties can only be applied to inline elements (in webkit). I tried to only apply display:inline to the particular elements I needed, but this didn't work. The only thing that worked was applying inline to all elements. I guess it's one of the large container div' that's messing things up.

Maybe someone could expand on this.

Waltur Buerk
  • 1,348
  • 13
  • 17
7

page-break-inside: avoid; definitely does not work in webkit, in fact has been a known issue for 5+ years now https://bugs.webkit.org/show_bug.cgi?id=5097

As far as my research has gone, there is no known method to accomplish this (I am working on figuring out my own hack)

The advice I can give you is, to accomplish this functionality in FF, wrap the content that you don;t want to break ever inside a DIV (or any container) with overflow: auto (just be careful not to cause weird scroll bars to show up by sizing the container too small).

Sadly, FF is the only browser I managed to accomplish this in, and webkit is the one I am more worried about.

Bob Monteverde
  • 1,750
  • 1
  • 12
  • 5
5

I have the same problem bu no solution yet. page-break-inside does not work on browsers but Opera. An alternative might be to use page-break-after: avoid; on all child elements of the div to keep togehter ... but in my tests, the avoid-Attribute does not work eg. in Firefox ...

What works in all ppular browsers are forced page breaks using eg. page-break-after: always

Bjoern
  • 51
  • 1
  • 1
  • This should work with Webkit. However you may need to put in a few extra divs styled for print with page-break-after: always; after ~ half a dozen of your regular divs. – ʍǝɥʇɐɯ May 16 '11 at 10:12
5

The possible values for page-break-after are: auto, always, avoid, left, right

I believe that you can’t use thie page-break-after property on absolutely positioned elements.

DOK
  • 32,337
  • 7
  • 60
  • 92
3

One pitfall I ran into was a parent element having the 'overflow' attribute set to 'auto'. This negates child div elements with the page-break-inside attribute in the print version. Otherwise, page-break-inside: avoid works fine on Chrome for me.

Eric D.
  • 1,567
  • 1
  • 9
  • 4
1
@media print{
    /* use your css selector */    
    div{ 
        page-break-inside: avoid;
    }
}

For all new browser this solution works. See caniuse.com/#search=page-break-inside

Naun Lemos
  • 157
  • 1
  • 6
1

I got this problem while using Bootstrap and I had multiple columns in each rows.

I was trying to give page-break-inside: avoid; or break-inside: avoid; to the col-md-6 div elements. That was not working.

I took a hint from the answers given above by DOK that floating elements do not work well with page-break-inside: avoid;.

Instead, I had to give page-break-inside: avoid; or break-inside: avoid; to the <div class="row"> element. And I had multiple rows in my print page.

That is, each row only had 2 columns in it. And they always fit horizontally and do not wrap on a new line.

In another example case, if you want 4 columns in each row, then use col-md-3.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Hemant K
  • 13
  • 3