tsayen / dom-to-image

Generates an image from a DOM node using HTML5 canvas
Other
10.32k stars 1.68k forks source link

the font property can not apply on the image #220

Open kkkisme opened 6 years ago

kkkisme commented 6 years ago

Use case: description, code

Edit Vue Template

Expected behavior

the <span> tag cssRules font-size:40px and font-weight:600 is apply on the image

Actual behavior (stack traces, console logs etc)

the <span> tag didnot applying the cssRules

Library version

2.6.0

Browsers

Chrome 67.0.3396.62

it seems a bug of chrome 67

Tu-Szu-Chi commented 6 years ago

Same issue +1 ...

rista404 commented 6 years ago

Same issue here.

jwareing commented 6 years ago

Same issue here. It seems that somehow our individual rules like font-size and font-weight etc. are getting collapsed into a single shorthand font declaration during the inlining process. In our code, we do not set font-stretch, but it is being set as 100% in the shorthand CSS rule that we see on the generated SVG. font: 700 100% 36px/46.8px Oswald; That second property above is font-stretch, but Chrome cannot interpret this shorthand for some reason. When the 100% declaration is removed, the image renders fine. I think something weird is happening when the font styles are inlined. Other browsers, and Chrome 66, are not collapsing all font rules to shorthand, and on the generated SVG we see inlined styles that look like font-family: Oswald; font-style: normal; font-weight: 700;

jwareing commented 6 years ago

Upon further inspection, I think chrome is doing this unintended translation when the cloned node's cssText is being set to the cssText from window.getComputedStyles(original) (see this line).

Running window.getComputedStyle on my original node in the Chrome console gives normal normal 400 normal 36px / normal Oswald, but after cloning the node and running clone.cssText = window.getComputedStyles(original).cssText, the clone's font is 400 100% 36px Oswald.

I don't know what can be done to get around this chrome bug. It seems like it is not interpreting the cssText correctly when it is resetting all the style properties in the node's CSSStyleDeclaration(context here). I couldn't find a great fix for this, but hopefully that helps if anyone is looking into it.

AresP commented 6 years ago

I find that if change the code cloneStyle() to

                function copyStyle(source, target) {
                    if (source.cssText) {
                        target.cssText = source.cssText;
                        target.font = source.font; // here, we re-assign the font prop.
                    } else copyProperties(source, target);

the problem is fixed.

HyggeBo7 commented 6 years ago
jwareing commented 6 years ago

So when we do window.getComputedStyles(original), font-stretch goes from normal to 100%. This is fine, but it looks like the bug is that Chrome is somehow trying to collapse the rule to the font shorthand when font-stretch is set, but it doesn't know how to handle font-stretch as a percentage in shorthand. It was not collapsing the rule as of Chrome 66.

jwareing commented 6 years ago

It looks like the Chrome team actually just became aware of this issue! Someone from BuzzFeed reported it lol.

https://bugs.chromium.org/p/chromium/issues/detail?id=850092

MDSLKTR commented 6 years ago

In case anyone wants this as an npm package feel free to use dom-to-image-chrome-fix while it's getting fixed. I'll deprecate the package again once it is fixed.

MadalenaGoncalves commented 6 years ago

@MDSLKTR thanks for the fix

MDSLKTR commented 6 years ago

It's basicly just @AresP's fix as a npm package :P

pietersv commented 6 years ago

@MDSLKTR @AresP Thank you for posting the fix! This resolves the issue on Chrome, still works on Firefox and (as expected) is subject to Safari's own security rules.

gitolog commented 6 years ago

@AresP thank you for the fix!