Reputation: 19014
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
Reputation: 21253
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