Print Stylesheets for Data Tables
Permalink to "Print Stylesheets for Data Tables"Printing is unglamorous but real: auditors print reconciliations, managers print weekly reports, and many users with low vision or cognitive disabilities find paper easier to read than a dense screen. Data tables print badly by default. Wide grids are clipped at the right margin, sticky headers print once on page one, row striping and status colours vanish because browsers drop background colours, and scroll containers print only their visible part.
This guide belongs to data export & print.
Spec reference
Permalink to "Spec reference"There is no WCAG criterion about printed output, but printing is how many users consume the same content, and the principles carry over:
- SC 1.4.1 Use of Color (A) — browsers remove background colours by default when printing, so colour-only status disappears entirely on paper.
- SC 1.3.1 Info and Relationships (A) — headers must be identifiable on every page; CSS
display: table-header-grouprepeatstheadacross pages in all major browsers. - SC 1.4.10 Reflow (AA) and SC 1.4.4 Resize Text (AA) — on screen, the same reflow techniques that help zoom users help printing: content that fits a narrow width prints without clipping.
- CSS Paged Media —
@pagesize and margins,break-inside: avoidon rows.
When to use — and when not to
Permalink to "When to use — and when not to"Add a print stylesheet to any page where users might reasonably print a table: reports, statements, reconciliations, admin lists. Add a visible “Print” button only if printing is a real task; browsers’ own print command is otherwise enough.
Do not try to print a virtualized grid as-is: only rendered rows exist in the DOM. Either render all rows for printing (if the count is reasonable), or route users to a print-optimised view or a PDF.
The misapplication: @media print { .grid { overflow: visible; } } and nothing else. Wide tables then overflow the page edge, clipped and unreadable.
Annotated code example
Permalink to "Annotated code example"@media print {
@page { size: A4 landscape; margin: 12mm; }
/* Remove interactive chrome */
.toolbar, .pagination, .row-actions, .site-header, .site-footer { display: none !important; }
/* Undo screen scroll containers so every row prints */
.table-scroll { overflow: visible !important; max-height: none !important; }
/* Header row repeats on every page (SC 1.3.1 by analogy) */
thead { display: table-header-group; }
tfoot { display: table-footer-group; }
tr, td, th { break-inside: avoid; }
table { font-size: 9pt; border-collapse: collapse; width: 100%; }
th, td { border: 0.5pt solid #000; padding: 2pt 4pt; color: #000 !important; }
/* Status must not depend on background colour (SC 1.4.1) */
.status-badge { background: none !important; border: 0.5pt solid #000; }
.print-caption { display: block !important; font-size: 9pt; margin-bottom: 4pt; }
a[href]::after { content: none; } /* avoid URL clutter in cells */
}
.print-caption { display: none; }
<!-- Print-only context: what this printout is (hidden on screen) -->
<p class="print-caption">Invoices — Status: Overdue — sorted by Due date, oldest first — printed 2 October 2026</p>
<div class="table-scroll" tabindex="0" role="region" aria-label="Invoices">
<table>…</table>
</div>
Keyboard & AT behaviour
Permalink to "Keyboard & AT behaviour"Printing is triggered with Ctrl+P (Cmd+P) or a Print button; the print dialog is browser UI and is announced by the screen reader. The considerations are mostly about the page:
| Event | Expected behaviour | Notes |
|---|---|---|
| Ctrl+P | Browser print dialog | Do not intercept unless offering a custom print view |
| Print button | Calls window.print(); name: “Print invoices table” |
Keep focus on the button after the dialog closes |
| Screen reader user prints for a sighted colleague | Output matches what they filtered | The print caption confirms filters |
| Print preview | Header row on every page | Verify in Chrome, Firefox and Safari |
Integration context
Permalink to "Integration context"The same structural decisions that make tables reflow on screen help them print — see meeting reflow 1.4.10 with wide tables and sticky headers and first columns, whose sticky positioning must be disabled in print. For long or formal reports, a tagged PDF may suit better: generating accessible PDF reports from data views.
Gotchas
Permalink to "Gotchas"Sticky headers print in the wrong place. position: sticky can leave a header stuck mid-page in print. Reset to position: static in the print stylesheet.
Dark mode. Users printing from a dark theme get dark backgrounds that browsers then drop, leaving light text on white. Force color: #000 in print.
Totals rows. If totals live in tfoot, display: table-footer-group repeats them on every page in some browsers — usually not what you want for a grand total. Put grand totals after the table, or accept the repeat with a clear label.
Framework notes
Permalink to "Framework notes"Grid libraries render their own DOM, which print styles must target. AG Grid offers a print layout (api.setGridOption('domLayout', 'print')) that renders all rows without virtualization — switch to it before window.print() and back afterwards. MUI X Premium has printOptions on its export; it opens a print window with all rows. For Angular Material tables, standard CSS works because the DOM is a real table.
// AG Grid: print every row, then restore
api.setGridOption('domLayout', 'print');
setTimeout(() => { window.print(); api.setGridOption('domLayout', 'normal'); }, 0);
Testing checklist
Permalink to "Testing checklist"Design system notes
Permalink to "Design system notes"Ship print styles with the table component and a printCaption prop, so every product’s tables print consistently. Status badges should always include text, which makes them print-safe by design.
FAQ
Permalink to "FAQ"Should I add a Print button?
Only if printing is a common task for the page. Browser print works everywhere; a button adds discoverability for users who do not know Ctrl+P.
How do I handle tables wider than a landscape page?
Reduce font size moderately, drop non-essential columns in print with a class, or print a narrower “report” view. Never let columns clip silently.
Can screen reader users check what will print?
Print preview is visual. The print caption and a “What will print” summary near the Print button help: “Prints 240 rows, 5 columns, landscape.”
Do printed tables need row numbers?
For long printouts, a row number column helps people refer to rows in conversation. Add it in print only if it would clutter the screen.
Should print output use the user's chosen theme or zoom?
Print should ignore the dark theme (force dark text on white) but respect the browser’s print scaling, which users adjust in the print dialog. Avoid fixed pixel font sizes in print styles; points or relative units scale better.
Related
Permalink to "Related"- CSV and Excel exports — the digital alternative
- Sticky headers and first columns — reset them for print
- Windows High Contrast audits — another place background colours vanish