Google Chrome gets stuck when using toJpeg (after Google Chrome 138 upgrade)
Expected Behavior
toJpeg method generates compressed jpeg image as expected without any performance issue.
Current Behavior
Google Chrome gets stuck and generating jpeg file takes too long (causing the page to crash).
Possible Solution
Can't provide a suggested solution.
Steps To Reproduce
- Try to generate a jpeg file for a big DOM element using toJpeg method.
Additional Context
We have seen people reporting similar issue using html2canvas library (specifically html2canvas method), not sure if this library is using it behind the scene.
Your Environment
- html-to-image: 1.11.11
- OS: macOS Sequoia 15.5
- Browser: Google Chrome Version 138.0.7204.93 (Official Build) (arm64)
👋 @jose-escalona
Thanks for opening your first issue here! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. To help make it easier for us to investigate your issue, please follow the contributing guidelines.
We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can.
Commenting here to say I've also been impacted by this, best guess is the issue lies somewhere in the way every stylesheet is inlined on every node/element within the image. What that has to do with the Chrome 138 update I can't parse out.
I've opened a chromium issue as well for anyone else affected, and to see if there's a browser level issue.
Just to confirm, we use html2canvas and that library has been affected as well. Images (.png) we generate with html2canvas take 5 to 10 times longer to generate in Chrome 138 than they did in 137.
Any update on the fix for this as I am stuck facing this freezing issue. Any workaround if possible will also help
I just got the issue fixed in my project based on the solution from @erik-grubbs I am using version 1.11.11. I copied all the source files into my project and made the following modification: https://github.com/bubkoo/html-to-image/blob/efdf04338f3b943e9a0b27c4e1ee0b09d470c743/src/clone-node.ts#L121
toArray<string>(sourceStyle)
.filter((name) => !name.startsWith("--") && name !== "length")
You can also add a property to enable or disable this filter just like what erik did in his commit.
Thanks @erik-grubbs for the finding.
Any idea when this will be pushed to the repo. Copying the entire project to local doesnt seem a viable solution as its an enterprise project
@Debayan-Saha1406 don't currently have the time to make a PR adding it to the repo, mainly because we are basing our fork off a previous version, but should be pretty simple for anyone who's got the bandwidth. Or in html2canvas others have found success with changing to the library Snapdom.
I have tried with @erik-grubbs commit, but now Images formed are not proper and are distorted, without this commit Image generation was the exact match of html DOM.
Adding the source code directly into the project instead of using it as an npm package really helped. We observed an improvement in the speed of image generation from the HTML DOM.
I have tried with @erik-grubbs commit, but now Images formed are not proper and are distorted, without this commit Image generation was the exact match of html DOM.
@ashutosh-aneja did this also got fixed? If yes, what changes need to be done?
The root cause of this is a change in Chrome, https://crbug.com/41451306, to include custom properties in the result of getComputedStyle(). This is a change we'd like to make as there's currently no way to get this information in a cross-browser way. Firefox and Safari have included custom properties for a long time already.
Fortunately, there is a possible workaround for this in html-to-image using includeStyleProperties. You can compute an array of regular properties to include once, and pass it to toPng() or whichever method you depend on. Here's a helper method to compute that array, which again only needs to be done once:
// Get all property names accessible through getComputedStyle(), excluding custom properties
function getAllPropertyNames() {
var names = [];
var style = getComputedStyle(document.documentElement);
for (var i = 0; i < style.length; i++) {
var name = style[i];
if (!name.startsWith('--')) {
names.push(name);
}
}
return names;
}
Modifying the toPng() example to integrate this might look like this:
const node = document.getElementById('my-node');
const allPropertyNames = getAllPropertyNames(); // do this somewhere global, once only
htmlToImage
.toPng(node, { includeStyleProperties: allPropertyNames })
.then((dataUrl) => {
const img = new Image();
img.src = dataUrl;
document.body.appendChild(img);
})
.catch((err) => {
console.error('oops, something went wrong!', err);
});
I hope this can be a quickfix for some people when the change rolls out in Chrome again. If you want to test it now, you can use the --enable-features=CSSEnumeratedCustomProperties command line argument.
This change is rolling out again in Chrome 141, tracked by https://chromestatus.com/feature/5070655645155328. The workaround suggested above has been verified as working on one site that tried it, so it's what I would recommend to anyone who is affected by this issue.