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.