Content Best Practices
Master professional patterns, optimization techniques, accessibility guidelines, and common gotchas for all content components in PDF documents.
Learning Objectives
By the end of this article, you’ll be able to:
- Optimize images and graphics for PDFs
- Improve table performance
- Enhance accessibility
- Apply professional content patterns
- Troubleshoot common issues
- Build production-ready documents
Image Optimization
File Size Optimization
<!-- ❌ Unoptimized: 5MB original photo -->
<img src="./photos/product-original.jpg"
alt="Product"
style="width: 300pt;" />
<!-- ✅ Optimized: 150KB resized and compressed -->
<img src="./photos/product-optimized.jpg"
alt="Product"
style="width: 300pt;" />
Optimization Steps:
- Resize to target dimensions (e.g., 2× display size for quality)
- Compress appropriately for format
- Choose right format (JPEG for photos, PNG for graphics, SVG for logos)
Image Format Selection
| Use Case | Format | Reason |
|---|---|---|
| Photos | JPEG | Smaller file size, good quality |
| Logos | SVG or PNG | Sharp edges, scalable |
| Screenshots | PNG | Preserves text clarity |
| Charts | SVG | Scalable, small file size |
| Icons | SVG | Perfect scaling, tiny files |
Resolution Guidelines
<!-- For 300pt wide image in PDF: -->
<!-- ❌ Too low: 300px (1× DPI) -->
<img src="./image-300px.jpg" style="width: 300pt;" />
<!-- ✅ Good: 600px (2× DPI) -->
<img src="./image-600px.jpg" style="width: 300pt;" />
<!-- ⚠️ Overkill: 1200px (4× DPI) - larger file, minimal benefit -->
<img src="./image-1200px.jpg" style="width: 300pt;" />
Recommendation: 2× the display size at 96 DPI.
SVG Optimization
Simplify SVG Code
<!-- ❌ Exported SVG with unnecessary complexity -->
<svg viewBox="0 0 100 100">
<defs>
<clipPath id="clip0">...</clipPath>
<filter id="filter0">...</filter>
</defs>
<g transform="matrix(1.2, 0, 0, 1.2, 0, 0)">
<path d="M 1.234567 2.345678 L 3.456789..." fill="#3B82F6" />
<!-- Hundreds of unnecessary precision decimals -->
</g>
</svg>
<!-- ✅ Optimized SVG -->
<svg viewBox="0 0 100 100" width="100" height="100">
<circle cx="50" cy="50" r="40" fill="#3b82f6" />
</svg>
Optimization Tools:
- SVGO (CLI tool)
- SVGOMG (online tool)
- Manual simplification for simple graphics
Inline vs External
<!-- ✅ Inline for data binding and small graphics -->
<svg viewBox="0 0 100 100" width="50" height="50">
<rect width="100" height="" fill="#3b82f6" />
</svg>
<!-- ✅ External for complex, reusable graphics -->
<img src="./graphics/complex-diagram.svg"
alt="System Architecture"
style="width: 400pt;" />
Table Performance
Column Width Optimization
/* ❌ Auto layout - slow for large tables */
table {
table-layout: auto; /* Calculates based on content */
}
/* ✅ Fixed layout - fast */
table {
table-layout: fixed; /* Uses specified widths */
width: 100%;
}
th:nth-child(1) { width: 40%; }
th:nth-child(2) { width: 30%; }
th:nth-child(3) { width: 30%; }
Limit Table Complexity
<!-- ❌ Overly complex table -->
<table>
<tbody>
<!-- 10,000+ rows with complex styling -->
<!-- Heavy calculations in every cell -->
<!-- Multiple nested elements per cell -->
</tbody>
</table>
<!-- ✅ Optimized table -->
<table>
<tbody>
<!-- Reasonable row count (or paginated) -->
<!-- Simple cell content -->
<!-- Calculations outside loops when possible -->
</tbody>
</table>
Page Break Strategy
/* Control table pagination */
table {
page-break-inside: auto; /* Allow table to span pages */
}
thead {
display: table-header-group; /* Repeat headers */
}
tbody tr {
page-break-inside: avoid; /* Don't break rows */
}
/* For very large cells, allow breaks */
tbody tr.large-content {
page-break-inside: auto;
}
List Best Practices
Appropriate List Length
<!-- ❌ Too long - consider pagination or sectioning -->
<ul>
<!-- 500+ items -->
</ul>
<!-- ✅ Manageable length or grouped -->
<h2>Section A</h2>
<ul>
<!-- 10-20 items -->
</ul>
<h2>Section B</h2>
<ul>
<!-- 10-20 items -->
</ul>
Limit Nesting Depth
<!-- ❌ Too many levels -->
<ul>
<li>Level 1
<ul>
<li>Level 2
<ul>
<li>Level 3
<ul>
<li>Level 4</li> <!-- Too deep! -->
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<!-- ✅ 2-3 levels maximum -->
<ul>
<li>Level 1
<ul>
<li>Level 2</li>
<li>Level 2</li>
</ul>
</li>
</ul>
Accessibility
Alternative Text
<!-- ❌ Missing alt text -->
<img src="./chart.png" />
<!-- ❌ Useless alt text -->
<img src="./chart.png" alt="image" />
<!-- ✅ Descriptive alt text -->
<img src="./chart.png"
alt="Bar chart showing quarterly revenue growth from Q1 to Q4 2024" />
Table Headers
<!-- ❌ No proper headers -->
<table>
<tr>
<td><strong>Name</strong></td>
<td><strong>Age</strong></td>
</tr>
<tr>
<td>John</td>
<td>30</td>
</tr>
</table>
<!-- ✅ Proper semantic headers -->
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>30</td>
</tr>
</tbody>
</table>
Document Structure
<!-- ❌ Poor structure -->
<div style="font-size: 24pt; font-weight: bold;">Title</div>
<div style="font-size: 18pt; font-weight: bold;">Section</div>
<!-- ✅ Semantic structure -->
<h1>Title</h1>
<h2>Section</h2>
Professional Patterns
Pattern 1: Data Dashboard
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<title>Dashboard Pattern</title>
<style>
@page {
size: Letter landscape;
margin: 0.75in;
}
body {
font-family: Helvetica, Arial, sans-serif;
font-size: 11pt;
margin: 0;
}
/* ==============================================
METRICS GRID
============================================== */
.metrics {
display: table;
width: 100%;
margin-bottom: 30pt;
}
.metric-row {
display: table-row;
}
.metric-card {
display: table-cell;
width: 25%;
padding: 15pt;
text-align: center;
border: 1pt solid #e5e7eb;
border-radius: 5pt;
}
.metric-value {
font-size: 32pt;
font-weight: 700;
color: #2563eb;
}
.metric-label {
font-size: 10pt;
color: #666;
text-transform: uppercase;
}
/* ==============================================
CHART SECTION
============================================== */
.chart-container {
margin: 20pt 0;
text-align: center;
}
.chart-image {
width: 100%;
max-width: 600pt;
height: auto;
}
</style>
</head>
<body>
<!-- KPIs at top -->
<div class="metrics">
<div class="metric-row">
<div class="metric-card">
<div class="metric-value">$2.4M</div>
<div class="metric-label">Revenue</div>
</div>
<div class="metric-card">
<div class="metric-value">1,247</div>
<div class="metric-label">Customers</div>
</div>
<div class="metric-card">
<div class="metric-value">94%</div>
<div class="metric-label">Satisfaction</div>
</div>
<div class="metric-card">
<div class="metric-value">+18%</div>
<div class="metric-label">Growth</div>
</div>
</div>
</div>
<!-- Charts below -->
<div class="chart-container">
<img src="./charts/revenue-trend.svg"
alt="Revenue Trend Chart"
class="chart-image" />
</div>
</body>
</html>
Pattern 2: Product Catalog
<!-- Responsive grid with images and details -->
<div class="catalog-grid">
<div class="product-card">
<!-- Optimized product image -->
<img src=""
alt=""
style="width: 100%; height: 200pt; object-fit: cover;" />
<h3></h3>
<!-- Bulleted features -->
<ul>
<li></li>
</ul>
<p class="price">$</p>
</div>
</div>
Pattern 3: Report with Tables and Charts
<!-- Mixed content with optimal ordering -->
<h1>Annual Report</h1>
<!-- Executive summary first -->
<section class="summary">
<p>...</p>
</section>
<!-- Key chart -->
<img src="./charts/overview.svg" alt="Overview Chart" style="width: 100%;" />
<!-- Detailed data table -->
<table>
<!-- Large data table -->
</table>
<!-- Supporting charts -->
<img src="./charts/breakdown.svg" alt="Breakdown Chart" style="width: 100%;" />
Performance Optimization
Lazy Loading Considerations
<!-- For very large documents, consider splitting -->
<!-- Document 1: Main content -->
main-report.html
<!-- Document 2: Appendix with large tables -->
appendix.html
<!-- Combine during generation or provide as separate PDFs -->
Caching Strategy
<!-- Cache frequently used images -->
<!-- Load once, reference multiple times -->
<img src="./logos/company-logo.svg" alt="Logo" />
<!-- Logo appears on every page -->
<!-- Generator may cache this image -->
Resource Limits
Guidelines:
- Images: < 2MB each
- Total document: < 50MB for good performance
- Tables: < 1000 rows per table
- SVG: < 100KB per graphic
- Attachments: < 10MB each
Troubleshooting Guide
Images Not Showing
Possible Causes:
- Incorrect file path
- File doesn’t exist
- Unsupported format
- Corrupted image file
Solutions:
- Verify file exists at specified path
- Use supported formats (PNG, JPEG, SVG)
- Test with simple image first
- Check file permissions
Table Layout Issues
Possible Causes:
- Missing table-layout property
- No column widths specified
- Content too wide for columns
- border-collapse not set
Solutions:
- Set
table-layout: fixed - Specify column widths
- Use
overflow-wrap: break-wordfor long text - Always use
border-collapse: collapse
SVG Not Rendering
Possible Causes:
- Missing viewBox
- No width/height specified
- Complex SVG unsupported
- Incorrect SVG syntax
Solutions:
- Always include viewBox
- Specify width and height
- Simplify SVG code
- Validate SVG syntax
Page Break Problems
Possible Causes:
- Content forced together
- No break control specified
- Container prevents breaks
Solutions:
- Use
page-break-inside: avoidon elements - Allow breaks in tbody:
page-break-inside: auto - Test with real data volumes
Content Checklist
Images
- Optimized file sizes (< 500KB each)
- Appropriate format chosen
- 2× resolution for quality
- Alt text provided
- Paths verified
SVG
- viewBox defined
- Width and height specified
- Code optimized/simplified
- Tested in PDF
Lists
- 2-3 nesting levels maximum
- Proper spacing between items
- Semantic HTML used
- Data binding tested
Tables
- table-layout: fixed
- Column widths defined
- border-collapse: collapse
- Headers use <thead>
- Page breaks controlled
- Calculations validated
General
- Tested with real data
- Performance acceptable
- Accessible structure
- PDF renders correctly
Best Practices Summary
- Optimize Images - Resize and compress before embedding
- Use SVG for Scalability - Logos, icons, charts
- Fixed Table Layout - Performance and predictability
- Limit Complexity - Simple is faster and more reliable
- Semantic HTML - Proper heading structure
- Test Thoroughly - Real data, various sizes
- Control Page Breaks - Prevent awkward splits
- Provide Alt Text - Accessibility and context
- Cache Resources - Reuse images and graphics
- Monitor File Sizes - Keep documents manageable
Performance Targets
| Metric | Target | Maximum |
|---|---|---|
| Page generation time | < 1s per page | < 5s per page |
| Image size | < 500KB | < 2MB |
| Total PDF size | < 10MB | < 50MB |
| Table rows | < 500 per table | < 1000 per table |
| SVG complexity | < 50KB | < 100KB |
Next Steps
You’ve completed the Content Components series! Continue your journey:
- Configuration - Document settings and optimization
- Practical Applications - Real-world document examples
- Review previous series - Reinforce learning
Continue learning → Configuration Series