DEV Community

Raheel Shan
Raheel Shan

Posted on

Say Goodbye to Media Queries: Print Fully Styled HTML Content

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)