reactjsbabeljssvg-sprite

Mask tag in svg is ignored if used from an external svg-sprite file


I'm trying to use an svg sprite in my project, and it works fine, unless you're using a mask tag in a sprite:

public/sprite.svg:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="0" height="0">
  <defs>

    <symbol viewBox="0 0 16 16" id='pharmacy'>
      <mask id="pathOne" fill="white">
        <path fill-rule="evenodd" clip-rule="evenodd" d="M11 2H5V5L2 5V11H5V14H11V11H14V5H11V2Z"/>
      </mask>
      <path d="M5 2V1H4V2H5ZM11 2H12V1H11V2ZM5 5V6H6V5H5ZM2 5L2 4L1 4V5H2ZM2 11H1V12H2V11ZM5 11H6V10H5V11ZM5 14H4V15H5V14ZM11 14V15H12V14H11ZM11 11V10H10V11H11ZM14 11V12H15V11H14ZM14 5H15V4H14V5ZM11 5H10V6H11V5ZM5 3H11V1H5V3ZM6 5V2H4V5H6ZM2 6L5 6V4L2 4L2 6ZM3 11V5H1V11H3ZM5 10H2V12H5V10ZM6 14V11H4V14H6ZM11 13H5V15H11V13ZM10 11V14H12V11H10ZM14 10H11V12H14V10ZM13 5V11H15V5H13ZM11 6H14V4H11V6ZM10 2V5H12V2H10Z" fill="#171717" mask="url(#pathOne)"/>
    </symbol>

  </defs> 
</svg>

src/App.js:


export default function App() {
  return (
    <div className="App">

      <svg width="16px" height="16px">
        <use href="/sprite.svg#pharmacy" />
      </svg>
      
    </div>
  );
}

So the problem is that the mask is ignored in all the browsers, and you're getting wrong image. Strangely, when you're using an inline svg or you put your sprite inside markup, everything works fine. The problem might be with babel because I checked in vanilla JS, it's the same. Can somebody help me?

https://codesandbox.io/s/epic-darwin-0n5uk5


Solution

  • Currently masks or clipPaths are not supported in external <use> elements.

    As a workaround you could either use css mask-image property. You could either include you mask shape via data Url or using an external file.

    External: mask.svg

    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
        <path d="M11 2H5V5L2 5V11H5V14H11V11H14V5H11V2Z" />
    </svg>
    

    css:

    .masked-external {
      -webkit-mask-image: url("mask.svg");
      mask-image: url("mask.svg");
      -webkit-mask-size: cover;
      mask-size: cover;
    }
    

    Mask from data Url:

    .masked {
        -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M11 2H5V5L2 5V11H5V14H11V11H14V5H11V2Z' /%3E%3C/svg%3E");
        mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M11 2H5V5L2 5V11H5V14H11V11H14V5H11V2Z' /%3E%3C/svg%3E");
        -webkit-mask-size: cover;
        mask-size: cover;
    }
    

    HTML

    <svg class="masked" viewBox="0 0 16 16">
         <use href="sprite.svg#pharmacy" />
    </svg>