javascript

HTML a PDF con JavaScript

En este post te mostraré cómo exportar una página web a PDF a través de un botón, enlace o cualquier cosa soportada por JavaScript. A este proceso también se le conoce como convertir HTML a PDF.

Convertir HTML a PDF con JavaScript

Es decir, convertir web a PDF usando programación con JavaScript y las siguientes librerías:

De hecho, html2pdf usa las dos librerías anteriores. Aunque parece complejo, verás que no lo es realmente. Con esta librería podemos crear un PDF muy parecido a la página web, incluyendo imágenes.

Incluyendo librería

Tenemos dos opciones. Incluir el “bundle” que ya tiene las otras dos dependencias, o cargar las 3 dependencias por separado. Recomiendo el bundle, mismo que podemos conseguir aquí.

Nota: tal vez con el paso del tiempo, se cambie la manera de incluir la librería. Aquí te dejo el repositorio del proyecto por si algo ha cambiado.

En mi caso la he descargado, e incluido así:

<!-- El script de la librería-->
<script src="html2pdf.bundle.min.js"></script>

Generando PDF

Al incluir la librería tendremos a la función html2pdf. Aquí dejo el código y lo explico a continuación.

const $elementoParaConvertir = document.body; // <-- Aquí puedes elegir cualquier elemento del DOM
html2pdf()
    .set({
        margin: 1,
        filename: 'documento.pdf',
        image: {
            type: 'jpeg',
            quality: 0.98
        },
        html2canvas: {
            scale: 3, // A mayor escala, mejores gráficos, pero más peso
            letterRendering: true,
        },
        jsPDF: {
            unit: "in",
            format: "a3",
            orientation: 'portrait' // landscape o portrait
        }
    })
    .from($elementoParaConvertir)
    .save()
    .catch(err => console.log(err));
const $elementoParaConvertir = document.body; // <-- Aquí puedes elegir cualquier elemento del DOM
html2pdf()
    .set({
        margin: 1,
        filename: 'documento.pdf',
        image: {
            type: 'jpeg',
            quality: 0.98
        },
        html2canvas: {
            scale: 3, // A mayor escala, mejores gráficos, pero más peso
            letterRendering: true,
        },
        jsPDF: {
            unit: "in",
            format: "a3",
            orientation: 'portrait' // landscape o portrait
        }
    })
    .from($elementoParaConvertir)
    .save()
    .catch(err => console.log(err));

 

En la línea 1 declaramos el elemento del DOM que se tomará para crear el PDF. Si quieres que se le tome a todo el cuerpo, envía directamente a document.body. También puedes enviar un div, párrafo, etcétera (puedes usar querySelector).

Después establecemos las opciones con set. Por ejemplo, establecemos el nombre del PDF generado con JavaScript. También enviamos opciones propias de las librerías html2canvas y jsPDF.

Una cosa importante es scale dentro de html2canvas, que indica la escala. Entre mayor sea, se notará una mejor calidad, pero será un PDF más pesado o en ocasiones contendrá errores.

En el caso de jsPDF estamos indicando que el formato sea a3. Puede ser a4, a1, a2, etcétera. Si quieres una buena página para las medidas yo consulté papersizes.org

La orientación se define con orientation. Puede ser portrait que es de manera vertical, o landscape de manera horizontal.

Al invocar al método save se devuelve una promesa que se resolverá cuando el PDF sea descargado (Se le preguntará al usuario en dónde guardarlo, sugiriendo el nombre especificado en filename. Recuerda que como es una promesa podemos manejar el catch, then y finally.

Ejemplo de conversión HTML a PDF con JavaScript

Cabe mencionar que esto es compatible con la mayoría de navegadores actuales y decentes. Por favor, usuarios de Internet Explorer, ya es 2020, es hora de actualizar los navegadores.

Como sea, aquí dejo un ejemplo completo y funcional. Tenemos el código HTML. Recuerda que este código puede ser HTML puro, ser preprocesado por PHP u otro lenguaje, etcétera:

<!--

  ____          _____               _ _           _       
 |  _ \        |  __ \             (_) |         | |      
 | |_) |_   _  | |__) |_ _ _ __ _____| |__  _   _| |_ ___ 
 |  _ <| | | | |  ___/ _` | '__|_  / | '_ \| | | | __/ _ \
 | |_) | |_| | | |  | (_| | |   / /| | |_) | |_| | ||  __/
 |____/ \__, | |_|   \__,_|_|  /___|_|_.__/ \__, |\__\___|
         __/ |                               __/ |        
        |___/                               |___/         
    
____________________________________
/ Si necesitas ayuda, contáctame en \
\ https://parzibyte.me               /
 ------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
Creado por Parzibyte (https://parzibyte.me). Este encabezado debe mantenerse intacto,
excepto si este es un proyecto de un estudiante.
-->
<!DOCTYPE html>
<html lang="es">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Convertir HTML a PDF</title>
    <!-- El script de la librería-->
    <script src="html2pdf.bundle.min.js"></script>
    <!--Nuestro script, que se encarga de crear el PDF usando la librería-->
    <script src="script.js"></script>
    <!-- Algunos estilos -->
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <h1>Mi página web</h1>
    <strong>Presiona el siguiente botón para crear un PDF:</strong>
    <button id="btnCrearPdf">Click aquí</button>
    <h5>Estamos probando la creación de un PDF desde HTML usando JavaScript</h5>
    <a href="//parzibyte.me/blog">Creado por Parzibyte</a>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Voluptas dignissimos laudantium laboriosam asperiores?
        Doloremque fuga quia odit quas. Obcaecati aliquam suscipit molestias? Architecto nisi blanditiis maxime beatae
        temporibus assumenda ex.</p>
    <img src="lake-5534341_1280.jpg" alt="Una imagen">
    <h1>Otro encabezado</h1>
    <table>
        <thead>
            <tr>
                <th>Nombre</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Luis Cabrera Benito</td>
            </tr>
        </tbody>
    </table>
</body>

</html>

Se puede observar que estamos importando el script de la librería, y un script propio que hará el funcionamiento. Además, tenemos un botón que al ser presionado va a generar el documento PDF. Ahora en la parte de programación con JavaScript:

/*

  ____          _____               _ _           _       
 |  _ \        |  __ \             (_) |         | |      
 | |_) |_   _  | |__) |_ _ _ __ _____| |__  _   _| |_ ___ 
 |  _ <| | | | |  ___/ _` | '__|_  / | '_ \| | | | __/ _ \
 | |_) | |_| | | |  | (_| | |   / /| | |_) | |_| | ||  __/
 |____/ \__, | |_|   \__,_|_|  /___|_|_.__/ \__, |\__\___|
         __/ |                               __/ |        
        |___/                               |___/         
    
____________________________________
/ Si necesitas ayuda, contáctame en \
\ https://parzibyte.me               /
 ------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
Creado por Parzibyte (https://parzibyte.me). Este encabezado debe mantenerse intacto,
excepto si este es un proyecto de un estudiante.
*/document.addEventListener("DOMContentLoaded", () => {
    // Escuchamos el click del botón
    const $boton = document.querySelector("#btnCrearPdf");
    $boton.addEventListener("click", () => {
        const $elementoParaConvertir = document.body; // <-- Aquí puedes elegir cualquier elemento del DOM
        html2pdf()
            .set({
                margin: 1,
                filename: 'documento.pdf',
                image: {
                    type: 'jpeg',
                    quality: 0.98
                },
                html2canvas: {
                    scale: 3, // A mayor escala, mejores gráficos, pero más peso
                    letterRendering: true,
                },
                jsPDF: {
                    unit: "in",
                    format: "a3",
                    orientation: 'portrait' // landscape o portrait
                }
            })
            .from($elementoParaConvertir)
            .save()
            .catch(err => console.log(err));
    });
});

Puedes ver el código completo en este enlace. También puedes acceder a la demostración aquí. Finalmente, te dejo un vídeo en YouTube con la explicación adicional:

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.
parzibyte

Programador freelancer listo para trabajar contigo. Aplicaciones web, móviles y de escritorio. PHP, Java, Go, Python, JavaScript, Kotlin y más :) https://parzibyte.me/blog/software-creado-por-parzibyte/

Ver comentarios

  • excelente video me encanto mucho.. esta excelentemente bien explicado
    oyes solo tengo una duda como puedo hacer para que me muestre la ventana de guardar como al darle clic en mi botón de convertir a pdf
    solo es eso por el momento creo
    te agradecería mucho y de antemano te envió un saludo

  • Hola gracias por tu video! Me funciona pero cuando pongo una imagen no funciona más, no se porque si copie la los js exactamente igual. Me justaría tener ayuda. Gracias!

  • Gracias por tu aporte, no soy programador, solo entusiasta y autodidacta en codigos, me funciona super bien la implementacion, lo que paso al PDF es solo un div, y no el body completo, solo quisiera saber como puedo hacer que el div, agarre toda la pagina del pdf, lo hago landscape de a4, pero no puedo hacer que el div de 700px, tome toda la pagina del PDF, me podrias asesorar? nuevamente gracias por el aporte!! saludos desde Paraguay!

  • Hola, gracias por compartir tu conocimiento, implementé el procedimiento pero me sale este mensaje en la consola:

    html2pdf.bundle.min.js:2 Uncaught SyntaxError: Unexpected token '<'
    script.js:2 Uncaught SyntaxError: Unexpected token '<'

    Podrías orientarme un poco al respecto?

    Gracias

  • Hola.. gracias por este aporte esta muy bueno!!! Tengo una duda adicional... como hacer cuando el documento tiene mas de una página? Me pasa que la segunda página queda muy pegada al inicio es como que no respeta un margin. Muchas gracias!

  • Hola, muchas gracias por compartir, me podrías ayudar con un problema que me surge al exportar un pdf un textarea de mi pagina me sale todo el texto encimado, el texto se despliega bien en el navegador, pero el pdf ya no, espero me puedas ayudar a encontrar info sobre este problema, de antemano gracias, saludos.

  • cordial saludo, muy buen aporte, cuando son pocas paginas me sale desfazado, grande, fuera de borde el contenido y cuando son muchas paginas no sale contenido. me ayuda por favor.

  • Hola! muy bueno el tutorial, quería saber si hay alguna forma de subir ese archivo pdf al servidor directamente sin que se descargue localmente, si no que una vez se genere el pdf se guarde en el servidor

  • Muchas gracias por tu publicación, me ayudó bastante con la generación de reportes despues de varios dolores de cabeza intentando usar html2canvas y jspdf directamente, los cuales trabajan pesimo con CSS.

    De verdad muchisimas gracias, te ganaste el cielo

    • Me agrada escuchar que mi post le haya ayudado. Le invito a suscribirse al blog y a seguirme en mis redes sociales
      Saludos :)

Entradas recientes

Imprimir ñ en impresora térmica

En este post te enseñaré a imprimir la letra ñ en una impresora térmica. Voy…

2 días hace

Tramitar acta de nacimiento en línea de manera instantánea

En este post te quiero compartir mi experiencia tramitando un acta de nacimiento de México…

3 días hace

Creador de credenciales web – Aplicación gratuita

Hoy te voy a presentar un creador de credenciales que acabo de programar y que…

2 semanas hace

Desplegar PWA creada con Vue 3, Vite y SQLite3 en Apache

Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…

3 semanas hace

Arquitectura para wasm con Go, Vue 3, Pinia y Vite

En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…

3 semanas hace

Vue 3 y Vite: crear PWA (Progressive Web App)

En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…

3 semanas hace

Esta web usa cookies.