Appearance
Tables
Tables in Press use familiar HTML-like syntax. This guide covers everything from basic structure to data-driven tables, styling, and advanced features like column spanning and rotation.
Basic Structure
xml
<table>
<tr>
<th>Region</th>
<th>Revenue</th>
<th>Growth</th>
</tr>
<tr>
<td>North</td>
<td>£1.2M</td>
<td>+12%</td>
</tr>
<tr>
<td>South</td>
<td>£980K</td>
<td>+8%</td>
</tr>
</table>The standard tags <tr>, <td>, and <th> are components from Press's standard library. The underlying primitives are table, row, and cell.
Column Widths
Set widths on cells in the first row to control column proportions:
xml
<table>
<tr>
<th width="50%">Description</th>
<th width="20%">Quantity</th>
<th width="30%">Price</th>
</tr>
...
</table>Width values can be percentages, fixed sizes (100pt), or fill for remaining space.
Column Spanning
Use colspan to span a cell across multiple columns:
xml
<tr>
<td colspan="2" font-style="bold" text-align="right">Subtotal:</td>
<td text-align="right">£2,180</td>
</tr>Styling Tables
Inline Styles on Cells
xml
<tr>
<th background-color="#1e3a5f" font-color="white" padding="10pt">Region</th>
<th background-color="#1e3a5f" font-color="white" padding="10pt">Revenue</th>
</tr>Global Table Styles
Using <styles> with <child> rules is far cleaner for consistent table styling:
xml
<styles>
<table>
<width>fill</width>
<child name="th">
<background-color>#1e3a5f</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-left>10pt</padding-left>
<padding-right>10pt</padding-right>
<padding-top>8pt</padding-top>
<padding-bottom>8pt</padding-bottom>
<v-align>center</v-align>
</child>
</table>
</styles>Style Aliases for Table Variants
Create different table styles and apply them by name:
xml
<styles>
<alias name="borderless">
<child name="td">
<border-weight>0</border-weight>
<padding>4pt</padding>
</child>
</alias>
<alias name="summary-row">
<child name="td">
<border-weight>0</border-weight>
<padding-top>16pt</padding-top>
<padding-bottom>16pt</padding-bottom>
</child>
</alias>
</styles>xml
<table style="@borderless">...</table>
<tr style="@summary-row">
<td colspan="2" font-style="bold" text-align="right">Grand Total:</td>
<td text-align="right">£4,500</td>
</tr>Cell Alignment
| Attribute | Applies to | Values |
|---|---|---|
text-align | Text within cell | left, right, center, justified |
h-align | Cell content block | left, center, right |
v-align | Cell content block | top, center, bottom |
xml
<td text-align="right" v-align="center">£1,200</td>Border Properties
Table borders automatically collapse to avoid duplicate borders rendering between cells. Here are properties for controlling borders:
| Attribute | Description |
|---|---|
border-weight | All borders |
border-weight-top | Top border only |
border-weight-bottom | Bottom border only |
border-weight-left | Left border only |
border-weight-right | Right border only |
border-color | Color of all borders |
border-color-top | Color of top border |
border-color-bottom | Color of bottom border |
border-color-left | Color of left border |
border-color-right | Color of right border |
xml
<td border-weight="0" border-weight-bottom="1pt" border-color="#d1d5db">
Content with only a bottom border
</td>Data-Driven Tables
Generate rows from data with <repeat>:
xml
<table>
<tr font-size="9pt">
<th width="45%">Description</th>
<th text-align="center">Price</th>
<th text-align="center">Qty</th>
<th text-align="right">Total</th>
</tr>
<repeat data="data.items" item="line">
<tr font-size="8pt">
<td>
<frame font-size="9pt">{{ line.name }}</frame>
<frame show-if="line.description" font-size="8pt" font-color="#6b7280">
{{ line.description }}
</frame>
</td>
<td h-align="center">£{{ line.price }}</td>
<td h-align="center" text-align="center">{{ line.quantity }}</td>
<td h-align="right">£{{ line.total }}</td>
</tr>
</repeat>
</table>Tables Across Pages
Tables inside flows automatically break across pages. Each row is treated as a breakable unit -- Press will move the new row onto a new page or into a new frame.
To stop a table from breaking:
xml
<table break="never">
<tr background-color="#1e3a5f" font-color="white">
<td width="65%" font-style="bold" text-align="right" colspan="2">
Subtotal:<br />Tax (20%):
</td>
<td h-align="right">
£1,800<br />£360
</td>
</tr>
<tr background-color="#0f172a" font-color="white" font-size="12pt">
<td font-style="bold">Payment: Bank Transfer</td>
<td font-style="bold" text-align="right">Grand Total:</td>
<td h-align="right" font-style="bold">£2,160</td>
</tr>
</table>Rotated Tables
For wide data tables that don't fit in portrait, rotate the frame 270 degrees:
xml
<frame rotation="270" height="100%">
<table>
<tr>
<th>Variable</th>
<th>Jan</th>
<th>Feb</th>
<th>Mar</th>
<th>Apr</th>
<th>May</th>
<th>Jun</th>
<th>Jul</th>
<th>Aug</th>
<th>Sep</th>
<th>Oct</th>
<th>Nov</th>
<th>Dec</th>
</tr>
<repeat data="data.monthly-stats" item="row">
<tr font-size="7pt">
<td font-style="bold">{{ row.variable }}</td>
<repeat data="row.values" item="val">
<td text-align="center">{{ val }}</td>
</repeat>
</tr>
</repeat>
</table>
</frame>Note: width and height on rotated elements refer to pre-rotation dimensions. In the example above, the table is given the full height of the frame as width to render. See the Transformations guide for details.