In my previous post, I showed how to ditch media queries entirely and print beautifully styled HTML content using an image-based trick. It simplified printing by converting the content into an image and setting it into a hidden image element to be printed on a button click.
Take a look at how to print HTML content without Media Queries.

That same technique can be reused with a slight twist — this time, to generate a downloadable PDF.
No backend. No media queries. No complex rendering pipeline.
Setup
<!-- HTML structure -->
<body>
<div id="root-container">
<!-- html content -->
<div id="content-to-print">
<!-- add your content here -->
</div>
<!-- other content -->
</div>
<!-- empty image element to hold converted image from DOM -->
<img src="" alt="" id="printed-image" />
</body>
Then in JavaScript include files.
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.4.0/jspdf.umd.min.js"></script>
And here is a Javascript function to convert HTML to PDF.
// function to be called on button click
function printImage() {
generateImage()
}
// logic to convert content to image
function generateImage() {
const style = document.createElement('style');
document.head.appendChild(style);
style.sheet?.insertRule('body > div:last-child img { display: inline-block; }');
html2canvas(document.getElementById('content-to-print'), {
useCORS: true, // To handle cross-origin images
scale: 3,
backgroundColor: '#FFF', // Do not force a background color in html2canvas
scrollX: 0,
scrollY: 0,
windowWidth: document.documentElement.scrollWidth,
windowHeight: document.documentElement.scrollHeight
}).then(function(canvas) {
const {
jsPDF
} = window.jspdf;
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF('p', 'mm', 'a4'); // 'p' for portrait, 'mm' for millimeters, 'a4' for A4 size
const imgWidth = 210; // A4 width in mm (210mm)
const pageHeight = 285; // A4 height in mm (297mm)
const imgHeight = canvas.height * imgWidth / canvas.width;
const heightLeft = imgHeight;
let position = -7;
// Add a white background to the PDF page
pdf.setFillColor(255, 255, 255); // RGB for white
pdf.rect(0, 0, imgWidth, pageHeight, 'F'); // Fill the background
pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
pdf.save('sample-file.pdf');
});
}
And finally, call the function on button click.
<div style="text-align: center; margin-top: 20px;">
<h2>Download HTML as PDF</h2>
<button
id="print-without-media"
onclick="printImage()"
style="padding: 10px 20px; background-color: #007bff; color: white; border: none; border-radius: 5px; margin: 5px; cursor: pointer;"
>
Download PDF
</button>
</div>
What’s Happening Here?
- HTML2Canvas grabs a pixel-perfect snapshot of your HTML.
- jsPDF takes that image and turns it into a downloadable PDF.
- One button click, one function call.
Why This Approach?
- You don’t need to struggle with PDF layout APIs.
- It respects your existing CSS styles (including fonts and spacing).
- No server-side rendering.
- You can still apply the same technique for printing, emailing, or previewing content.
When to Use This
- Invoices
- Certificates
- Reports
- Styled documentation
If you’re after simplicity, this method is enough in 90% of the cases. And if you already followed the trick I shared in the last post, this is basically the same idea, just with a download instead of print.
A Quick Note on File Size
Keep in mind, if your content is large or has many images, the resulting PDF could be several MBs in size. It’s something to consider if you’re working with long documents or detailed graphics.
Demo
If you found this post helpful, consider supporting my work — it means a lot.
