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)