Html2canvas: Fontawesome showing blank squares when using foreignObjectRendering

Created on 16 Dec 2018  ·  19Comments  ·  Source: niklasvh/html2canvas

I want to take screenshot of website which is using bootstrap, so i need to use foreignObjectRendering: true, because normally bootstrap buttons are not rendered correctly on canvas. This happens only in chrome (tested only on chrome and edge, I don't have currently installed anything else). Normally this would not be such a problem because the app I am building will be only for me so I could switch to another browser, problem is that the app is based on electron, which is based on chrome and the app can't run in standard browser. Any help please?

Example:

Original content in browser:
image

Rendered without foreignObjectRendering (button without outline is messed up):
image

When using foreignObjectRendering (icons not showing):
image

When using foreignObjectRendering with Fontawesome as SVG:
image

Code that I am using to capture the screenshot

function takeScreenshot(path) {
    html2canvas(document.querySelector("section"), {
        allowTaint: true,
        height: $("body").height(),
        foreignObjectRendering: true,
    }).then(function (canvas) {
        const imageHash = canvas.toDataURL()

        const base64Data = imageHash.replace(/^data:image\/(png|jpg);base64,/, "")
        console.log(imageHash)

        fs.writeFile(path.split('.')[path.split('.').length - 2] + ".jpg", base64Data, 'base64', (err) => {
            console.log(err)
        })
    })
}

Most helpful comment

This fix solved my problem. Maybe it can help you https://github.com/niklasvh/html2canvas/pull/1948/files

All 19 comments

I have the same problem. Did you find any solution? I'd like to use fontawesome but it displays blank squares when I set foreignObjectRendering to true.

no luck yet.. but if you will find the solution let me know please.

My temporary solution is to put data-html2canvas-ignore="true" attribute on the div containing fontawesome icons. For example :
<span class="input-group-addon" data-html2canvas-ignore="true"><i class="fa fa-search"></i></span>
But I'd like to find a better solution to display the icons.

Same problem here.

same in a pwa

if anyone still has this problem - converting the svg fontawesome icons to canvas elements fixes it for me.
Here's the code:

const ratio = window.devicePixelRatio || 1;
[...document.querySelectorAll("svg.svg-inline--fa")].map(svgElement => {
  // create a new canvas
  const canvas = document.createElement("canvas");

  // multiply the dimensions by the ratio (important for retina displays)
  canvas.width = svgElement.getBoundingClientRect().width * ratio;
  canvas.height = svgElement.getBoundingClientRect().height * ratio;

  // force the canvas css to have the same width and height as the original svg icon
  canvas.style.width = svgElement.getBoundingClientRect().width + "px";
  canvas.style.height = svgElement.getBoundingClientRect().height + "px";

  // hide the original svg icon and append the newly created canvas
  svgElement.style.display = "none";
  svgElement.parentNode.appendChild(canvas);

  // draw the original svg icon onto the new canvas
  var ctx = canvas.getContext("2d");
  var DOMURL = self.URL || self.webkitURL || self;
  var svgString = new XMLSerializer().serializeToString(svgElement);
  var img = new Image();
  var svg = new Blob([svgString], { type: "image/svg+xml;charset=utf-8" });
  img.src = DOMURL.createObjectURL(svg);
  img.onload = function() {
    ctx.drawImage(img, 0, 0);
  };
});

I'm having this issue with just regular "fa-pencil" icons not using SVG. I tried the above code and got the same result of no icons.

Any chance you guys have your font awesome css in a file named differently than it was distributed?

I have the same issue, is there any chance it will be fixed?

Same issue, @niklasvh is there a workaround for this ? Or maybe you can tell us what is the problem so maybe we could do a pr about it ?

This fix solved my problem. Maybe it can help you https://github.com/niklasvh/html2canvas/pull/1948/files

I am using these font-awesome icons:

  1. fa fa-check-circle
  2. fa fa-exclamation-circle
  3. fa fa-clock

In the PDF i generate, its showing as small squares and I am having issue in chrome. Is there a workaround for these icons ?? Please let me know if there is workaround

Same here.
I am using 'Font Awesome 5 Free' installed with npm @fortawesome/fontawesome-free
All these icons are not rendered, only a square appears.

Made some tests and the issue appears from RC2 until RC5.
Working example with rc1: https://jsfiddle.net/1kn5hzLr/7/

Not sure if related but large icons are cropped.

Thanks!

I have a similar issue when trying to take a screenshot of a graph using alchemyjs. Only squares appear for icon inside svg foreignObject.

If anyone has time, I'd appreciate feedback on whether https://github.com/niklasvh/html2canvas/pull/2219 resolves this rendering issue (it does seem to affect fonts that contain a space in the font name; Font Awesome 5 Free falls into that category).

Update: the fix in #2219 only affects CSS-based font icon rendering; SVG / foreign object rendering is not affected. I'll resolve/hide these comments to avoid distracting others.

There is a CSS workaround for this. Per @jayaddison PR the issue seems to arise from the fact that the font awesome icons have the font 'Font Awesome 5 Free' which html2canvas doesn't parse correctly.

The solution in CSS is to save the font awesome font files locally and then use a @font-face css directive to rename it to something that html2canvas will parse properly (i.e. no spaces and no numbers). For starters, here is what I used to solve my immediate problem:

@font-face {
  font-family: 'fontawesome';
  src: url('../font/fa-solid-900.woff') format('woff');
}

.fa, .far, .fas {
  font-family: 'fontawesome' !important;
}

To make sure this works everywhere for all your font awesome icons you may need to add more fonts to the family / add some more comprehensive CSS, but this should get you started.

Hope this helps someone

hope this helps someone. If you're using the svg icons you can do something like this:

var svgElements = document.body.querySelectorAll('svg.svg-inline--fa'');
svgElements.forEach(function(item) {
    item.setAttribute("width", item.getBoundingClientRect().width);
    item.setAttribute("height", item.getBoundingClientRect().height);
    item.style.width = null;
    item.style.height= null;
});

height and width attributes are required on the svg element for them to show up https://stackoverflow.com/a/59162619/237917

I was experiencing the same problems with version 1.0.0-rc.5. Upgrading to 1.0.0-rc.7 fixed it for me. Font Awesome 5 Free icons now work flawlessly.

Was this page helpful?
0 / 5 - 0 ratings