-
Notifications
You must be signed in to change notification settings - Fork 364
Page features
danfickle edited this page Mar 1, 2021
·
7 revisions
<html>
<head>
<style>
@page {
/*
* Size can be a length (not a percentage) for width and height
* or a standard page size such as:
* a4, a5, a3, b3, b4, letter, legal, ledger.
* A standard page size can be followed by either 'portrait' or 'landscape'.
*
* In theory, you can use different page sizes in one document, but this renderer
* currently uses the first page width as the width of the body. That means it
* is only practical to use different page heights in the one document.
* See danfickle/openhtmltopdf#176 or #119 for more information.
*/
size: 500px 1000px;
/*
* Margin box for each page. Accepts one-to-four values, similar
* to normal margin property.
*/
margin: 50px;
/*
* Boxes to sit in the margin area. Can be one of:
* top-left-corner, top-left, top-center, top-right, top-right-corner
* bottom-left-corner, bottom-left, bottom-center, bottom-right, bottom-right-corner
* left-top, left-middle, left-bottom,
* right-top, right-middle, right-bottom.
*
* Useful for things such as page counters, etc.
*/
@top-left {
content: counter(page);
}
@bottom-center {
content: 'You are on ' counter(page) ' of ' counter(pages);
}
@bottom-right {
/* We can also place an element in a margin box. This allows for formatting
* of content in the margin box. The element must have a position of a named
* running position. Any name can be used, provided it is a valid CSS identifier.
* See danfickle/openhtmltopdf#352 for multi line header example with rich formatting.
*/
content: element(header);
}
}
/* Possible pseudo page matchers are first, left and right.
* By convention the first page is right. */
@page:first {
@top-center {
content: 'first';
}
}
@page:left {
@top-right {
content: 'left';
}
}
@page:right {
@bottom-left {
content: 'right';
}
}
/*
* An element can be placed on a named page. Any name can be used provided it is
* a valid CSS identifier. Elements are placed on this page using the page property.
*/
@page named {
@top-center {
content: 'You are on a named page for a change!';
}
}
/* The body margin is in addition to the page margin,
* but the top body margin only applies to the first page and
* the bottom margin to the last page. */
body {
margin: 0;
}
/*
* NOTE: The element names here are made up to illustrate a concept.
* As the renderer works with XML, you can use any XML valid element name.
*/
page-after {
/* Most page elements only work on block or block-like elements. */
display: block;
/* Create a page break after this element. */
page-break-after: always;
}
page-before {
display: block;
/* Create a page break before this element. */
page-break-before: always;
}
.toc li::after {
/* The target-counter function is useful for creating a
* table-of-contents or directing the user to a specific page.
* It takes as its first argument the hash link (in the form #id)
* to the element and returns the page that element is located on.
* We can use the attr function to pick up the href from the html. */
content: target-counter(attr(href), page);
}
page-inside-avoid {
display:block;
height: 750px;
/* With page-break-inside the renderer will try (if possible) to
* avoid page breaks inside an element. */
page-break-inside: avoid;
}
running {
/* We mark this element as running by using the running function
* to specify a named position. The name can be any valid CSS identifier.
* See the @page rule above. */
position: running(header);
}
/* The widows property allows us to specify the minimum number of lines
* to fall onto the next page, if there is a page break inside our element.
* For example, you can use this to avoid a single line falling onto a
* new page. The widows property is satisfied by inserting space above
* the widows count of lines to make them fall onto a new page.
*
* Try: Changing widows to 0 and seeing how many lines are left on the new
* page. The default initial value of widows is 2.
*/
widows {
padding: 0 10px;
border: 1px solid red;
page-break-before: always;
display: block;
widows: 5;
line-height: 20px;
font-size: 16px;
margin-top: 698px;
}
spacer {
page-break-before: always;
display:block;
height: 878px;
}
spacer.four-lines {
height: 798px;
}
/* Orphans property is the pair of widows. It allows the author to specify
* the minimum number of lines that should occur on the page before a
* page-break. For example, we might want to prevent one line on the first page,
* followed by ten lines on the next.
* This property is satisfied by adding a new page before the element, if the
* orphans constraint is violated.
*/
orphans {
padding: 0 10px;
border: 1px solid green;
display: block;
widows: 0;
orphans: 3;
line-height: 20px;
font-size: 16px;
}
td, th {
border-bottom: 1px dashed gray;
}
table {
/* With -fs-table-paginate on, the header and footer
* of a table will be repeated on each page that the table falls on.
*/
-fs-table-paginate: paginate;
/* Similar to the orphans property, this property allows the author
* to specify how much of the block must show before a page-break.
* If the constraint is violated, a page break is added before the element.
* Very useful on elements not made of lines, such as tables, etc.
* TRY: Uncomment this property and see how the table moves to a new page
* to satisfy the constraint.
*/
/* -fs-page-break-min-height: 100px; */
}
.continued:before {
/**
* For repeated table headers (thead elements), show " - Continued"
* before each table header repeat on subsequent (not initial) pages.
* See https://github.com/danfickle/openhtmltopdf/pull/32
*/
content: " - Continued";
visibility: -fs-table-paginate-repeated-visible;
}
named-page {
page-break-before: always;
/* The page property allows us to marry up an element with a @page rule. */
page: named;
display: block;
}
</style>
</head>
<body>
<ul class="toc">
<li href="#p1">Page: </li>
<li href="#p4">Page: </li>
</ul>
<running id="run">The <strong>chicken</strong> <i>crossed</i>
<span style="color: green;">the</span> <span style="background-color: red;">road</span>.</running>
<page-after id="p1">Page 1</page-after>
<page-after>Page 2</page-after>
<page-after>Page 3</page-after>
<page-after id="p4">Page 4</page-after>
<page-after>Page 5</page-after>
<page-before>Page 6</page-before>
<page-before>Page 7</page-before>
<page-inside-avoid>Page 7.1</page-inside-avoid>
<page-inside-avoid>Page 8</page-inside-avoid>
<widows>
Line 1<br/>
Line 2<br/>
Line 3<br/>
Line 4<br/>
Line 5<br/>
Line 6<br/>
Line 7<br/>
Line 8<br/>
Line 9<br/>
Line 10<br/>
Line 11
</widows>
<spacer/>
<orphans>
Line 1<br/>
Line 2<br/>
Line 3<br/>
Line 4<br/>
Line 5<br/>
Line 6<br/>
Line 7<br/>
Line 8<br/>
Line 9<br/>
Line 10<br/>
Line 11
</orphans>
<spacer class="four-lines"/>
<table>
<caption>Paginated Table</caption>
<thead>
<tr><th>Title 1.1</th><th>Title 1.2</th></tr>
</thead>
<tfoot>
<tr><td>Footer 1.1</td><td>Footer 1.2</td></tr>
</tfoot>
<tbody>
<tr><td>Cell 1.1</td><td>Cell 1.2</td></tr>
<tr><td>Cell 2.1</td><td>Cell 2.2</td></tr>
<tr><td>Cell 3.1</td><td>Cell 3.2</td></tr>
<tr><td>Cell 4.1</td><td>Cell 4.2</td></tr>
<tr><td>Cell 5.1</td><td>Cell 5.2</td></tr>
<tr><td>Cell 6.1</td><td>Cell 6.2</td></tr>
<tr><td>Cell 7.1</td><td>Cell 7.2</td></tr>
<tr><td>Cell 8.1</td><td>Cell 8.2</td></tr>
<tr><td>Cell 9.1</td><td>Cell 9.2</td></tr>
<tr><td>Cell 10.1</td><td>Cell 10.2</td></tr>
</tbody>
</table>
<table>
<caption>Paginated Table with "Continued" header</caption>
<thead>
<!--
If the table extends to multiple pages,
the header will show "My Table - Continued" in the repeating header.
-->
<tr><th colspan="2"><h2>My Table<span class="continued"></span></h2></th></tr>
</thead>
<tbody>
<tr><td>Cell 1.1</td><td>Cell 1.2</td></tr>
<tr><td>Cell 2.1</td><td>Cell 2.2</td></tr>
<tr><td>Cell 3.1</td><td>Cell 3.2</td></tr>
<tr><td>Cell 4.1</td><td>Cell 4.2</td></tr>
<tr><td>Cell 5.1</td><td>Cell 5.2</td></tr>
<tr><td>Cell 6.1</td><td>Cell 6.2</td></tr>
<tr><td>Cell 7.1</td><td>Cell 7.2</td></tr>
<tr><td>Cell 8.1</td><td>Cell 8.2</td></tr>
<tr><td>Cell 9.1</td><td>Cell 9.2</td></tr>
<tr><td>Cell 10.1</td><td>Cell 10.2</td></tr>
</tbody>
</table>
<named-page>
Some content on a named page<br/>
More content on a named page<br/>
</named-page>
</body>
</html>
Still missing is -fs-keep-wfsith-inline
, as I haven't yet figured out its functionality.
By default, the first running element on a page specified with the matching running position is used for margin box content. This means that you can re-assign margin box content on subsequent pages. If you simply want content to be available to all pages, add the running elements as the first children of the body element.
<html>
<head>
<style>
@page {
margin: 20px;
@bottom-left {
content: element(footer);
}
}
.footer {
position: running(footer);
}
</style>
</head>
<body>
PAGE 1
<!-- This is the footer running block for page 1.
If it was not present no footer would be shown on page 1. -->
<div class="footer">
FOOTER1
</div>
<div style="page-break-before: always;">PAGE 2</div>
<!-- This is the footer running block for page 2.
If it was not present, 'FOOTER1' would be used. -->
<div class="footer">
FOOTER2
</div>
<div style="page-break-before: always;">PAGE 3</div>
<!-- This is the footer running block for page 3.
If it was not present, 'FOOTER2' would be used. -->
<div class="footer">
FOOTER3
</div>
</body>
</html>
-
#238
page:last
is not supported. Support could be complicated by the fact that empty pages are removed late in the rendering process. -
#233 White page added with named page.- Add a CSS rule:body { margin-top: 0; }
as a simple workaround. - #230 Page size slightly off
- #202 Paginated tables that start at top of page have incorrect header layout
- #119 First page determines body element width