@cassida/plugin-print
v0.7.0
Published
Cassida companion plugin: ships a `printPreflight()` factory returning a CSS string of conservative @media print defaults (black-on-white, expand external link URLs, page-break hygiene, image width clamp). Designed to be served through @cassida/plugin-glo
Maintainers
Readme
@cassida/plugin-print
Companion plugin for Cassida that ships a printPreflight() factory
returning a CSS string of conservative @media print defaults — the
kind of preflight every printable page benefits from regardless of
site design.
Cassida is a CSS-mania library, so print styling is a first-class concern out of the box.
What's in the preflight
- Black-on-white, no shadows / backgrounds. Saves ink and makes copy legible. The user opts back in when they actually need a brand-color page.
- External link URLs appended. Anchors with an absolute
http:///https://///href get(https://example.com/...)glued after their visible text, withoverflow-wrap: break-wordso a long URL wraps inside the column instead of bleeding off the page. Relative paths and non-web schemes (mailto:,tel:,javascript:) are skipped — their expanded form would be uninformative noise. Strict-prefix selectors (the trailing://) avoid the false positive where a relative filename likehttp-server.pdfwould have matched a bare[href^="http"]. - Abbreviation expansion.
<abbr title="...">FYI</abbr>prints asFYI (For Your Information)— H5BP-classic idiom that uses the sametitleattribute screen readers already announce. - Page-break hygiene.
pre,blockquote,tr, and the media group (img,svg,video,canvas) don't break across pages. All heading levels (h1-h6) avoid being orphaned at page end from their body content. Body text and list items (p,li) useorphans: 2/widows: 2— enough to prevent true singletons without forcing 3-5 line paragraphs onto the next page. - Media width clamp.
img, svg, video, canvas { max-width: 100%; height: auto }keeps oversized media inside the printable area without distorting the aspect ratio (height: autoundoes any HTML / CSS height that would otherwise lock the box shape after the width shrinks).<video>prints its poster image and<canvas>is commonly used for charts — same treatment. - Table header / footer repetition.
theadis restored todisplay: table-header-groupandtfoottodisplay: table-footer-groupso printed tables repeat their header and footer rows across page boundaries. - Pre wrapping.
pre { white-space: pre-wrap }so long source lines don't fall off the page edge.
The rules are adapted from the well-known HTML5 Boilerplate print
stylesheet subset (MIT-licensed). They are deliberately conservative;
opinionated decisions like "hide nav / footer / button" stay
out of the library default because they're site-specific.
The preflight intentionally ships without !important. CSS
Cascade Layers flip the precedence on important declarations —
!important in earlier layers wins over !important in later ones,
which would lock users out of overriding the defaults from their own
@layer cas rules. Without !important, the canonical @layer base,
cas; declaration order plus class-vs-universal specificity does the
right thing: explicit Cassida-driven colors print as written, while
elements without an explicit color fall back to ink-saving black.
Install
pnpm add @cassida/plugin-print
pnpm add -D @cassida/plugin-global-css # peer for deliveryUse
printPreflight() returns a CSS string. It does not ship its own
stylesheet delivery — pair it with @cassida/plugin-global-css to
mount the rules through Vite's CSS pipeline:
// vite.config.ts
import { defineConfig } from 'vite';
import { cassida } from '@cassida/vite-plugin';
import { cassidaGlobalCss } from '@cassida/plugin-global-css';
import { recommended } from '@cassida/recommended';
import { printPreflight } from '@cassida/plugin-print';
export default defineConfig({
plugins: [
cassida(recommended()),
cassidaGlobalCss({
css: printPreflight(),
layer: 'base',
virtualId: 'virtual:cassida-print.css',
}),
],
});// main.tsx
import 'virtual:cassida-print.css';The bundled rules are wrapped in @media print so they only affect
print output; screen rendering is untouched. The default @layer base
wrap pairs with the cascade declaration @layer base, cas; so any
Cassida classes you set print-specific overrides on still win without
specificity tricks.
Site-specific extensions
To tack on rules that hide your site's nav / footer / interactive controls (which the library default deliberately doesn't touch), concatenate or override:
cassidaGlobalCss({
css: printPreflight() + `
@media print {
nav, footer, button, [aria-hidden="true"] {
display: none !important;
}
body {
font-family: Garamond, "Times New Roman", serif;
}
}
`,
layer: 'base',
virtualId: 'virtual:cassida-print.css',
});Preserving icons / logos in print
The universal selector clears background and forces color: #000
so prose pages don't burn ink on every gradient and shadow. That
zeroes out background-image too, which can erase essential
elements like icon spritesheets or brand logos rendered as
background images. Because the preflight is !important-free, you
can override per-element from your Cassida chain:
<span
{...cas.unsafe({ 'print-color-adjust': 'exact' })
.backgroundImage('url(/logo.svg)')
.props}
/>Two parts to the override: backgroundImage(...) beats the
universal-selector background: transparent via class specificity
(later layer in @layer cas, base-aware terms — see "Why no
!important" above), and print-color-adjust: exact tells the
browser to actually paint that background even in print mode.
Routed through cas.unsafe because print-color-adjust lives
outside Cassida's curated safe surface.
Replace the bundled defaults entirely
Authoring a fully custom print stylesheet from scratch? Skip the
factory and feed your own string straight to cassidaGlobalCss:
cassidaGlobalCss({
css: myOwnPrintCss,
layer: 'base',
virtualId: 'virtual:cassida-print.css',
});printPreflight() is opinion-free beyond what it returns — no
"replace defaults" knob exists because string concatenation already
covers extension and direct assignment already covers full
replacement.
License
MIT © pishio. Bundled print-rule subset adapted from HTML5 Boilerplate (MIT).
