Birrel
Birrel

Reputation: 4834

SVG - Clip-path only works when defined within same <svg> tags

I have an SVG star that I define externally, and then include within the DOM using use:

<svg>
  <defs>
    <symbol id="Star" viewBox="0 0 256 244">
      <polygon points="128 0 168.79 78.61 256 93.2 194 156.37 207.11 244 128 204.43 48.89 244 62 156.37 0 93.2 87.21 78.61 128 0"/>
    </symbol>
  </defs>
</svg>

<svg class="icon star" viewBox="0 0 256 244">
  <title>Add Favorite</title>
  <use xlink:href="#Star"></use>
</svg>

In this case, it is simply defined at the top of the body, but in practice will be an external file.

What I'd like to do is make the star appear to be filling in, from the outside. To do this, I add a stroke-width transition, and clip the SVG with the same path:

*HTML*

<svg class="icon star" viewBox="0 0 256 244">
  <defs>
    <clipPath id="clip" viewBox="0 0 256 244">
      <polygon points="128 0 168.79 78.61 256 93.2 194 156.37 207.11 244 128 204.43 48.89 244 62 156.37 0 93.2 87.21 78.61 128 0"/>
    </clipPath>
  </defs>

  <title>Add Favorite</title>
  <use xlink:href="#Star" clip-path="url(#clip)"></use>
</svg>


*CSS*

.icon {
  margin: 50px;
  width: 50px;
  height: 50px;
}
.star {
  fill: #0F0;
  stroke: #F00;
  stroke-width: 1px;
  transition: stroke-width 200ms linear;
}
.star:hover {
  stroke-width: 50%;
}

And it works a treat! Here is a working fiddle

BUT, when I try to move the clipPath definition up to the top...

<svg style="display: none;">
  <defs>
    <clipPath id="clip" viewBox="0 0 256 244">
      <polygon points="128 0 168.79 78.61 256 93.2 194 156.37 207.11 244 128 204.43 48.89 244 62 156.37 0 93.2 87.21 78.61 128 0"/>
    </clipPath>
  </defs>

  <defs>
    <symbol id="Star" viewBox="0 0 256 244" clip-path="url(#clip)">
      <polygon points="128 0 168.79 78.61 256 93.2 194 156.37 207.11 244 128 204.43 48.89 244 62 156.37 0 93.2 87.21 78.61 128 0"/>
    </symbol>
  </defs>
</svg>

<svg class="icon star" viewBox="0 0 256 244">
  <title>Add Favorite</title>
  <use xlink:href="#Star"></use>
</svg>

... it doesn't work anymore. Here is a not working fiddle.

There is no change if I include the clip-path="url(#clip)" within the use below. Same result. Likewise, for adding it within the CSS:

.star {
  ...
  clip-path: url(#clip);
}

So, what gives? How are the two different from one another? If I MUST use the first method, then so be it. But ideally, I'd like to keep the DOM as clean as possible, and have all the SVG definitions separate - or at least together at the top.

Upvotes: 1

Views: 263

Answers (2)

Ricardo Rodrigues
Ricardo Rodrigues

Reputation: 133

As Robert Longson suggested the display: none is best avoided.

Replacing it with width: 0; height: 0; fixed the issue.

https://jsfiddle.net/uq37cxep/12/

Upvotes: 0

Robert Longson
Robert Longson

Reputation: 124049

display: none is best avoided where SVG content is concerned. It turns off CSS and things like clip-path are CSS mapped attributes so they no longer work.

Use width="0" and height="0" instead (or set the outer SVG width and height via CSS if you want).

Upvotes: 1

Related Questions