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 thebreak-after
orbreak-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 individualmargin-left
,margin-top
,margin-right
andmargin-bottom
properties are available. At the moment, flow-relative properties (likemargin-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 inlandscape
orientation.portrait
: Prints the page content inportrait
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 thelandscape
andportrait
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 page90deg
to the left.rotate-right
: Rotates the page90deg
to the right.
Available <page-size>
values are:
Value | Equivalent | Width (cm) | Height (cm) |
---|---|---|---|
A5 | ISO A5 Media | 14.8 | 21.0 |
A4 | ISO A4 Media | 21.0 | 29.7 |
A3 | ISO A3 Media | 29.7 | 42.0 |
B5 | ISO B5 Media | 17.6 | 25.0 |
B4 | ISO B4 Media | 25.0 | 35.3 |
JIS-B5 | JIS B5 Media | 18.2 | 25.7 |
JIS-B4 | JIS B4 Media | 25.7 | 36.4 |
letter | NA Letter Media | 21.59 | 27.94 |
legal | NA Legal Media | 21.59 | 35.56 |
ledger | NA Ledger Media | 27.94 | 43.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:

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:

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: margin
, size
, 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
propertiesoutline
propertiespadding
propertiestext
propertieswidth
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 margin
, size
and page-orientation
properties. While margin at-rules, the rest of the properties and counters are only available in Chromium.
More information
- The At-Rules of CSS (Geoff Graham)
- Add content to the margins of web pages when printed using CSS (Rachel Andrew)
Related
:first
@page :first { margin: 50%; }
:right
@page :left { margin: 1in 2in; }
:left
@page :left { margin: 1in 2in; }
:blank
p:blank { display: none; }
break-after
.element { page-break: always; }
break-before
.element { break-before: column; }
page-break
.element { page-break-before: always; }
break-inside
.element { break-inside: avoid; }