Skip to content

Styling

Press offers three ways to style elements: inline attributes, global style rules, and style aliases. This guide covers all three and shows how to build a consistent design system for your documents.

Inline Attributes

The simplest way to style an element is to set attributes directly on it:

xml
<frame background-color="#f5f5f5" padding="12pt" border-radius="4pt">
  <h2 font-color="#2c3e50" font-size="18pt">Quarterly Summary</h2>
  <p font-size="10pt" line-height="1.6">Revenue exceeded expectations...</p>
</frame>

Inline attributes always take the highest priority -- they override anything set in styles.

The <styles> Block

For consistent styling across a document, use the <styles> top-level element. Rules are defined by tag name:

xml
<styles>
  <document>
    <font>Helvetica</font>
    <font-size>10pt</font-size>
    <line-height>1.4</line-height>
  </document>

  <h1>
    <font-size>24pt</font-size>
    <font-style>bold</font-style>
    <font-color>#1a1a2e</font-color>
    <space-after-desired>16pt</space-after-desired>
  </h1>

  <h2>
    <font-size>16pt</font-size>
    <font-color>#16213e</font-color>
    <space-after-desired>12pt</space-after-desired>
  </h2>

  <p>
    <space-after-desired>8pt</space-after-desired>
  </p>

  <hr>
    <color>#e0e0e0</color>
    <height>0.5pt</height>
    <space-before-desired>12pt</space-before-desired>
    <space-after-desired>12pt</space-after-desired>
  </hr>
</styles>

The <document> rule sets defaults that all elements inherit. Every <h1> in the document will now use these styles without any inline attributes.

Style Aliases

Aliases let you define named style bundles and apply them with the style attribute:

xml
<styles>
  <alias name="card">
    <background-color>#ffffff</background-color>
    <padding>16pt</padding>
    <border-radius>6pt</border-radius>
    <border-weight>0.5pt</border-weight>
    <border-color>#e0e0e0</border-color>
  </alias>

  <alias name="primary-text">
    <font-color>#2563eb</font-color>
    <font-style>bold</font-style>
  </alias>

  <alias name="muted">
    <font-color>#6b7280</font-color>
    <font-size>9pt</font-size>
  </alias>
</styles>

Apply aliases with the @ prefix:

xml
<frame style="@card">
  <h3 style="@primary-text">Engagement Report</h3>
  <p style="@muted">Generated on 15 January 2026</p>
</frame>

Combining Aliases

Chain multiple aliases with semicolons:

xml
<frame style="@card;@primary-text">
  Combined card layout with primary text colour.
</frame>

When aliases conflict, later ones in the chain take priority.

Child Rules

Target child elements inside a style rule using <child name="...">:

xml
<styles>
  <table>
    <width>fill</width>
    <child name="td">
      <border-weight>0</border-weight>
      <border-weight-bottom>0.5pt</border-weight-bottom>
      <padding>8pt</padding>
      <v-align>center</v-align>
    </child>
    <child name="th">
      <background-color>#1a1a2e</background-color>
      <font-color>white</font-color>
      <font-style>bold</font-style>
      <padding>10pt</padding>
      <border-weight>0</border-weight>
    </child>
  </table>
</styles>

Child rules also work inside aliases:

xml
<alias name="clean-table">
  <child name="td">
    <border-weight>0</border-weight>
    <padding-left>0pt</padding-left>
    <padding-top>4pt</padding-top>
    <padding-bottom>4pt</padding-bottom>
  </child>
</alias>

Colour Formats

Press supports multiple colour formats anywhere a colour value is expected:

FormatExampleNotes
Hex (short)#RGBThree-character shorthand
Hex (full)#RRGGBBSix-character hex
Hex (alpha)#RRGGBBAAEight-character with alpha
RGBrgb(66, 135, 245)Functional notation
RGBArgba(66, 135, 245, 0.5)With transparency
HSLhsl(220, 90%, 61%)Hue, saturation, lightness
Namedwhite, black, greyCommon colour names
Asset colourprimaryReferences a colour from <assets><colors>
xml
<frame background-color="rgba(0, 0, 0, 0.05)" border-color="#e5e7eb">
  <p font-color="primary">Uses a named asset colour for text.</p>
</frame>

Priority Order

When the same property is set in multiple places, the order of priority is:

  1. Inline attributes (highest) -- <frame padding="8pt">
  2. Style aliases -- style="@card"
  3. Tag-name rules -- <styles><frame><padding>...</padding></frame></styles>
  4. Inherited from parent -- e.g., font-color set on <document> flows down to children
  5. Press defaults (lowest)

Example: A Brand Style System

Here's a complete document using a brand style system. The styles define document defaults, heading treatments, table styling, and reusable aliases -- then the document, flows, components, and data put them to use:

xml
<press>
  <document format="A4" page-margin="2cm">
    <page>
      <frame direction="row" v-align="center" space-after-desired="24pt">
        <img src="logo" max-height="36pt" />
        <frame padding-left="12pt" font-size="14pt" font-color="brand-primary" font-style="bold">
          {{ data.company }}
        </frame>
      </frame>
      <hr />
      <frame height="fill">
        <flow name="report" />
      </frame>
      <page-footer show-page-num="false" />
    </page>

    <page repeat="true" flow="report" page-margin-top="2.5cm">
      <frame height="fill">
        <flow name="report" />
      </frame>
      <page-footer />
    </page>
  </document>

  <flows>
    <report>
      <h1>{{ data.title }}</h1>
      <p>Prepared by {{ data.author }} · {{ data.date }}</p>

      <h2>Overview</h2>
      <p>This report presents key performance indicators across all
        operating regions for the current fiscal year. Growth was
        driven by expansion in the Northern and Western divisions.</p>

      <frame style="@highlight-box" space-before-desired="12pt" space-after-desired="12pt">
        <b>Key Insight:</b> Overall revenue grew 15% year-on-year,
        outperforming the industry average of 9%.
      </frame>

      <h2>Regional Performance</h2>
      <table>
        <tr>
          <th width="35%">Region</th>
          <th text-align="right">Revenue</th>
          <th text-align="right">Expenses</th>
          <th text-align="right">Growth</th>
        </tr>
        <repeat data="data.regions" item="region">
          <tr>
            <td>{{ region.name }}</td>
            <td text-align="right">{{ data.currency }}{{ region.revenue }}</td>
            <td text-align="right">{{ data.currency }}{{ region.expenses }}</td>
            <td text-align="right">{{ region.growth }}</td>
          </tr>
        </repeat>
      </table>
      <frame style="@caption" space-before-desired="6pt">
        Table 1 — Regional revenue and expenses for the year ending December 2025.
      </frame>

      <h2>Summary</h2>
      <p>All regions met or exceeded their annual targets. The board
        recommends continued investment in the Northern region, which
        showed the highest growth trajectory.</p>

      <frame style="@highlight-box" space-before-desired="12pt" break="never">
        <b>Next Steps:</b> Detailed divisional breakdowns will be
        circulated ahead of the Q1 planning session on {{ data.next-meeting }}.
      </frame>
    </report>
  </flows>

  <components>
    <page-footer show-page-num="true" font-size="8pt" font-color="#9ca3af">
      <frame width="100%" direction="row" v-align="center" padding-top="12pt">
        <frame width="fill">{{ data.company }}</frame>
        <frame width="fill" text-align="center" h-align="center">
          <frame show-if="{{ attrs.show-page-num }}">
            <page-number /> / <total-pages />
          </frame>
        </frame>
        <frame width="fill" text-align="right" h-align="right">{{ data.date }}</frame>
      </frame>
    </page-footer>
  </components>

  <styles>
    <document>
      <font>Inter</font>
      <font-size>10pt</font-size>
      <line-height>1.5</line-height>
      <font-color>#1f2937</font-color>
    </document>

    <h1>
      <font>Playfair Display</font>
      <font-size>28pt</font-size>
      <font-color>#0f172a</font-color>
      <space-after-desired>20pt</space-after-desired>
    </h1>

    <h2>
      <font-size>16pt</font-size>
      <font-style>bold</font-style>
      <font-color>#0f172a</font-color>
      <space-before-desired>24pt</space-before-desired>
      <space-after-desired>12pt</space-after-desired>
    </h2>

    <hr>
    <color>#e5e7eb</color>
    <height>0.5pt</height>
    <space-before-desired>4pt</space-before-desired>
    <space-after-desired>20pt</space-after-desired>
    </hr>

    <table>
      <width>fill</width>
      <child name="th">
        <background-color>brand-dark</background-color>
        <font-color>white</font-color>
        <font-style>bold</font-style>
        <font-size>9pt</font-size>
        <padding>10pt</padding>
        <border-weight>0</border-weight>
      </child>
      <child name="td">
        <border-weight>0</border-weight>
        <border-weight-bottom>0.5pt</border-weight-bottom>
        <border-color>#e5e7eb</border-color>
        <padding>8pt</padding>
      </child>
    </table>

    <alias name="highlight-box">
      <background-color>#eff6ff</background-color>
      <padding>16pt</padding>
      <border-weight-left>3pt</border-weight-left>
      <border-color>brand-primary</border-color>
      <border-radius>4pt</border-radius>
    </alias>

    <alias name="caption">
      <font-size>8pt</font-size>
      <font-color>#6b7280</font-color>
      <font-style>italic</font-style>
    </alias>
  </styles>

  <assets>
    <colors>
      <brand-primary>#6900F4</brand-primary>
      <brand-dark>#5000C0</brand-dark>
    </colors>
    <images>
      <logo>https://examples.papermill.io/papermill_logo.png</logo>
    </images>
  </assets>

  <data type="json">
  {
    "company": "Northbrook Analytics",
    "title": "Annual Performance Report",
    "author": "R. Whitfield",
    "date": "January 2026",
    "currency": "£",
    "next-meeting": "14 February 2026",
    "regions": [
      { "name": "Northern", "revenue": "1,240,000", "expenses": "890,000", "growth": "+18%" },
      { "name": "Southern", "revenue": "980,000", "expenses": "710,000", "growth": "+12%" },
      { "name": "Eastern", "revenue": "860,000", "expenses": "620,000", "growth": "+9%" },
      { "name": "Western", "revenue": "1,100,000", "expenses": "805,000", "growth": "+15%" }
    ]
  }
  </data>
</press>