I'm trying to use an SVG to mask an image.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width=500 height=300>
<defs>
<clipPath id="clip">
<path d="M2.16,1.363h23.699c13.739,0,24.899,10.74,24.899,23.999s-11.16...
<img width="500" style="clip-path: url(#clip);-webkit-clip-path: url(#clip);" />
It works but I want the clipPath size to match the media. In Chrome I can control the size of the clipPath with CSS but in FF the clipPath stays small. In Safari with one asset nothing appears and with another it appears off-center.
I've read other questions that talk about using clipPathUnits:
<clipPath id="clip" clipPathUnits="objectBoundingBox">
But I cannot get this to work at all. Apparently it expects the paths units to be decimals... but my shape is too complicated to write by hand and I don't know of any design software that supports that format.
Update
Following Robert's comments, I tried adding a CSS transform to the clipPath to "translate" the units...
#clip {
-webkit-transform:scale(0.004195862879,0.005554321262);
transform:scale(0.004195862879,0.005554321262);
}
This allowed objectBoundingBox to work as expected in Chrome. But still no luck with Safari or FF. It appears that Safari still renders the clipPath outside the the element to be clipped... making it invisible. FF developer tools make it less clear where it's placing the clipPath.
-
1objectBoundingBox units go between 0 and 1.Robert Longson– Robert Longson2017年05月20日 20:21:50 +00:00Commented May 20, 2017 at 20:21
-
@RobertLongson I think this is stated in the question, no?emersonthis– emersonthis2017年05月21日 00:15:27 +00:00Commented May 21, 2017 at 0:15
-
What you've given us is an incomplete example so we can't fix that, all we're left with is stating generalities as an answer and you don't want that, so what do you want as an answer?Robert Longson– Robert Longson2017年05月21日 03:55:47 +00:00Commented May 21, 2017 at 3:55
-
@RobertLongson can you clarify what's missing from my question? I literally copy/pasted it from my project. I just omitted the path element's d attribute to save space. Looks like I also missed the href for the img... what else do you want me to include? Also generalities are welcome... I just confused because you repeated the question.emersonthis– emersonthis2017年05月21日 07:13:18 +00:00Commented May 21, 2017 at 7:13
-
An minimal reproducible example is missing. Please create a shortened valid path that we can correct.Robert Longson– Robert Longson2017年05月21日 07:14:15 +00:00Commented May 21, 2017 at 7:14
3 Answers 3
Run into this problem right now and found the solution. Thanks @RobertLongson for mentioning that when you applying clipPathUnits="objectBoundingBox", you should be sure that all of your coordinates are between 0 and 1. It means, that if you have, for example, a circle
<svg viewBox="0 0 20 20">
<defs>
<clipPath id="clip">
<circle cx="10" cy="10" r="10" />
</clipPath>
</defs>
</svg>
then with clipPathUnits="objectBoundingBox" it should looks like this:
<svg>
<defs>
<clipPath id="clip" clipPathUnits="objectBoundingBox">
<circle cx="0.5" cy="0.5" r="0.5" />
</clipPath>
</defs>
</svg>
In case of complex paths, I found one solution. All you need is an application for vector images editing. For Linux it could be Gravit Designer (I used it and it worked).
- Create new file of size 1x1
- Open you svg that contains your complex path without
clipPathtag. If you don't have such source, then you can simply create new text file, paste your<path .../>into<svg>...</svg>and save it with*.svgextension, and then open it in your application (Gravit Designer). - Copy your complex path from opened svg and paste it into created new file (1x1).
- Turn off "Preserve aspect ratio" (or something simillar) function if it enabled
- Set this parameters for your complex path:
Width: 1px,Height: 1px,Top: 0px,Left: 0px. - Save this 1x1 file as svg.
- Open this svg file in text editor and copy the value of
dattribute.
Now you have your complex path in relative coordinates. Set it into you clip
...
<clipPath id="clip" clipPathUnits="objectBoundingBox">
<path d="/* your copied value */" />
</clipPath>
...
Done! Now you can enjoy your responsive clip path without any additional transformations or other workarounds.
I know, it looks too complicated, but it really will be done in approximately 2 minutes (if you have vector image editing software installed).
Hope this helps someone despite of question was asked 1.5 years ago :)
5 Comments
I was using Adobe Illustrator to try and shrink my vectors down to 1px by 1px, and it wasn't capturing all of the coordinates correctly. I instead found this awesome online tool that will convert SVG path coordinates to CSS clip-path friendly coordinates relative to a "1" unit without needing a vector editing program. The quality is much better than Illustrator and easier to use. 🙌
3 Comments
I got a similar problem, I solved it like this:
- I transfer the svg file to figma (drag and drop)
- I align to a square 100 by 100 (without preserving the sides)
- export the file as svg
- I upload the file to the service https://betravis.github.io/shape-tools/path-to-polygon/ (not advertising, you can use something else)
- I get a clean polygon as a percentage, which can be used in clip-path;
example:
.elem-to-path{
clip-path: polygon(89.758% 99.457%, 67.178% 99.862%, 39.660% 99.621%, 7.748% 98.475%, 5.924% 98.004%, 5.742% 97.859%, 4.348% 92.036%, 1.807% 80.831%, 0.174% 36.869%, 1.052% 1.541%, 1.301% 1.012%, 2.237% 0.790%, 62.832% 0.559%, 78.860% 0.810%, 88.832% 0.810%, 96.913% 1.195%, 98.441% 3.283%, 99.616% 24.932%, 98.813% 86.202%, 96.703% 95.116%, 89.758% 99.457%)}