clip-path not working in SVG sprite

2019-05-07 20:34发布

(live example at http://codepen.io/RwwL/pen/xbNLJp)

I'm including SVGs in an app using the <symbol> element (see https://css-tricks.com/svg-symbol-good-choice-icons/ for full details as to why), and certain icons — ones that include clip-path — are not rendering when I include their icons in pages with the <use> element.

<svg style="display: none">
  <symbol id="icon-pin" viewBox="0 0 24 24" enable-background="new 0 0 24 24">
    <path fill="none" stroke="#2F3137" stroke-width="2" stroke-miterlimit="10" d="M12 2C8.3 2 5.3 5 5.3 8.7c0 1.2.3 2.3.9 3.3l5.4 9.9c.1.1.2.2.4.2.1 0 .3-.1.4-.2l5.4-9.9c.5-.9.9-2.1.9-3.3C18.7 5 15.7 2 12 2zm0 0" />
    <clipPath id="pin-clip">
        <path d="M12 11.2c-1.4 0-2.5-1.1-2.5-2.5s1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5-1.1 2.5-2.5 2.5zm0 0" />
    </clipPath>
    <path clip-path="url(#pin-clip)" fill="#2F3137" d="M4.5 1.2h15v15h-15z" />
  </symbol>
</svg>
</div>

<h2>Normal inline SVG</h2>
<svg id="inlinePin" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" enable-background="new 0 0 24 24">
    <path fill="none" stroke="#2F3137" stroke-width="2" stroke-miterlimit="10" d="M12 2C8.3 2 5.3 5 5.3 8.7c0 1.2.3 2.3.9 3.3l5.4 9.9c.1.1.2.2.4.2.1 0 .3-.1.4-.2l5.4-9.9c.5-.9.9-2.1.9-3.3C18.7 5 15.7 2 12 2zm0 0" />
    <clipPath id="inline-pin-clip">
        <path d="M12 11.2c-1.4 0-2.5-1.1-2.5-2.5s1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5-1.1 2.5-2.5 2.5zm0 0" />
    </clipPath>
    <path clip-path="url(#inline-pin-clip)" fill="#2F3137" d="M4.5 1.2h15v15h-15z" />
</svg>

<h2>Inline SVG using sprite</h2>
<svg>
  <use xlink:href="#icon-pin">
</svg>

Here's how it's rendering:

enter image description here

It's broken in the same way across Chrome/Firefox/Safari, so it seems to most likely just be something I'm not understanding about the way other elements need to be referenced in SVG, especially when a symbol is being pulled in via a use. IE11 is also not rendering correctly, but in a slightly different way (no dot in the middle of the pin, but no solid square box like the others).

标签: svg
1条回答
欢心
2楼-- · 2019-05-07 21:16

The problem is caused by the very first line

<svg style="display: none">

Removing display: none will render your svg referencing the inline sprite just fine.

This does at first seem a bit odd since the spec tells us

The ‘display’ property does not apply to the ‘symbol’ element; thus, ‘symbol’ elements are not directly rendered even if the ‘display’ property is set to a value other than none, and ‘symbol’ elements are available for referencing even when the ‘display’ property on the ‘symbol’ element or any of its ancestors is set to none.

But reading further down the spec it becomes apparent why setting display: none causes this unexpected rendering:

The ‘display’ property affects direct rendering into offscreen canvases also [...] Setting display: none on a child of a ‘clipPath’ element will prevent the given child element from contributing to the clipping path.

Thus, setting display: none globally on the svg inhibits rendering of these offscreen canvases leaving you with the incomplete clip path, although it can still be referenced. Removing the display-attribute from the root svg and setting it directly to the clipPath will demonstrate the same behaviour.

To hide your sprite svg you could go for something like

<svg width="0" height="0">

Update:

IE and Firefox seem to be even a bit more stringent on rendering the offscreen canvases when putting a clipPath inside a symbol. Since symbols itself are never rendered, the contained clipPath will keep missing the offscreen rendering and can therefore not meaningfully be applied to any element. You should put the clipPath right outside the symbol which works well in IE, FF and Chrome.

<svg>
    <clipPath id="pin-clip">
        <path d="M12 11.2c-1.4 0-2.5-1.1-2.5-2.5s1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5-1.1 2.5-2.5 2.5zm0 0" />
    </clipPath>
    <symbol id="icon-pin" viewBox="0 0 24 24" enable-background="new 0 0 24 24">
        <path fill="none" stroke="#2F3137" stroke-width="2" stroke-miterlimit="10" d="M12 2C8.3 2 5.3 5 5.3 8.7c0 1.2.3 2.3.9 3.3l5.4 9.9c.1.1.2.2.4.2.1 0 .3-.1.4-.2l5.4-9.9c.5-.9.9-2.1.9-3.3C18.7 5 15.7 2 12 2zm0 0" />
        <path clip-path="url(#pin-clip)" fill="#2F3137" d="M4.5 1.2h15v15h-15z" />
    </symbol>
</svg>
查看更多
登录 后发表回答