Add CSS to Puppeteer PDF

Hey developers! In this article, we will see how to add CSS in PDF using Puppeteer. In the previous article, we have already seen how to convert HTML to PDF using Puppeteer. This will be a continuation of where we stopped last time. We will see various ways to add CSS in PDF converted from HTML. We have used Puppeteer for the conversion of HTML to PDF and also to add CSS in page

The GitHub repo is already updated, and you can find the link at the bottom.

Table of Content

  1. Insert Logo in Header for PDF Using Puppeteer
  2. How to Add CSS to HTML File Using Puppeteer
  3. Add External CSS for PDF Using Puppeteer
  4. How to add Bootstrap CSS in PDF Using Puppeteer
  5. How to Resolve the Overlapping Header Issue in Puppeteer
  6. Conclusion

NOTE: This is a continuation of the previous task. So, make sure to follow this article to catch up. Or clone this GitHub Repository. 

Add CSS HTML: Insert Logo in Header for PDF Using Puppeteer

We are going to perform additional tasks on an already working project. With this in mind, let’s create a new route so that our previous work remains untouched. So first add a new route by adding the following line of code in the “index.js” file.  

				
					app.post("/pdf-with-css", service.generate_pdf_with_css); 
				
			

Similarly, we going to create a new service function named “generate_pdf_with_css” in our NodeJS project.

Hence, add the following function in the “service.js”. This will apply header CSS in pdf for every page and will add the logo to your generated PDF.  

				
					exports.generate_pdf_with_css = async (req, res) => {  
  const browser = await puppeteer.launch({ headless: true }); 
  const page = await browser.newPage(); 
  const logo_url = "https://programatically.com/file/2021/10/Nginx-Docker-BG.webp"; 
  
  // FETCHING LOGO FROM URL AND CONVERTING INTO BASE64 
  var logo = await fetch(logo_url) 
    .then((response) => response.buffer()) 
    .then((buffer) => buffer.toString("base64")) 
    .catch(console.error); 
  
  //  ADDING CSS TO HTML BODY CONTENT 
  const html = await `${fs.readFileSync(`./dummy.html`, "utf8")}`; 
  await page.setContent(html, { waitUntil: "domcontentloaded"}); 
  
  const pdf = await page.pdf({ 
    format: "A4", 
    printBackground: false, 
    preferCSSPageSize: true, 
    displayHeaderFooter: true, 
  
    headerTemplate: `<div class="header"><img decoding="async" width="100" src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20100%200'%3E%3C/svg%3E" alt="company_logo" data-lazy-src="data:image/png;base64, ${logo}"><noscript><img decoding="async" width="100" src="data:image/png;base64, ${logo}" alt="company_logo"></noscript></div> `, 
    footerTemplate: '<footer><h5>Page <span class="pageNumber"></span> of <span class="totalPages"></span></h5></footer>', 
    margin: { top: "200px", bottom: "150px", right: "20px", left: "20px" }, 
  }); 

  //  SENDING BACK PDF IN RESPONCE TO API CALL 
  res.contentType("application/pdf"); 
  res.send(pdf);   
}; 
				
			

Explanation:  

To insert CSS in PDF and add a logo in when we are converting HTML to PDF, we are fetching a logo from a given URL. Then converting the image into base64 at runtime and finally embedding it into the header tag. Simple isn’t it.

Alternatively, you could also just have a logo on your local machine and convert it into base64. Then embed it to your header while you add CSS in page.

Adding Logo to the Header While Converting HTML to PDF Using Puppeteer
Adding Logo to the Header While Converting HTML to PDF Using Puppeteer

Add CSS HTML: How to Add CSS to HTML File Using Puppeteer

Let’s add CSS to HTML file when we convert from HTML to PDF. Now, if you are wondering where to put CSS in HTML… simply add a <style> script tag INSIDE the HTML file and write your CSS code. You don’t have to change anything in the code for adding inline CSS. Puppeteer will automatically catch and add CSS in PDF.

CSS in Page: Add External CSS for PDF Using Puppeteer

In contrast with the previous method, if you want to add external CSS from a file then add the following function in the “service.js” file. 

				
					exports.generate_pdf_with_css = async (req, res) => {
  const browser = await puppeteer.launch({ headless: true }); 
  const page = await browser.newPage(); 
  const logo_url = "https://programatically.com/file/2021/10/Nginx-Docker-BG.webp"; 
  
  // FETCHING LOGO FROM URL AND CONVERTING INTO BASE64 
  var logo = await fetch(logo_url) 
    .then((response) => response.buffer()) 
    .then((buffer) => buffer.toString("base64")) 
    .catch(console.error); 
  
  //  ADDING CSS TO HTML BODY CONTENT 
  const html = await `<style> ${fs.readFileSync(`./html_body.css`, "utf8")} </style> ${fs.readFileSync(`./dummy.html`, "utf8")}`; 
  await page.setContent(html, { waitUntil: "domcontentloaded"}); 
  
  const pdf = await page.pdf({ 
    format: "A4", 
    printBackground: false, 
    preferCSSPageSize: true, 
    displayHeaderFooter: true, 
  
    headerTemplate: `<div class="header"><img decoding="async" width="100" src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20100%200'%3E%3C/svg%3E" alt="company_logo" data-lazy-src="data:image/png;base64, ${logo}"><noscript><img decoding="async" width="100" src="data:image/png;base64, ${logo}" alt="company_logo"></noscript></div> `, 
    footerTemplate: '<footer><h5>Page <span class="pageNumber"></span> of <span class="totalPages"></span></h5></footer>', 
    margin: { top: "200px", bottom: "150px", right: "20px", left: "20px" }, 
  }); 
  
  //  SENDING BACK PDF IN RESPONCE TO API CALL 
  res.contentType("application/pdf"); 
  res.send(pdf);   
}; 
				
			

Then, create a CSS script named “html_body.css”. We are going to add CSS to HTML page by injecting the external CSS code while reading the HTML content. A simple concatenation did the trick here. Check the result of the generated PDF in the image below:  

Add External CSS to PDF While Converting HTML to PDF Using Puppeteer
Add External CSS to PDF While Converting HTML to PDF Using Puppeteer

Add CSS HTML: How to add Bootstrap CSS in PDF Using Puppeteer

In the event that you would want to inject the entire Bootstrap library while converting HTML to PDF using Puppeteer… we got you covered. 

You will follow all the things mentioned in step 3. The only change you will make is that you will download the CSS class of Bootstrap 5.0 from Google. Extract the “bootstrap.css” file from this and add it to your project root directory. And just like we injected external CSS in step 3, you will inject the bootstrap class in your generated PDF. Look at the image below for reference: 

Add Bootstrap CSS While Converting HTML to PDF Using Puppeteer
Add Bootstrap CSS While Converting HTML to PDF Using Puppeteer

And we’re done. This will add bootstrap CSS when you convert HTML to PDF in JavaScript using Puppeteer. 

P.S. adding BootStrap CSS in PDF using CDN does not work. I’ve tried.

CSS in Page: How to Resolve the Overlapping Header Issue in Puppeteer

Well, I have a few solutions for this. Just know that the puppeteer library is very powerful and stable. So it’s most likely the cause of CSS that makes the overlapping issue. Let’s see a few ways to resolve this problem. 

Solution 1:

Add the following CSS by injecting external CSS for PDF:  

				
					thead, tfoot { 
  display: table-row-group; 
}
				
			

Solution 2:

Add the following CSS by injecting external CSS for PDF:  

				
					thead { display: table-header-group; } 
tfoot { display: table-row-group; } 
tr { page-break-inside: avoid; } 
				
			

Solution 3:

Add the following CSS by injecting external CSS for PDF:  

				
					thead {
  display: table-header-group; 
  break-inside: avoid; 
}
				
			

Solution 4:

Add the following CSS by injecting external CSS for PDF:  

				
					table { overflow: visible !important; } 
thead { display: table-header-group } 
tfoot { display: table-row-group } 
tr { page-break-inside: avoid } 
				
			

Solution 5:

Remove the class ‘card’ 

I found that if there is a class named ‘card’ then this overlapping issue also comes up. Remove it and then try generating the PDF from HTML file. 

Conclusion

In summary, we were successful in the performing the following tasks:  

  1. Adding a logo in the Header while converting HTML to PDF 
  2. Add CSS to HTML file while generating PDF
  3. Adding External CSS in page while generating PDF
  4. Adding Bootstrap CSS to HTML while generating PDF 
  5. Covered a few solutions to resolve the overlapping header problem 

 

That’s all folks! I hope this tutorial helped you learn how to add CSS in PDF using Puppeteer. You may also want to learn how to download PDF in Angular or how to create DynamicJasper report. Feel free to leave a review in the comment section below.

Have a great one!