nicael
nicael

Reputation: 19014

Clip-path with source SVG is not applied

I would like to clip an image (<dummy> in the example) with clip-path, and it works perfectly if the SVG is inside HTML:

avaplace {
  display: flex;
}

verify {
  position: absolute;
  height: 100%;
  width: 100%;
  top: 62.5%;
  left: 62.5%;
}

green-circle {
  display: block;
  height: 35%;
  width: 35%;
  background: lightgreen;
  border-radius: 50%;
}

ava {
  position: relative;
}

dummy {
  display: block;
  width: 150px;
  height: 150px;
  background: red;
  clip-path: url(#v1);
}
<avaplace>
  <ava>
    <dummy></dummy>
    <verify>
      <green-circle></green-circle>
    </verify>
  </ava>
</avaplace>

<svg>
  <clipPath id="v1" clipPathUnits="objectBoundingBox">
    <path d="M0.964293 0.685917C0.987327 0.628445 1 0.565702 1 0.5C1 0.223858 0.776142 0 0.5 0C0.223858 0 0 0.223858 0 0.5C0 0.776142 0.223858 1 0.5 1C0.565702 1 0.628445 0.987327 0.685917 0.964293C0.633989 0.928167 0.6 0.868053 0.6 0.8C0.6 0.689543 0.689543 0.6 0.8 0.6C0.868053 0.6 0.928167 0.633989 0.964293 0.685917Z"/>
  </clipPath>
</svg>

However, I don't want the <svg> to be present on my HTML page, so I moved it to another file with-verify.svg (in the same folder) and altered my CSS according to docs (<clip-source>):

dummy {
  /* same stuff */
  clip-path: url(with-verify.svg#v1);
}

with-verify.svg has the following contents (i.e., whole svg just moved from HTML to this file)

<svg>
  <clipPath id="v1" clipPathUnits="objectBoundingBox">
    <path d="M0.964293 0.685917C0.987327 0.628445 1 0.565702 1 0.5C1 0.223858 0.776142 0 0.5 0C0.223858 0 0 0.223858 0 0.5C0 0.776142 0.223858 1 0.5 1C0.565702 1 0.628445 0.987327 0.685917 0.964293C0.633989 0.928167 0.6 0.868053 0.6 0.8C0.6 0.689543 0.689543 0.6 0.8 0.6C0.868053 0.6 0.928167 0.633989 0.964293 0.685917Z"/>
  </clipPath>
</svg>

For some unknown reason, at this point clipping is not applied at all. I was able to confirm via Chrome dev tools that with-verify.svg file is successfully pulled from its location (i.e., it's not a mislocated file), however the result looks as if the clipping was never applied:

I find it somewhat hilarious that this seemingly trivial problem has been bugging me for almost an hour. What am I doing wrong?

Upvotes: 0

Views: 186

Answers (1)

Even with that Chrome bug solved, you might run into duplicate ID issues when you have multiple images/clips on the page.

Problem with inline SVGs is the ID values need to be unique per SVG, or any following SVG will use the first defined mask/clip-path IDs

A Web Component can define your SVG once, and create those IDs dynamically:

svg {
  width: 250px;
  background: #efefef
}
<svg-avatar r="16" fill="#4267B2" href="//i.imgur.com/iCKbSvQ.png"></svg-avatar>
<svg-avatar r="14" href="//i.imgur.com/zTUDE6c.png"></svg-avatar>

<script>
  customElements.define("svg-avatar", class extends HTMLElement {
    connectedCallback() {
      let id     = n => n + Math.random() * 1e18; // create a unique id
      let maskid = id("mask");
      let clipid = id("clip");
      let r      = ~~(this.getAttribute("r")||14);
      this.innerHTML = 
      `<svg viewBox="0 0 60 40">
      <defs>
        <mask id="${maskid}"><rect fill="white"x="0"y="0"width="60"height="40"/>
          <circle cx="40"cy="20"r="${r+2}"/></mask>
        <clipPath id="${clipid}"><circle cx="40"cy="20"r="${r}"/>
      </defs>
      <circle mask="url(#${maskid})"fill="${this.getAttribute("fill")||"#F6BB43"}"
              opacity="1"cx="20"cy="20"r="${r}"/>
      <image href="${this.getAttribute("href")}"clip-path="url(#${clipid})"
             x="21"y="2"width="35"height="35"/>
      </svg>`
}});
</script>

Upvotes: -1

Related Questions