Printing HTML content with all styles intact has always been a challenging task for me. Media queries often complicate things when trying to achieve a clean and consistent print layout. However, I recently discovered a simple solution that bypasses the need for media queries altogether. Here’s how I did it.
The Solution: Using jsPDF to Print HTML as an Image
I used jsPDF, a JavaScript library, to convert HTML content into an image. This image is then set into a hidden element, which is displayed only during print. The idea is straightforward:
The HTML Structure
The HTML body has two main elements:
- A containing the main content with id root-container.
- A hidden
<img>
element with id printed-image outside of root-container where the image generated by jsPDF will be stored.
<body>
<div id="root-container">
<!-- html content -->
<div id="content-to-print"></div>
<!-- other content -->
</div>
<img src="" alt="" id="printed-image" />
</body>
Convert Content to Image
- Extract the HTML content you want to print and use jsPDF to convert it into an image.
- Save the generated image into the hidden
<img>
element (#printed-image).
// generate image on document ready to be saved in image tag
$(document).ready(function() {
generateImage()
})
// function to be called on button click
function printImage() {
window.print();
}
// 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);
$('#printed-image').prop('src', imgData)
});
}
CSS for Print
Add print-specific styles to hide the main content and display only the generated image when the print button is pressed.
/* Default styles */
#printed-image {
display: none;
}
/* Print-specific styles */
@media print {
#root-container {
display: none !important;
}
#printed-image {
display: block !important; /* Force image to display only during print */
margin: auto; /* Optional: center the image */
max-width: 100%; /* Ensure image fits the page */
}
}
Final Workflow
- When the document is ready html content will be converted to image
- This image is placed inside the hidden
<img>
element. - During printing, the main content (#root-container) is hidden, and the image (#printed-image) is displayed.
Why This Approach Works
By converting the HTML content into an image
- Media Queries Become Obsolete: Styles are baked into the image, so there’s no need to tweak styles for different screen sizes or layouts.
- Consistent Print Output: The image ensures that the print result matches what you see on the screen, regardless of the printer or browser quirks.
Top comments (0)