Beginner

Print Stylesheet

A real @media print stylesheet, loaded site-wide — strips chrome, forces light mode, and prints link URLs.

2 min read

Live Implementation

There's no fake preview here — this is a real @media print stylesheet, already loaded on this exact page. Press Ctrl+P (Cmd+P on a Mac) right now, or open Print Preview, to see it applied for real:

How It Works

Everything lives in one @media print block, loaded on every page, not just this one. Three things it does:

Strips the chrome. The header, footer, breadcrumbs, and Prev/Next links exist to help someone navigate a website — none of that means anything once the page is on paper, so they’re hidden outright:

.site-header,
.site-footer,
.breadcrumbs,
.pagination-nav {
    display: none !important;
}

Forces light mode, regardless of the real toggle. This site’s dark mode sets colors through :root[data-theme="dark"] — a fairly specific selector. To reliably win against it during print, the print rule targets that exact same selector (plus :root[data-theme="light"], plus the bare :root) inside @media print, so it always wins no matter which theme is active when someone hits print:

@media print {
    :root,
    :root[data-theme="dark"],
    :root[data-theme="light"] {
        --color-bg: #ffffff;
        --color-fg: #000000;
    }
}

Prints link destinations. A link is only clickable on a screen. On paper, <a href="..."> text alone loses the URL entirely — so external links get it appended in parentheses automatically:

a[href^="http"]:not([href*="11ty-demos.netlify.app"])::after {
    content: " (" attr(href) ")";
}

Folder Structure

src/assets/scss/base/_print.scss ← the whole stylesheet
src/assets/scss/main.scss        ← registers it, right after base/theme

Important Files

src/assets/scss/base/_print.scss

@media print {
    :root,
    :root[data-theme="dark"],
    :root[data-theme="light"] {
        --color-bg: #ffffff;
        --color-bg-raised: #ffffff;
        --color-bg-inset: #f2f2f2;
        --color-fg: #000000;
        --color-fg-muted: #333333;
        --color-border: #999999;
        --color-accent-strong: #000000;
        --color-code-bg: #f2f2f2;
        --token-string: #146b45;
        --token-keyword: #8a3d7a;
        --token-function: #2a5fb0;
        --token-number: #a05a1a;
        --token-property: #8a6a15;
        --shadow-hard: none;
        --shadow-hard-lg: none;
    }

    html,
    body {
        background: #fff;
        color: #000;
    }

    .site-header,
    .site-footer,
    .skip-link,
    .breadcrumbs,
    .demo__related,
    .pagination-nav {
        display: none !important;
    }

    .demo-card,
    .demo__live-frame,
    pre,
    blockquote,
    img,
    svg {
        break-inside: avoid;
    }

    a[href^="http"]:not([href*="11ty-demos.netlify.app"])::after {
        content: " (" attr(href) ")";
        font-size: 0.8em;
        color: #555;
    }
}

Notes

  • Hard drop-shadows (--shadow-hard) are set to none for print, but borders stay — a shadow is a screen-only affordance, while a border is still doing real work separating one block from another on a printed page.
  • break-inside: avoid on cards, code blocks, and images stops a browser from slicing one of them in half across a page break — a small detail, but the difference between “readable” and “a code block with the punchline on the next sheet.”
  • There’s no automated test for this. The honest way to check a print stylesheet is still Print Preview in a real browser, which is exactly what the Live Implementation above asks you to do on this page itself.