I'm generating a multi-page html document that I'd like to send to an Airprint printer from my app. Each page is discrete and must begin on it's own sheet.
This should be relatively simple - the content of each page is immediately followed by a div
element having display: block; page-break-after: always;
Here is a simple example:
<html>
<head>
<title>Printing with Page Breaks</title>
<style type="text/css">
@media screen or print {
div.pageb { display: block; page-break-after: always; }
}
</style>
</head>
<body>
<h1>Page 1</h1>
<p>Lorem ipsum dolor sit amet...</p>
<div class="pageb"></div> <!-- should page break here! -->
<h1>Page 2</h1>
<p>Lorem ipsum dolor sit amet...</p>
<div class="pageb"></div> <!-- should page break here! -->
<h1>Page 3</h1>
<p>Lorem ipsum dolor sit amet...</p>
<div class="pageb"></div> <!-- should page break here! -->
</body>
</html>
This document prints perfectly from Safari and Chrome, which both put all page breaks where they should be. On iOS however, the page breaks aren't inserted.
To print the html I'm using a UIPrintInteractionController
to print the contents of a UIWebView
by way of UIViewPrintFormatter
. Something like this:
UIPrintInteractionController *controller = [UIPrintInteractionController sharedPrintController];
UIPrintInfo *printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGeneral;
controller.printInfo = printInfo;
UIWebView *webViewPrint = [[UIWebView alloc] init];
[webViewPrint loadHTMLString:printHTML baseUrl:@"/"];
UIViewPrintFormatter *viewFormatter = [webViewPrint viewPrintFormatter];
controller.printFormatter = viewFormatter;
controller.showsPageRange = NO;
[controller presentAnimated:YES completionHandler:completionHandler];
This all seems very standard and I'm left wondering why page breaks print properly on other Webkit browsers but not UIWebView. Any ideas on how to do page breaks on iOS?
I don't have a general solution but I did manage to get page breaks working after some fiddling. Seems like UIWebView is a little finicky with where page-break-before/page-break-after
can be applied. Taking a hint from this question I decided to try adding my page break styles to the h1
elements instead of divs
and to my surprise the pagebreaks appeared. Here's what it looks like now:
<style type="text/css">
@media print {
.pagebreak-before:first-child { display: block; page-break-before: avoid; }
.pagebreak-before { display: block; page-break-before: always; }
}
</style>
...
<body>
<h1 class="pagebreak-before">Page 1</h1>
<p>Lorem ipsum dolor sit amet...</p>
<h1 class="pagebreak-before">Page 2</h1>
<p>Lorem ipsum dolor sit amet...</p>
<h1 class="pagebreak-before">Page 3</h1>
<p>Lorem ipsum dolor sit amet...</p>
</body>
I also added a duplicate of the .pagebreak-before
selector, now having a :first-child
pseudo-element. This is to prevent a blank page at the beginning of the document.
I'm pretty sure that it's not the h1 vs. the div that's the problem. But it did work a lot better when using an element before the content and using page-break-before: always.
First I tried something like this:
<div class="page">
<h2>Header</h2>
<p>Content</p>
</div>
<div class="page">
<h2>Header</h2>
<p>Content</p>
</div>
<div class="page">
<h2>Header</h2>
<p>Content</p>
</div>
And the css:
.page { page-break-after: always; }
This gave me very strange page breaks and the header could be the only element vertically centered on the page.
Changing the markup to:
<div class="page">
<div class="break"></div>
<h2>Header</h2>
<p>Content</p>
</div>
<div class="page">
<div class="break"></div>
<h2>Header</h2>
<p>Content</p>
</div>
<div class="page">
<div class="break"></div>
<h2>Header</h2>
<p>Content</p>
</div>
And the css to:
.break { page-break-before: always; }
.page:first-child .break { page-break-before: avoid; }
Worked as expected.
I found that I had to set the paginationMode
property of my UIWebView
to UIWebPaginationModeTopToBottom
(or any other value besides the default UIWebPaginationModeUnpaginated
value) for the CSS page-break rules to be used.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With