puppeteer: Custom Fonts not loaded when pdf generated
I try to generate a PDF with custom font but it doesn’t work when I inject fonts like this :
import { injectGlobal } from 'styled-components'
import Book from './assets/fonts/718/sevenoneeight-medium.woff2';
import Book2 from './assets/fonts/718/sevenoneeight-medium.woff';
injectGlobal `
@font-face {
font-family: "718book";
src: url(${Book}) format("woff2"),
url(${Book2}) format("woff");
}
body {
font-family: '718book';
-webkit-print-color-adjust: exact;
}
`;
Someone have an idea how to import fonts correclty ? I need a solution that works with any url -> http://localhost:3000, http://xxxxx.com …
It works when I generated a fonts folder in my build and I inject fonts like this :
injectGlobal `
@font-face {
font-family: "718book";
src: url('http://localhost:3000/fonts/718/sevenoneeight-medium.woff2') format("woff2"),
url('http://localhost:3000/fonts/718/sevenoneeight-medium.woff') format("woff");
}
`;
I convert my html to pdf like this :
let convertHTMLToPDF = async (html, callback, options = null) => {
if (typeof html !== 'string') {
throw new Error('xxxx.');
}
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setRequestInterception(true);
page.once('request', request => {
request.respond({ body: html });
page.on('request', request => request.continue());
});
const response = await page.goto('https://google.com');
await page.setContent((await response.buffer()).toString('utf8'));
await page.evaluateHandle('document.fonts.ready');
await page.pdf(options).then(callback, function(error) {
console.log(error);
});
await browser.close();
};
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 39
- Comments: 24
Commits related to this issue
- fix: wait for fonts before pdf printing https://github.com/puppeteer/puppeteer/issues/3183 — committed to puppeteer/puppeteer by OrKoN 3 months ago
- fix: wait for fonts before pdf printing https://github.com/puppeteer/puppeteer/issues/3183 — committed to puppeteer/puppeteer by OrKoN 3 months ago
- fix: wait for fonts before pdf printing https://github.com/puppeteer/puppeteer/issues/3183 — committed to puppeteer/puppeteer by OrKoN 3 months ago
@elrumordelaluz @billyvg What worked for us is to wait till the font’s are actually loaded before you create your pdf file, using this command:
This seems the best solution so far. As you can use custom fonts that are registered system wide and do not need to load them as base64 strings.
All credits go to this post: https://github.com/puppeteer/puppeteer/issues/422#issuecomment-708142856
EDIT: Important to note that we are using custom fonts that are imported system wide and NOT inline as base64 encoded.
I’ll expose my tests in case is useful for anyone to continue debug or to find a better solution:
I am generating a pdf from an
html
string. Something like:Since the html string uses an external font I tried different options that I’ll describe below. However only the last one works without differences on two environments. I am testing in local using OSX and in an external server using Linux. Here are the different options I tried:
@import url('https://fonts.googleapis.com/css2?family=…');
into a<style>
tag of the html string passedurl
as addStyleTag urlpuppeteer
is working and passing a addStyleTag pathawait page.evaluateHandle('document.fonts.ready')
and anotherwaitUntil
values.In all those scenarios, the resulting
pdf
were generated with the wrongfont
and using different fallback, since are different operating systems.The solution that works cross platform is to pass this
css
declaration inside thehtml
string:I hope there are better solutions since the base64 string for only one style of a font family is pretty big, and increases in cases where more styles or families are needed in the same page.
In some cases this is a bug related to the Access-Control-Allow-Origin limitations.
If you trust the url source, adding
--disable-web-security
fixes the issue.I also facing the same issue. I have attached the PDf file generated from Puppeteer. However, in my case I am using all my custom fonts base64 encoded. The page is rendered properly in chrome, chromium and also I tested headless: false, in all these case pages is rendered fine. But in headless: true all font is missing. hn.pdf
@font-face { font-family:ffc; src:url('data:application/font-woff;base64,d09…)format(“woff”); }
.ffc{font-family:ffc;line-height:1.589369;font-style:normal; font-weight:normal; visibility:visible; }
If you intend to use this only for pdf then maybe you could base64 encode the font and load it via url.
Hi @shibli786,
I have found a work around, it seem like the font need to be rendered as lead one time, so i have create a dummy
div
right afterbody
tag to render that font, e.g,See my real code here: