Vue: Xlink:href svg disappear bug in IE11 and below

Created on 30 Jun 2016  路  11Comments  路  Source: vuejs/vue

Vue.js version

1.0.26

Reproduction Link

http://vue-xlink-ie-bug.handcraft.com/index.html

Steps to reproduce

Load the page. As soon as vue is activated, the arrow-down svg icon inside the <button> disappears on IE11 and below.

What is Expected?

I expect the icon to remain. This behaviour is correct in browsers such as chrome, edge or firefox.

What is actually happening?

The icon is a xlink:href svg icon that vue is trying te re-render, which for some reason fails.

I know of an ugly workaround, which is:

<use xlink:href="#icon-angle-down" v-bind="{ 'xlink:href': '#icon-angle-down' }"></use>

However, this should not be required to render xlink:href svg's.

Source:

<html>
<head>
        <title>sdffsdfsd</title>
</head>
<body>
  <div id="site">
    <div @click="counter++">
      {{counter}}
    </div>
    <main>
      <button>
         hallo
         <svg><use xlink:href="#icon-angle-down"></use></svg>
      </button>
    </main>
  <div>

    <svg style="display: none;">
      <symbol viewBox="0 0 1792 1792" id="icon-angle-down"><title>angle-down</title><path d="M1395 736q0 13-10 23l-466 466q-10 10-23 10t-23-10L407 759q-10-10-10-23t10-23l50-50q10-10 23-10t23 10l393 393 393-393q10-10 23-10t23 10l50 50q10 10 10 23z"></path></symbol>
    </svg>
  </div>
</div>
<script src="http://cdn.jsdelivr.net/vue/1.0.26/vue.min.js"></script>
<script>
new window.Vue({
  el: '#site',
  data: function() {return {counter: 0};}
})
</script>
<style>
        button {
  position: relative;
  padding-right: 40px;
}
svg {
    height: 18px;
    width: 18px;
    fill: currentColor;
    position: absolute;
    right: 10px;
    top: 50%;
    -webkit-transform: translateY(-50%);
    -ms-transform: translateY(-50%);
    transform: translateY(-50%);
}
</style>
</body>
</html>

Most helpful comment

Using href instead of xlink:href did the trick for me.

All 11 comments

Your repro doesn't show the source code.

I've attached the source.

<use> is very buggy in Internet Explorer. If vue is detaching elements and moving them around in the DOM, all <use> svgs that are children of the moved elements will be lost, see here for example:

http://codepen.io/anon/pen/NAgRVm?editors=1010
An element with an svg icon is simply moved to another, using appendChild. In IE the icon disappears where as in other browsers it remains. This is not something vue could do anything about I'd imagine.

One 'solution' for you it to use a string template or script tag template, but that will only solve your current issue. There's many times, e.g. list rendering, where vue will use appendChild meaning you will face the same issue.

Ideally you would have an <icon name="icon-angle-down"> component which injects the full svg code of a given icon instead of using <use>. This will work much better in IE.

Close (5 days inactivity)

If you use symbols instead of groups, will work in IE11, with this polyfill svgxuse

@fergaldoyle almost 2 years later, one of the greatest wtf IE moments of my dev path.

We were able to fix this by using the v-pre tag, if it is of any help. Just use it on either the SVG or any of its parent elements.

Using href instead of xlink:href did the trick for me.

Neither of these worked for me. My icons still disappear. Everything I'm reading online says that if you have a symbol based SVG system, and are referencing nodes that exist on the page (not external), <use> should work fine in IE11. Yet, even with both :xlink:href and :href (I also tried v-pre and v-once) I'm not able to make it work. I'm going to make a demo with and without Vue and see if I can get a reproducible test case together to demonstrate the issue...

After a riveting day of SVG fun, this isn't a Vue issue.

If you notice any weirdness with your icons, make a test html page and work with that. Embed the svg icon in HTML without Vue to make sure it works fine, then add your loaders and only do it with javascript to see how your loaders change the HTML markup. Only after this should you then _finally_ add your InlineSVG.vue component (or equivalent)

TLDR: Ultimately, what I went with was updating my svgs not to have <use> elements. We simplified them so that they only have one compound path.

I learned about compound paths when giving up and trying to use a font icon building site. They wouldn't convert my icons unless they were in something called a "compound path". So I figured out what that was and figured out how to convert them to svgs that were defined in one path element.

This solution obviously doesn't work if you want to style individual bits of the SVG, but for an icon font, it worked pretty well.

What about styling individual parts of the SVG?
If you want to make some cool SVG, whose parts can be individually styled... then, inline the paths in its own MySpecialSvg.vue component, and make the component do the reusability via :style and :class on the individual paths.

My main caution is: stay away from <use>. If you have masks that depend on <use>, change the icon in Illustrator or sketch.

Tools/Solutions
Inline SVGs, after removing usages of or = vue-svg-loader
*Inline SVGs with <use> and sprite sheets = svg-sprite-loader + svgo-loader + svg4everybody

Other stuff
Honorable mention for if you're trying to get sprite sheets to work with href="sprite.svg#myCoolSprite" or xlink:href="sprites.svg#myCoolSprite" is to use a tool called svg4everybody to allow me to just use :href and :xlink:href. This works magically under the hood. (It uses XHR to request the sprite sheet externally and then creates a document context).

  • I couldn't figure out a way to get around the CORS restrictions of sprite sheets, so I couldn't do this. (We're a plugin on a partner's page, so we get blocked when cross origin requesting sprite sheets in prod 馃槄)

+1 for svg4everybody, it's what enabled us the IE11 compat.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

franciscolourenco picture franciscolourenco  路  3Comments

bfis picture bfis  路  3Comments

aviggngyv picture aviggngyv  路  3Comments

robertleeplummerjr picture robertleeplummerjr  路  3Comments

hiendv picture hiendv  路  3Comments