Html2canvas: SVG class styles are not rendered

Created on 10 Jan 2018  ·  7Comments  ·  Source: niklasvh/html2canvas

Version: 1.0.0-alpha.9
Issue: It seems that classes applied to SVG elements (and their children) are not applied to exported images.
However, if those styles are applied in an inline "style" attribute, they are applied correctly.

I have noticed that font, color, and fill to be problematic.

fiddle: http://jsfiddle.net/patgoins/2d90yop3/

--Examples--
Exported Image:
exportusinghtml2canvas

HTML View:
ui_screenshot

Most helpful comment

I don't know that I would call this a "fix" by any means but I have come up with a workaround for this issue.

The gist of this workaround consists of identifying problematic CSS properties that are not being rendered and then scanning the dom and inlining those styles wherever they are found on an element.

The following code is TypeScript but one could easily modify it for vanilla JS. I am calling this method just before calling the html2canvas(..) method:

private setInlineStyles(targetElem: HTMLElement) {

        const transformProperties = [
            'fill',
            'color',
            'font-size',
            'stroke',
            'font'
        ];

        let svgElems = Array.from(targetElem.getElementsByTagName("svg"));

        for (let svgElement of svgElems) {
            recurseElementChildren(svgElement);
        }

        function recurseElementChildren(node: SVGSVGElement | HTMLElement) {
            if (!node.style)
                return;

            let styles = getComputedStyle(node);

            for (let transformProperty of transformProperties) {
                node.style[transformProperty] = styles[transformProperty];
            }

            for (let child of Array.from(node.childNodes)) {
                recurseElementChildren(child as SVGSVGElement);
            }
        }
    }

targetElem is just a ref to an html element and could be an individual SVG element or even the whole <body> element if you would chose to do so

All 7 comments

I am having a very similar issue with some SVG charts that I have in my application as well.

I was just wondering if anyone from the HTML2Canvas team or anyone on this forum has any idea why this issue is occurring?

I don't know that I would call this a "fix" by any means but I have come up with a workaround for this issue.

The gist of this workaround consists of identifying problematic CSS properties that are not being rendered and then scanning the dom and inlining those styles wherever they are found on an element.

The following code is TypeScript but one could easily modify it for vanilla JS. I am calling this method just before calling the html2canvas(..) method:

private setInlineStyles(targetElem: HTMLElement) {

        const transformProperties = [
            'fill',
            'color',
            'font-size',
            'stroke',
            'font'
        ];

        let svgElems = Array.from(targetElem.getElementsByTagName("svg"));

        for (let svgElement of svgElems) {
            recurseElementChildren(svgElement);
        }

        function recurseElementChildren(node: SVGSVGElement | HTMLElement) {
            if (!node.style)
                return;

            let styles = getComputedStyle(node);

            for (let transformProperty of transformProperties) {
                node.style[transformProperty] = styles[transformProperty];
            }

            for (let child of Array.from(node.childNodes)) {
                recurseElementChildren(child as SVGSVGElement);
            }
        }
    }

targetElem is just a ref to an html element and could be an individual SVG element or even the whole <body> element if you would chose to do so

I have a similar problem but the difference is that the svg content which is spilling out of the svg element is not visible, by default the "user agent stylesheet" says svg overflow hidden, but I have a class to the svg element where I have overwritten the overflow property to "overflow: visible !important;". but still ever though I have tried to apply the overflow property on runtime just before I call the html2canvas(...) function, this doesn't seem to work.

The work-around is more than great but I think this issue should not be closed

Oh and btw for some strange reason (August 2020) the class styles work fine for firefox and chrome. Only Safari remains problematic here

same problem here. firefox and chrome are OK. But safari have this issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dking3876 picture dking3876  ·  4Comments

anthonymejia picture anthonymejia  ·  4Comments

stevencherry1 picture stevencherry1  ·  3Comments

celik75 picture celik75  ·  4Comments

AlphaDu picture AlphaDu  ·  4Comments