Generating a pdf that preserves styling of the HTML page with jsPDF

20,990

I ended up getting this to work by using html2canvas along with jsPDF.

My button that hides itself from pdf with an html2canvas option:

<div data-html2canvas-ignore="true">
    <button id="pdf-new"><a href="javascript:demoFromHTML()" class="button" style="color: black;">Generate PDF</a></button>
</div>

And the script for the bottom of the html page

<script>
    function demoFromHTML() {
        var pdf = new jsPDF('p', 'pt', 'letter');
        var options = {
            background: '#fff' //background is transparent if you don't set it, which turns it black for some reason.
        };
        pdf.addHTML($('#content')[0], options, function () {
                pdf.save('Test.pdf');
        });
    }
</script>

Also in html2canvas.js I changed:

_html2canvas.Util.isTransparent = function(backgroundColor) {
  return (backgroundColor === "transparent" || backgroundColor === "rgba(0, 0, 0, 0)");
};

to this, in order to avoid that transparent-to-black background

_html2canvas.Util.isTransparent = function(backgroundColor) {
  return (backgroundColor === "transparent" || backgroundColor === "rgba(0, 0, 0, 0)" || backgroundColor === undefined);
};

Hope that helps someone!

Share:
20,990
Virge Assault
Author by

Virge Assault

Updated on December 03, 2020

Comments

  • Virge Assault
    Virge Assault over 3 years

    I'm trying to create a button that will start the automatic download of a PDF of the page as it looks with the sass styling. However, everything I try ends up with the styling messed up.

    Here is the page (this is a testing site with several different content types)

    http://gobrandgotests.wpengine.com/preview-pdf/

    But the PDF comes out looking like this:

    enter image description here

    I'm pulling jspdf.debug.js and have the following HTML button+script in my page:

    <div id="bypass"> <!-- keeps button from showing in PDF -->
        <button id="pdf-new" style="margin: 50px;"><a href="javascript:demoFromHTML()" class="button" style="color: black;">Generate PDF</a></button>
    </div>
    
    <script>
        function demoFromHTML() {
            var pdf = new jsPDF('p', 'pt', 'letter');
            // source can be HTML-formatted string, or a reference
            // to an actual DOM element from which the text will be scraped.
            source = $('#content')[0];
    
            // we support special element handlers. Register them with jQuery-style 
            // ID selector for either ID or node name. ("#iAmID", "div", "span" etc.)
            // There is no support for any other type of selectors 
            // (class, of compound) at this time.
            specialElementHandlers = {
                // element with id of "bypass" - jQuery style selector
                '#bypass': function (element, renderer) {
                    // true = "handled elsewhere, bypass text extraction"
                    return true
                }
            };
            margins = {
                top: 80,
                bottom: 60,
                left: 40,
                width: 522
            };
            // all coords and widths are in jsPDF instance's declared units
            // 'inches' in this case
            pdf.fromHTML(
            source, // HTML string or DOM elem ref.
            margins.left, // x coord
            margins.top, { // y coord
                'width': margins.width, // max width of content on PDF
                'elementHandlers': specialElementHandlers
            },
    
            function (dispose) {
                // dispose: object with X, Y of the last line add to the PDF 
                //          this allow the insertion of new lines after html
                pdf.save('Test.pdf');
            }, margins);
        }
    </script>
    

    How can I make the styling stay consistent from the html to the pdf?