@page

Get affordable and hassle-free WordPress hosting plans with Cloudways — start your free trial today.

The @page at-rule lets us style a site when presented as a paged media, that is, when printed or displayed as a PDF. Specifically, it allows us to set the page’s size, orientation, and margins. In supporting browsers, we can even use it to embed headings and footers in the printed pages.

@page {
  size: landscape;

  margin-top: 3cm;
  margin: 2.54cm; /* or 1in */
}

@page :right {
  margin-left: 4cm;
}

Click the print button in the following demo and check how the page margins and orientation change:

The @page at-rule is defined in the CSS Paged Media Module Level 3

Syntax

@page = @page <page-selector-list>? { <declaration-rule-list> }
<page-selector-list> = <page-selector>#
<page-selector> = [ <ident-token>? <pseudo-page>* ]!
<pseudo-page> = ':' [ left | right | first | blank ]

In addition, we have 16 margin rules, each representing a region of the margin:

@top-left-corner { <declaration-list> };
@top-left { <declaration-list> };
@top-center { <declaration-list> };
@top-right { <declaration-list> };
@top-right-corner { <declaration-list> };
@bottom-left-corner { <declaration-list> };
@bottom-left { <declaration-list> };
@bottom-center { <declaration-list> };
@bottom-right { <declaration-list> };
@bottom-right-corner { <declaration-list> };
@left-top { <declaration-list> };
@left-middle { <declaration-list> };
@left-bottom { <declaration-list> };
@right-top { <declaration-list> };
@right-middle { <declaration-list> };
@right-bottom { <declaration-list> };

Margin rules can’t exist outside the @page main at-rule, and can only contain page-margin properties. In other words, these at-rules are designed to work specifically with @page and nowhere else.

Selectors and properties

/* Simple @page declaration */
@page {
    margin: 2.54cm;
    size: A4 landscape;
    page-orientation: rotate-left;
}

/* Using Pseudo-classes */
@page :first {
    margin-top: 3cm;
}

@page :right {
    margin-left: 3cm;
}

@page :left {
    margin-right: 3cm;
}

/* Margin At-Rules (CHROMIUM ONLY) */
@page {
    margin: 2cm;

    @top-center {
        content: "My Title";
    }
}

/* Page Counters (CHROMIUM ONLY) */
@page {
    @bottom-center {
        content: counter(page);
    }
}

The @page at-rule has four (supported) pseudo-classes to select pages based on their content or position:

  • :blank: Matches pages without content. Empty pages are created by the break-after or break-before when used to force page breaks.
  • :first: Matches the first page of the document.
  • :right: In a double-sided document, matches the right pages. In other words, it matches the odd pages in the document.
  • :left: In a double-sided document, matches the left pages. In other words, it matches the even pages in the document.

We consider :right as the odd pages since books in English usually start at the first right page. Sadly, we will have to wait before we get logical versions of them that are based on writing mode instead.

According to the spec, we have lots of properties available to style paged media, but sigh browser support… So right now, only the following properties are supported in all major browsers:

  • margin: Sets the space between the document’s content and its borders. It still works as a shorthand, so all the individual margin-leftmargin-topmargin-right and margin-bottom properties are available. At the moment, flow-relative properties (like margin-block-start) are only supported in Chromium.
  • size: Sets the size of the printed document, it can be…
    • auto: Lets the browser decide, usually tries to match the target media sheet.
    • landscape: Prints the page content in landscape orientation.
    • portrait: Prints the page content in portrait orientation.
    • <length [0,∞]>: Manually sets the length of the printed document. By writing one length, it will set both sides. Writing two lengths will set the width and then the height of the document.
    • <page-size>: Picks the page size from one of the printed media sheets. It can be used along the landscape and portrait to pick both size and orientation.
  • page-orientation: Can be used to rotate the final output of the page by 90 degrees. Its possible values are:
    • upright: Keeps the page as is.
    • rotate-left: Rotates the page 90deg to the left.
    • rotate-right: Rotates the page 90deg to the right.

Available <page-size> values are:

ValueEquivalentWidth (cm)Height (cm)
A5ISO A5 Media14.821.0
A4ISO A4 Media21.029.7
A3ISO A3 Media29.742.0
B5ISO B5 Media17.625.0
B4ISO B4 Media25.035.3
JIS-B5JIS B5 Media18.225.7
JIS-B4JIS B4 Media25.736.4
letterNA Letter Media21.5927.94
legalNA Legal Media21.5935.56
ledgerNA Ledger Media27.9443.18

Basic usage

Go ahead and press Ctrl + P or Command + P right now. Yes, I am waiting for you to do it. Nice! You should see the printing menu open up, showing this entry as a paged media, that is a document divided into pages. It looks pretty different from your everyday CSS-Tricks, I may even say it’s a little hard on the eyes. Don’t be surprised, making pages look as good as webpages requires a new toolbox of CSS and the @page at-rule is among them.

In its most basic form, @page sets the margin, size, and orientation of paged media. For example, we can set the margin for each page to match APA style (which is 1in, but I refuse to use imperial units, so 2.54cm):

@page {
  margin: 2.54cm;
}

@page also comes with pseudo-classes that are used to match certain pages. For example, the :first pseudo-class matches the first page, which can be used to give it a different margin than the rest, e.g. for an initial header:

@page :first {
  margin-top: 5cm;
}

We can also select only even or odd pages using the :left and :right pseudoclasses. For example, in a double-sided document that will be stapled together, we may leave a wider margin on the center side of each page, that is, a wider right margin on left pages and a wider left margin for right pages:

@page :left {
  margin-right: 4cm;
}

@page :right {
  margin-left: 4cm;
}

Using @page, we can also change the page size using the size property. For example, we could print the page into an A5 page (14.8×21.0 cm) laid on landscape, and the content will break down accordingly.

@page {
  size: A5 landscape;
}

Lastly, we may want to change the page orientation. Using the page-orientation property, we can turn it 90 degrees to the left by setting it to rotate-left and to the right using rotate-right. If you wish to turn it upside down, I encourage turning your paper sheet 180 degrees.

@page {
  page-orientation: rotate-left;
}

Margins at-rules

From here onwards, we will be talking about features that are only available in Chromium because… browser support is lacking… again.

The first member on this unsupported list is the Margins at-ules, a series of rules that can be used to embed content on the margins of documents, such as headers, footers, or page numbers. There are exactly 16 margin at-rules, each representing a region of the margin as shown here:

Diagram showing the position of each margin-rule

However, this image is a little misleading since it shows all Margins at-rules living together in the same document. In reality, a region doesn’t exist until we initiate the at-rule. To do so, we write the region we want to display and give it a content, similar to how we display ::before and ::after. This allows us to embed something like the title of the book as a header and display it on each printed page:

@page {
  margin: 2cm;

  @top-center {
    content: "My Title";
  }
}

One thing to notice, corner margins have a fixed size given by the intersection of the margins, so the @top-left-corner size will depend on the size of margin-top and margin-left. However, the rest will act kinda like flex items, trying to fill the available space:

Margin regions sizes depending on sibling regions

Even though a single @top-center and a single @top-right take the same space, their text-align properties will change to match their region. The same thing happens on the left and right regions, in which the vertical-align of @left-middle is middle while in @left-bottom it’s bottom.

More properties

The only properties available in all major browsers are the ones I mentioned before: marginsize, and page-orientation. However, Chromium browsers offer A LOT more properties to style the margin and each of its regions. You can find the whole list listed in the Spec, but it includes things like:

  • background properties.
  • border properties.
  • counter properties.
  • font properties.
  • height properties
  • outline properties
  • padding properties
  • text properties
  • width properties.

Counters in pages

You may notice a key element from printed media is missing: page numbers! Luckily in Chromium, the browser creates two counters for paged media: page that increments for each page and pages which holds the total number of pages and isn’t incremented.

We can display the current page count using the counter() function on any of the margin regions content property. For example, we could put together everything we’ve learned (margins, pseudo-classes, and margin at-rules) to display the current page count at the lower-left region of each left page and the lower-right region of each right page:

@page {
  margin-bottom: 2.54cm;
}

@page :left {
  @bottom-left {
    content: counter(page);
  }
}

@page :right {
  @bottom-right {
    content: counter(page);
  }
}

A lot of new things… in the future

Right now, the CSSWG has two working draft specs related to paged media that may come soon. The first is CSS Logical Properties and Values Module Level 1, which defines logical equivalents for the :right and :left pseudo-classes that will depend on the user’s page progression.

In English and Spanish, we turn pages from left to right, but there are some cases in which it’s the other way around. For example, some media in Japanese and Chinese are paginated from right to left. For this, the spec defines:recto (the logical equivalent of :right) and :verso (the logical equivalent of :left) that will vary depending on the user’s page progression.

The second work draft specificication is the larger CSS Generated Content for Paged Media Module which defines ways to capture the content of the HTML and use it as the content inside margin regions.

Specification

The @page at-rule is defined in the CSS Paged Media Module Level 3. There are also many drafts throughout the spec that define (hopefully) soon-to-be-shipped features around @page. The :recto and :verso logical pseudo-classes are defined in the CSS Logical Properties and Values Level 1 and the Generated Content for Paged Media is defined in the module of the same name.

Browser support

Right now, the only @page features supported in all browsers are the marginsize and page-orientation properties. While margin at-rules, the rest of the properties and counters are only available in Chromium.

More information