Skip to content
Back to Blog
February 20, 2025Tom Silas Helmke15 min readCSS Guide

CSS Tips for Perfect PDF Output

The screen and the printed page are fundamentally different mediums. This comprehensive guide covers everything you need to know about styling HTML for flawless PDF conversion—from basic print stylesheets to advanced page break control and troubleshooting.

Mastering Page Breaks

Page break control is perhaps the most important aspect of PDF styling. Nothing ruins a document faster than a heading orphaned at the bottom of a page or a table split awkwardly across two pages.

CSS provides three properties for page break control, each with modern and legacy syntax:

  • page-break-before / break-before: Controls whether a page break occurs before an element
  • page-break-after / break-after: Controls page breaks after an element
  • page-break-inside / break-inside: Controls whether an element can be split across pages
Page Break Control
/* Force page break before element */
.chapter-start,
.new-section {
  page-break-before: always;
  break-before: page; /* Modern syntax */
}

/* Force page break after element */
.end-of-section {
  page-break-after: always;
  break-after: page;
}

/* Prevent element from being split */
.keep-together,
table,
figure,
blockquote,
.testimonial {
  page-break-inside: avoid;
  break-inside: avoid;
}

/* Keep headings with following content */
h1, h2, h3, h4, h5, h6 {
  page-break-after: avoid;
  break-after: avoid;
}

/* Orphan and widow control */
p {
  orphans: 3; /* Min lines at bottom of page */
  widows: 3;  /* Min lines at top of page */
}

Orphans and Widows

In typography, an "orphan" is a single line of a paragraph left alone at the bottom of a page, while a "widow" is a single line at the top of a page. Both are considered poor typography. The orphans and widows properties set the minimum number of lines that must appear together.

Browser Compatibility Note

Use both the legacy (page-break-*) and modern (break-*) syntax for maximum compatibility. Chrome, Safari, and html2pdf.js work best with the legacy syntax, while Firefox prefers the modern version.

Backgrounds and Colors

By default, browsers do not print background colors and images. This is a deliberate choice to save ink. However, for documents where backgrounds are essential (like invoices with branded headers), you need to explicitly enable them.

Background Printing
@media print {
  /* Force background colors to print */
  * {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
    color-adjust: exact !important;
  }

  /* Alternative: Use borders instead of backgrounds */
  .highlight-box {
    /* Instead of: background: #fef3c7; */
    border: 2px solid #f59e0b;
    padding: 1rem;
  }

  /* Header with guaranteed visibility */
  .header {
    background: #1e293b !important;
    color: white !important;
    -webkit-print-color-adjust: exact !important;
  }
}

When Backgrounds Won't Print

Even with print-color-adjust: exact, users can override this in their browser's print settings. For mission-critical elements, consider alternatives:

  • Use borders instead of background colors for highlighting
  • Use inline SVG for colored shapes that must appear
  • Consider dark text on white backgrounds as the default

Typography and Web Fonts

Font rendering in PDFs can be tricky. Web fonts loaded from Google Fonts or Adobe Fonts must be fully downloaded before the PDF is generated, or you'll see fallback fonts.

Print Typography
/* Define print-safe font stack */
body {
  font-family: 
    'Segoe UI',      /* Windows */
    'SF Pro Text',   /* macOS */
    'Roboto',        /* Android/Chrome OS */
    -apple-system,   /* Safari fallback */
    Arial,           /* Universal fallback */
    sans-serif;
}

/* Ensure web fonts are loaded before print */
@font-face {
  font-family: 'CustomFont';
  src: url('/fonts/custom.woff2') format('woff2');
  font-display: block; /* Wait for font to load */
}

/* Print-specific typography */
@media print {
  body {
    font-size: 12pt;
    line-height: 1.5;
  }

  h1 { font-size: 24pt; }
  h2 { font-size: 18pt; }
  h3 { font-size: 14pt; }

  /* Avoid thin fonts that don't print well */
  * {
    font-weight: normal;
  }
  
  strong, b, h1, h2, h3 {
    font-weight: bold;
  }
}

Font Size in Print

On screen, we typically use pixels or relative units (rem, em). For print, points (pt) are the traditional unit. The standard conversion is 1pt = 1/72 inch. Common sizes:

  • Body text: 10pt - 12pt
  • Headings: 14pt - 24pt
  • Captions and footnotes: 8pt - 9pt

Safe System Fonts

These fonts are available on virtually all systems and don't require loading:

  • • Sans-serif: Arial, Helvetica, Verdana, Trebuchet MS
  • • Serif: Times New Roman, Georgia, Palatino
  • • Monospace: Courier New, Consolas, Monaco

Layout Strategies

Modern CSS layouts with Flexbox and Grid work well for PDF generation, but you may need adjustments for the fixed dimensions of paper. A4 paper is 210mm × 297mm, and with typical 2cm margins, your content area is approximately 170mm × 257mm.

Print Layout
/* A4-optimized container */
.print-container {
  max-width: 210mm;
  padding: 20mm;
  margin: 0 auto;
  box-sizing: border-box;
}

/* Content width for comfortable reading */
.content {
  max-width: 170mm; /* 210mm - 40mm margins */
}

@media print {
  /* Remove max-width constraints */
  .print-container,
  .content {
    max-width: none;
    width: 100%;
    padding: 0;
    margin: 0;
  }

  /* Convert flex/grid to simpler layouts if needed */
  .complex-grid {
    display: block;
  }

  .complex-grid > * {
    width: 100%;
    margin-bottom: 1rem;
  }
}

Dealing with Sidebars

Two-column layouts that work on screen often don't translate well to print. Consider:

  • Hiding sidebars entirely for print
  • Moving sidebar content to the end of the document
  • Converting to a single-column layout

Images and Media

Images require special attention for PDF output. Lazy-loaded images may not be loaded when the PDF is generated, and high-resolution images can make PDFs enormous.

Image Handling
/* Ensure images don't overflow pages */
img {
  max-width: 100%;
  height: auto;
  page-break-inside: avoid;
}

/* Handle lazy-loaded images */
img[loading="lazy"] {
  loading: eager; /* Force immediate load for print */
}

@media print {
  /* Ensure images print */
  img {
    display: block !important;
    visibility: visible !important;
    max-width: 100% !important;
    
    /* Prevent quality loss */
    image-rendering: -webkit-optimize-contrast;
    image-rendering: crisp-edges;
  }

  /* Hide decorative images */
  .decorative-bg,
  .parallax-image {
    display: none !important;
  }

  /* Ensure alt text shows if image fails */
  img::after {
    content: attr(alt);
    font-style: italic;
    color: #666;
  }
}

Image Resolution

For print-quality output, images should be at least 300 DPI (dots per inch). On screen, we typically see 72-96 DPI. If your PDF will be printed, ensure images are high enough resolution, or they'll appear pixelated.

For web-to-PDF conversion where printing isn't the goal, standard screen resolution is fine. The html2pdf.js scale option effectively increases rendering resolution.

Handling Links

On screen, links are obvious—they're blue and clickable. On paper, you need to make URLs visible so readers can type them manually. CSS can automatically append URLs after link text.

Link Visibility
@media print {
  /* Make links visible but not distracting */
  a {
    color: #000 !important;
    text-decoration: underline;
  }

  /* Show URL after external links */
  a[href^="http"]:after,
  a[href^="https"]:after {
    content: " (" attr(href) ")";
    font-size: 0.8em;
    color: #666;
    word-break: break-all;
  }

  /* Don't show URL for internal links */
  a[href^="#"]:after,
  a[href^="/"]:after {
    content: none;
  }

  /* Don't show URL for email links */
  a[href^="mailto"]:after {
    content: " (" attr(href) ")";
  }

  /* Limit very long URLs */
  a:after {
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    display: inline-block;
    vertical-align: bottom;
  }
}

Tables for Print

Tables present unique challenges for PDF generation. Long tables spanning multiple pages need repeating headers, and complex layouts may need simplification.

Print-Optimized Tables
/* Print-optimized tables */
table {
  width: 100%;
  border-collapse: collapse;
  page-break-inside: auto;
}

tr {
  page-break-inside: avoid;
  page-break-after: auto;
}

thead {
  display: table-header-group; /* Repeat header on each page */
}

tfoot {
  display: table-footer-group;
}

th, td {
  border: 1px solid #ddd;
  padding: 8px;
  text-align: left;
}

@media print {
  th {
    background: #f3f4f6 !important;
    -webkit-print-color-adjust: exact;
  }

  /* Zebra striping */
  tr:nth-child(even) {
    background: #f9fafb !important;
    -webkit-print-color-adjust: exact;
  }

  /* Ensure table fits page width */
  table {
    font-size: 10pt;
  }
}

Table Header Repetition

The display: table-header-group property on thead tells the browser to repeat the header row on each page. This is essential for data tables that span multiple pages.

Complete Print Stylesheet Template

Here's a comprehensive print stylesheet you can use as a starting point for any project. It incorporates all the techniques discussed above.

Complete Print Stylesheet
/* Complete Print Stylesheet Template */
@media print {
  /* ===== RESET & BASICS ===== */
  * {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }

  body {
    background: white !important;
    color: black !important;
    font-family: 'Segoe UI', Arial, sans-serif;
    font-size: 12pt;
    line-height: 1.6;
  }

  /* ===== PAGE SETUP ===== */
  @page {
    size: A4 portrait;
    margin: 2cm;
  }

  @page :first {
    margin-top: 1cm; /* Smaller top margin for first page */
  }

  /* ===== HIDE ELEMENTS ===== */
  nav, footer, aside,
  .no-print, .sidebar,
  button, .modal,
  .cookie-banner,
  .social-share,
  .comments-section {
    display: none !important;
  }

  /* ===== PAGE BREAKS ===== */
  h1, h2, h3 {
    page-break-after: avoid;
  }

  h1 {
    page-break-before: always;
  }

  h1:first-of-type {
    page-break-before: avoid;
  }

  table, figure, img, blockquote {
    page-break-inside: avoid;
  }

  p {
    orphans: 3;
    widows: 3;
  }

  /* ===== TYPOGRAPHY ===== */
  h1 { font-size: 24pt; margin-bottom: 12pt; }
  h2 { font-size: 18pt; margin-top: 18pt; }
  h3 { font-size: 14pt; }

  /* ===== LINKS ===== */
  a {
    color: black !important;
    text-decoration: underline;
  }

  a[href^="http"]:after {
    content: " [" attr(href) "]";
    font-size: 0.8em;
    color: #666;
  }

  /* ===== IMAGES ===== */
  img {
    max-width: 100% !important;
    page-break-inside: avoid;
  }

  /* ===== TABLES ===== */
  table {
    width: 100%;
    border-collapse: collapse;
    font-size: 10pt;
  }

  th, td {
    border: 1px solid #ccc;
    padding: 6pt;
  }

  thead {
    display: table-header-group;
  }

  th {
    background: #f0f0f0 !important;
  }
}

Troubleshooting Common Issues

Problem: Content is cut off

Solution: Check that your container doesn't have a fixed height. Use min-height instead of height. Ensure overflowis set to visible, not hidden.

Problem: Backgrounds disappear

Solution: Add -webkit-print-color-adjust: exact andprint-color-adjust: exact to the elements. Remember that users can still override this in browser settings.

Problem: Fonts look different

Solution: Ensure web fonts are fully loaded before generating the PDF. Use document.fonts.ready in JavaScript. Provide fallback fonts that closely match your web fonts.

Problem: Page breaks in wrong places

Solution: Use both legacy and modern syntax for page-break properties. Add break-inside: avoid to elements that shouldn't be split. Check that parent elements don't have conflicting break properties.

Conclusion

Creating CSS for PDF output requires a different mindset than screen design. The key principles to remember:

  • Use @media print to create separate print styles
  • Control page breaks explicitly with CSS properties
  • Force background printing when needed with print-color-adjust
  • Use points (pt) for font sizes in print
  • Ensure images and fonts are loaded before PDF generation
  • Hide interactive elements that don't make sense on paper

With these techniques, you can create documents that look professional whether viewed on screen or converted to PDF.

Test Your CSS

Try our free HTML to PDF converter to see your print styles in action.

Convert HTML to PDF

Related Articles