I am having some issues using an SVG clip-path. I can't work out how to make the path align with the image I am clipping - it is always way off. This is my markup:
HTML
<img class="svg-clipped" src="https://unsplash.it/1200/1200" alt="">
<svg height="0" width="0">
<defs>
<clipPath id="svgPath">
<path d="M124.8,656.7H142V501.9c65.5-27.5,53.6,10.8,129,4.7v150.1h17.2v20.7H124.8V656.7z"/>
</clipPath>
</defs>
</svg>
SCSS
.svg-clipped {
-webkit-clip-path: url(#svgPath);
clip-path: url(#svgPath);
}
And a Codepen here:
https://codepen.io/mikehdesign/pen/yoOZYo
If you scroll down you will see the SVG outline I am using. Ideally I would like it to be centered on the image, though top left would be fine too. As it is I can't work out what the logic is behind the positioning.
Thanks!
Mike
When applying clip paths to HTML elements, it is highly recommended that you use the objectBoundingBox coordinate space rather than the default user space coordinates (userSpaceOnUse).
In objectBoundingBox units, the coordinates map directly to the object the clip is being applied to. So (0,0) means the top-left of the object, and (1,1) maps to the bottom-right of the object.
So if you stick to coordinates in that range, your clipping path is guaranteed to fall directly over your image.
Here's a demo with a simple diamond clip path. I'll you to do the conversion of your shape to objectBoundingBox coordinates.
.svg-clipped {
-webkit-clip-path: url(#svgPath);
clip-path: url(#svgPath);
}
<img class="svg-clipped" src="https://unsplash.it/1200/1200" alt="">
<svg height="0" width="0">
<defs>
<clipPath id="svgPath" clipPathUnits="objectBoundingBox">
<path d="M 0.5,0 L 1,0.5 0.5,1, 0,0.5 Z"/>
</clipPath>
</defs>
</svg>
Related
I'm trying to create an effect on an svg path with vector="non-scaling-stroke" with a drop shadow using filter: drop-shadow(...).
However, when the path is scaled to fit the screen (having this scaling is necessary) the path remains a a consistent size but the drop shadow stretches:
svg {
width: 1000px; /*just to simulate problem, these would be vw & vh units in practice*/
height: 200px;
}
path {
filter: drop-shadow(0px 0px 1px blue);
}
<svg preserveAspectRatio="none" viewBox="0 0 100 100">
<path fill="none" stroke="black" stroke-width="5" vector-effect="non-scaling-stroke" d="M0,30 h50 v70"></path>
</svg>
As you can see, the shadow is closely fitted around the horizontal section of the line but more spread on the vertical section. This is expected really but I'm wondering if there's any trick I'm missing to have the shadow be a consistent size around the line for the entire path.
As well as using css filter I've tried:
using svg filters drop shadow on the path.
placing a dummy path behind the line with a gaussian blur to simulate a shadow.
Both produce the same result.
I also understand I can resize the svg viewBox to fit the screen with js to avoid the scaling issues altogether but this is really a last resort if there are no other solutions.
Thanks!
I think, that this could work!
svg {
width: 1000px;
/*just to simulate problem, these would be vw & vh units in practice*/
height: 200px;
}
<svg preserveAspectRatio="none" viewBox="0 0 100 100">
<path fill="none" stroke="black" stroke-width="5" vector-effect="non-scaling-stroke" d="M0,30 h50 v70"></path>
<rect x="0" y="29" width="50" height="2" style="fill:blue;filter: blur(2px);" />
<rect x="49.8" y="29" width=".5" height="70" style="fill:blue;filter: blur(.5px);" />
</svg>
lets suppose I have an image of dimensions 1280x720
I have some polygons that are computed by a server on top of the original sized images that need to be drawn on top of this image. They are
<polygon points="531,243,687,316,663,593,360,717,191,520" />
<polygon points="275,17,422,45,412,312,271,235" />
<polygon points="929,180,1108,248,985,707,847,676" />
<polygon points="598,70,700,101,658,531,516,436" />
Now I need to display the image and overlay these polygons on top of it. The problem however is that the image is scaled by the browser depending on the window size, which is dynamic. The image is displayed using object-fit-contain CSS so the size changes as I resize.
How do I ensure the SVG co-ordinates above auto scale?
I've read about viewBox but I'm not really looking to specify my own co-ordinates here. The issue is I don't really know how the image will be displayed/sized by the browser as it will depend on the window.
thanks
The default scaling behaviour of SVGs is the same as object-fit: contain. So all you should need to do is set the SVG's viewBox width and height to the same dimensions as the image.
So, for instance, if your image is 640x480, set your viewBox to "0 0 640 480".
div {
position: relative;
}
div > img,
div > svg {
width: 100%;
height: 200px;
}
img {
object-fit: contain;
}
svg {
position: absolute;
top: 0;
}
<div>
<img src="http://lorempixel.com/output/people-q-c-640-480-1.jpg"/>
<svg viewBox="0 0 640 480">
<circle cx="450" cy="215" r="40" fill="none" stroke="red" stroke-width="10"/>
</svg>
</div>
Could you avoid doing this with html in any way? A simple image editor seems like a better way of doing this, but I can't say because I don't know your circumstances. Otherwise you could probably use margin for the placement.
You can use <image> element inside the <svg> tag, then they will become one, you can do any scale with it.
Here is an SVG image example:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="10" y="10" height="130" width="500" style="fill: #000000"/>
<image x="20" y="20" width="300" height="80"
xlink:href="http://jenkov.com/images/layout/top-bar-logo.png" />
<line x1="25" y1="80" x2="350" y2="80"
style="stroke: #ffffff; stroke-width: 3;"/>
</svg>
Reference: SVG image element
Hello, I'm using slick slider and I want to clip-path the container but the clip-path doesn't work well..
this is my svg path
<svg width="0" height="0">
<defs>
<clipPath id="mask1">
<path id="curve" d="m242.6,393.7c-82.2,-4.7 -138.1,-15.4 -191.2,-36.6 -19.3,-7.7 -36.4,-16.1 -47.7,-23.5l-3.2,-2.1 -0,-71.5c-0,-39.3 -0.1,-113.9 -0.3,-165.8l-0.3,-94.2 371.1,0 371.1,0 0,152 0,152 -5.8,3.7c-7.8,5 -14.5,8.8 -23.4,13.4 -70.4,36.3 -187.2,62.5 -317.4,71.2 -28.6,1.9 -31.6,2 -91.2,1.9 -31,-0 -58.8,-0.2 -61.9,-0.4z">
</path>
</clipPath>
</defs>
</svg>
the slider works but the clip-path doesn't fit the 100% window..
Thanks.. and sorry for my English..
You should convert your clipPath to one using bounding box units:
<clipPath clipPathUnits="objectBoundingBox" ... >
When you use bounding box units, all your clip path coordinates should be defined in the range 0..1.
http://www.w3.org/TR/SVG/masking.html#EstablishingANewClippingPath
If you do this, the clipping path will be given the same size as the the element you apply it to.
img {
width: 100%;
clip-path: url(#mask1);
-webkit-clip-path: url(#mask1);
}
<svg width="0" height="0">
<defs>
<clipPath id="mask1" clipPathUnits="objectBoundingBox">
<path id="curve"
transform="scale(0.00135, 0.00254)"
d="m242.6,393.7c-82.2,-4.7 -138.1,-15.4 -191.2,-36.6 -19.3,-7.7 -36.4,-16.1 -47.7,-23.5l-3.2,-2.1 -0,-71.5c-0,-39.3 -0.1,-113.9 -0.3,-165.8l-0.3,-94.2 371.1,0 371.1,0 0,152 0,152 -5.8,3.7c-7.8,5 -14.5,8.8 -23.4,13.4 -70.4,36.3 -187.2,62.5 -317.4,71.2 -28.6,1.9 -31.6,2 -91.2,1.9 -31,-0 -58.8,-0.2 -61.9,-0.4z">
</path>
</clipPath>
</defs>
</svg>
<img src="//placekitten.com/400/150"/>
What I have done in the example above is to use a transform to scale the clip path to size 1x1. It's easier than recreating the shape with new coordinates.
I am trying to display these social media icons on my website in such a way that I can change the color using css (so i can add the hover effect shown in the code below).
However, since these are vector image files (.svg) I couldn't seem to find a way to insert the image into my web page using the conventional <img src=""> method. So I proceeded to create CSS classes to get the image to appear as a CSS mask (thus allowing me to change the color via CSS).
However, I quickly noticed that the sides of the otherwise circular vector graphic icons were slightly cutoff. Being the perfectionist that I am, I wanted to make the icons actually appear round as they were supposed to. So, after checking out the webkit-mask MSDN entry I increased the width of the .media-buttons class and used -webkit-mask-position to shift the image a few pixels down and to the left as is evident in my code below. This obviously did not work.
It has also come to my attention that -webkit-mask is not fully supported by all browsers.
CSS:
#cross{-webkit-mask: url("http://path/to/image.svg") no-repeat;}
.media-buttons {
width: 202px;
height: 202px;
background: #000;
-webkit-mask-position: 10px 10px;
}
.media-buttons:hover {background: rgb(94, 176, 201);}
HTML:
<img class="media-buttons" id="cross">
TL;DR, I am looking for a (possibly new) way to display my .svg icons that has somewhat decent browser support and the ability to manipulate the icon's color via CSS.
Here's one way:
svg:hover {
color: #009BCD;
}
p {
color: green;
}
<svg width="200px" height="200px" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" display="none">
<title>Cross</title>
<description>Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<path d="M100,0 C44.771524,3.03201907e-14 0,44.771524 0,100 C0,155.228476 44.771524,200 100,200 C155.228476,200 200,155.228476 200,100 C200,44.771524 155.228476,-3.41060513e-14 100,0 Z M84.0763011,40 L115.923699,40 L115.923699,84.1405714 L160,84.1405714 L160,116.034408 L115.923699,116.034408 L115.923699,160.16875 L84.0763011,160.16875 L84.0763011,116.034408 L40,116.034408 L40,84.1405714 L84.0763011,84.1405714 L84.0763011,40 Z" id="Cross" fill="currentColor" sketch:type="MSShapeGroup"></path>
</g>
</svg>
<p>
Heh! What's this
<svg width="1em" height="1em" viewBox="0 0 200 200">
<use xlink:href="#Cross"/>
</svg>
doing in the middle of a sentence?
</p>
<svg width="50px" height="50px" viewBox="0 0 200 200">
<use xlink:href="#Cross"/>
</svg>
What I did here was:
Copy the SVG into the HTML (and removed the XML preamble)
Set display="none" on the <svg> so that it is invisible on the page.
Changed the fill on the icons <path> element to currentColor
Now every time you want a copy of the icon to appear, create a mini-svg that reverences the <path> in the first SVG.
<svg width="50px" height="50px" viewBox="0 0 200 200">
<use xlink:href="#Cross"/>
</svg>
Just set it's size with the width and height values. You just need to include each icon once and you can reference them as many times as you like.
What is currentColor for?
currentColor is a special color value in SVGs that tells the elements to use the value of the current color setting. It means you can set the color outside the <use> element and it gets inherited by whatever the <use> is referencing. Normally you can't style each of the icon references individually. They would all be stuck having whatever fill the original <path> is set to.
Using just the original SVG
svg path {
fill: blue;
}
svg:hover path {
fill: #009BCD;
}
<p>SVG just used as is</p>
<svg width="100px" height="100px" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<title>Cross</title>
<description>Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill-rule="evenodd" sketch:type="MSPage">
<path d="M100,0 C44.771524,3.03201907e-14 0,44.771524 0,100 C0,155.228476 44.771524,200 100,200 C155.228476,200 200,155.228476 200,100 C200,44.771524 155.228476,-3.41060513e-14 100,0 Z M84.0763011,40 L115.923699,40 L115.923699,84.1405714 L160,84.1405714 L160,116.034408 L115.923699,116.034408 L115.923699,160.16875 L84.0763011,160.16875 L84.0763011,116.034408 L40,116.034408 L40,84.1405714 L84.0763011,84.1405714 L84.0763011,40 Z" id="Cross" sketch:type="MSShapeGroup"></path>
</g>
</svg>
I can't tell for sure where this bug is coming from but I think it has something to do with borders. Add a 1px border and you'll see some really weird behaviour. Now to answer your question: To make sure your image doesn't get clipped you can use mask-size. E.g. -webkit-mask-size: 50% 50%;
Just don't think masks are ready for primetime just yet.
Here's a pen that demonstrates this: http://codepen.io/anon/pen/ONLRbZ
I've created an svg and an ellipse inside it using the code
<svg xmlns="http://www.w3.org/2000/svg"
version="1.1"
type="svgObj"
style="display: inline; position: relative; left: 0px; top: 0px;"
id="svg_5"
preserveAspectRatio="none">
<ellipse type="svgShpObj" id="shape_2" cx="59px" cy="33px" rx="57px" ry="31px"
fill="#A5A85A" stroke-width="10" stroke="#F5821F"
stroke-opacity="1" fill-opacity="0.39215686274509803"/>
</svg>
paste it to http://www.w3schools.com/svg/tryit.asp?filename=trysvg_myfirst and check the problem that it clips left and top sides of the ellipse. How to fix this?
The "clipped" parts of the SVG are simply outside of the viewport.
There are several ways to "fix" this.
You can reposition the ellipse (MDN docu here and here) by changing the respective coordinates to
cx="70px" cy="40px"
Or you can explicitly set a viewBox (MDN docu), that includes the whole ellipse, by adding, e.g.,
viewBox="-10 -10 300 300"
to the <svg> element itself.