Reference

CSS for paged documents, and what actually works

The paged media specification is large and only partly implemented, and unimplemented CSS fails silently. Every entry below says which side of that line it falls on, because that is the part that is hard to find written down and the part that costs an afternoon.

For the dimensions themselves, meaning what A4, a 4 by 6 label or an 80mm receipt roll actually measure and what margin each one needs, see PDF page sizes. For the scripts where a font with the right characters still is not enough, see writing systems in PDF output.

The page box

  • @pageWorks in a browser-based render

    @page declares the properties of the page box itself: its dimensions and its margins, which are things no element selector can reach.

  • sizeWorks in a browser-based render

    The size descriptor inside @page sets the paper dimensions, either by name (A4, Letter) or as an explicit width and height.

  • margin (in @page)Works in a browser-based render

    The margin descriptor inside @page sets the unprintable border around the content area of every page.

  • @page :first, :left, :rightWorks in a browser-based render

    Page pseudo-classes let the first page, and left and right pages in a double-sided document, carry different margins from the rest.

  • page (named pages)Only in dedicated print engines

    A named @page rule plus the page property on an element lets one part of a document use a different page box from the rest.

  • @top-center and the margin boxesDoes nothing in a browser-based render

    The page margin boxes are sixteen named regions around the page box, such as @top-center and @bottom-right, each of which can hold generated content that repeats on every page.

  • counter(page)Does nothing in a browser-based render

    counter(page) and counter(pages) are automatic counters holding the current page number and the total, intended to be used in generated content.

Where pages break

  • break-insideWorks everywhere

    break-inside: avoid asks the layout not to put a page break inside this element.

  • break-beforeWorks everywhere

    break-before: page starts a new page before this element, whatever is left of the current one.

  • break-afterWorks everywhere

    break-after: avoid asks the layout not to break immediately after this element, which in practice keeps a heading attached to its section.

  • page-break-insideWorks everywhere

    page-break-before, page-break-after and page-break-inside are the original properties from CSS 2.1. The break-* properties replaced them and cover fragmentation in columns and regions as well as pages.

  • orphans and widowsWorks everywhere

    orphans sets the minimum number of lines of a paragraph that can be left at the bottom of a page; widows sets the minimum that can be carried to the top of the next one.

  • box-decoration-breakWorks in a browser-based render

    box-decoration-break decides whether an element that fragments across a break gets its border and padding applied once across the whole thing (slice) or on each fragment (clone).

  • theadWorks everywhere

    Rows inside a thead element repeat at the top of every page the table runs onto. This is markup, not CSS: there is no property that creates the behaviour.

  • column-countWorks in a browser-based render

    Multi-column layout flows content into columns, and in a paged context those columns fill one page before the flow continues on the next.

How it renders

  • print-color-adjustWorks in a browser-based render

    print-color-adjust: exact tells the renderer not to optimise colours away for printing, which is the per-element counterpart to the render's printBackground option.

  • @media printWorks everywhere

    The print media type matches when a document is being laid out for a paged medium, which a PDF render is.

  • prefers-color-schemeWorks everywhere

    prefers-color-scheme matches the environment's colour preference, which in a headless render is a default rather than anyone's choice.

  • position: fixedWorks in a browser-based render

    Fixed positioning places an element relative to the viewport. A paged document has either one viewport per page or none, depending on the engine, so the element repeats on every page or appears once.

  • image-renderingWorks everywhere

    image-rendering hints at the scaling algorithm, but blurry images in a PDF are almost always a resolution problem rather than an algorithm problem.

  • background on bodyWorks in a browser-based render

    A background set on html or body covers the canvas, which in a paged context means every page, though how it repeats depends on whether it is sized to the page or to the document.

  • opacity and mix-blend-modeWorks in a browser-based render

    Opacity works and produces real transparency in the output. Blend modes are composited during rendering, which means the result is correct and the layering information is gone.

  • box-shadowWorks in a browser-based render

    Shadows are backgrounds as far as print optimisation is concerned, so they are dropped along with background colours unless backgrounds are enabled.

Text and typography

  • @font-faceWorks everywhere

    @font-face declares a font and where to fetch it. The fetched font is embedded in the output, so the document renders identically for a reader who has never had the font installed.

  • font-displayWorks everywhere

    font-display controls what happens while a font is loading: swap shows fallback text immediately, block waits, optional gives up quickly.

  • unicode-rangeWorks everywhere

    unicode-range restricts a @font-face to a set of code points, so the browser only uses that face for characters inside the range.

  • font-variant-numericWorks everywhere

    font-variant-numeric: tabular-nums switches to fixed-width digit glyphs, so every digit occupies the same horizontal space.

  • hyphensWorks everywhere

    hyphens: auto lets the layout break words at syllable boundaries, using a dictionary for the language declared on the document.

  • overflow-wrapWorks everywhere

    overflow-wrap: break-word allows a break inside a word when the line has no other option; anywhere is more aggressive and also affects how the minimum width is calculated.

  • white-spaceWorks everywhere

    white-space: pre preserves formatting and refuses to wrap, which on a page means everything past the margin is lost. pre-wrap preserves the formatting and allows wrapping.

  • text-align: justifyWorks everywhere

    Justified text stretches the spaces on each line so both edges align. It is the default in most printed books and it needs hyphenation to look right.

  • line-heightWorks everywhere

    Line height sets the distance between baselines. Print conventions differ from screen conventions, and copying the screen value produces a document that looks loose and runs long.

  • text-wrap: balanceWorks in a browser-based render

    text-wrap: balance distributes a short block of text evenly across its lines rather than filling each line greedily, which prevents a heading ending with one word alone.

Units and measurement

  • mm, cm, in, ptWorks everywhere

    Physical units mean a real measurement in the output. A millimetre in a PDF is a millimetre on paper, which is not true of a millimetre on a screen.

  • px in a paged contextWorks everywhere

    CSS defines one inch as 96 pixels, so A4 at 210mm wide is 793.7 pixels. The fraction is the reason pixel-based page layouts drift.

  • vh and vwWorks in a browser-based render

    Viewport units resolve against the render viewport, which in a paged context is one page. 100vh is the height of a page, not the height of the document.

  • resolutionWorks everywhere

    CSS works at 96 dots per inch. Print quality is conventionally 300, so an image needs roughly three times its CSS pixel dimensions to look sharp on paper.