I've created an svg for use as a clip-path on an image, and it appears perfect in Firefox, however it doesn't work in Chrome, and I'm wondering what the problem is.
Chrome should support an inline svg clip-path according to this.
And full support according to MDN.
<style>
img {
width: 40%;
height: auto;
display: inline;
}
.clip {
-webkit-clip-path: url('#clip');
clip-path: url('#clip');
}
</style>
<p>Left image should be clipped, right image is not.</p>
<img src="https://i.imgur.com/nnHdzO6l.jpg" class="clip">
<img src="https://i.imgur.com/nnHdzO6l.jpg" >
<svg version="1.1"
baseProfile="full"
height="400" width="400"
xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="clip"
clipPathUnits="objectBoundingBox"
transform="scale(0.0025, 0.0025)">
<!-- https://css-tricks.com/scaling-svg-clipping-paths-css-use/ -->
<circle cx="50%" cy="50%" r="50%" />
<rect width="82.8%" height="82.8%" y="17.2%" x="8.6%" />
</clipPath>
</defs>
</svg>
External SVG files are not supported by Chrome at the moment.
You can check this here:
https://caniuse.com/#search=CSS%20clip
Here is what they say about the Partial support for Chrome:
Partial support refers to supporting shapes and the url(#foo) syntax
for inline SVG, but not shapes in external SVGs.
Related
Maybe it's a bug, but check this out. https://codepen.io/Firsh/pen/LegGQq
/*
Only these work:*/
/*
symbol{ overflow: visible; }
*/
/*
#circle-symbol{ overflow:visible; }
*/
/* NO matter how I target it, it doesn't work... */
.product symbol, svg symbol, .definitions symbol {
overflow: visible;
}
.my-circle{
overflow: visible;
fill:red;
stroke-width:15px;
stroke:#000;
}
.definitions{
position:absolute;
}
<br>This is cut off on Firefox only:<br><br>
<div class="product">
<svg viewBox="0 0 90 90" width="90" height="90" class="my-circle" style="">
<use xlink:href="#circle-symbol"></use>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" class="definitions">
<defs>
<symbol id="circle-symbol" viewBox="0 0 90 90">
<path fill-rule="evenodd" clip-rule="evenodd" d="M76.85,13.2C85.616,21.967,90,32.567,90,45c0,12.434-4.384,23.017-13.15,31.75 C68.05,85.583,57.434,90,45,90c-12.367,0-22.967-4.417-31.8-13.25C4.4,68.017,0,57.434,0,45c0-12.433,4.4-23.033,13.2-31.8 C22.033,4.4,32.633,0,45,0C57.434,0,68.05,4.4,76.85,13.2z"></path>
</symbol>
</defs>
</svg>
</div>
<br>This is how it should look like (Chrome, Edge):<br>
<img src="https://i.snag.gy/cxM306.jpg" width="109" height="108" />
I've found that when my CSS selector is direct, it works. Otherwise, no matter how I try to qualify symbol to add the visible overflow property, it doesn't work.
Firefox implements SVG 2 <use> elements. In SVG 2 <use> selectors must not cross the shadow document boundary i.e. you can't point part of the CSS selector to the (or its parents) and the other part to the <use> reference.
Chrome, Safari and Edge will likely change to match Firefox at some point.
For anyone having this problem, this solved it for me
svg, symbol { overflow: visible; }
Updated codepen here
There is a difference between displaying in Firefox and Chrome. As I investigated Chrome takes css into account while displaying image and Firefox not.
html
<svg viewBox="-80 0 500 500">
<g>
<g class="node" transform="translate(0,20)" style="opacity: 1;">
<text transform="translate(0,0)"><tspan class="message">Visible in Chrome and Firefox</tspan></text>
<image class="icon" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://cdn3.iconfinder.com/data/icons/diagram_v2/PNG/32x32/diagram_v2-17.png" x="0" y="15" width ="20px" height="20px" ><title>Try to use in Firefox and Chrome.</title>
</image>
</g>
<g class="node" transform="translate(0,80)" style="opacity: 1;">
<text transform="translate(0,0)"><tspan class="message">Invisible in Firefox</tspan></text>
<image class="icon" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://cdn3.iconfinder.com/data/icons/diagram_v2/PNG/32x32/diagram_v2-17.png" x="0" y="15" ><title>Try to use in Firefox and Chrome.</title>
</image>
</g>
</g>
</svg>
css
.icon {
display: block;
margin: 0 auto;
width: 20px;
height: 20px;
}
.message {
text-align: left;
visibility: visible;
font: 8pt sans-serif;
}
Here is jsfiddle for it. How to push Firefox to use css?
PS: I found related question, but I have viewBox in root element.
In SVG 1.1 (the current standard), only properties could be styled with CSS.
In the upcoming SVG 2 standard, nearly every attribute will be stylable with CSS. However browsers have only just started implementing this change. Chrome is further along in implementing this than Firefox.
For now, you'll have to do this a different way. Ie. with attributes width="20" height="20".
I have created a fairly simple shape using an SVG element which is then put into my CSS using clip-path. It should make the corners rounded for me but for some reason only 1 of the corners does the effect perfectly.
This is the shape:
<svg height="500" width="500">
<path fill="#555555" d="M50,0 L450,0 Q500,0 500,50 L500,400 Q500,450 450,450 L200,450 L175,500 L150,450 L50,450 Q0,450 0,400 L0,50 Q0,0 50,0z" />
</svg>
This is what happens when i use it as a clip-path
body {
background: #555;
}
img {
clip-path: url(#svgPath);
-webkit-clip-path: url(#svgPath);
}
<svg height="0" width="0">
<defs>
<clipPath id="svgPath">
<path fill="#FFFFFF" d="M50,0 L450,0 Q500,0 500,50 L500,400 Q500,450 450,450 L200,450 L175,500 L150,450 L50,450 Q0,450 0,400 L0,50 Q0,0 50,0z" />
</clipPath>
</defs>
</svg>
<img src="https://dummyimage.com/500" />
It seems to work perfectly within FireFox but shows the corners aren't cut correctly in Chrome apart from the bottom right corner.
The default units for the clip-path is userSpaceOnUse and this seems to calculate the coordinates of the path with reference to the root element. This is the reason why the clip-path seems like it is producing an incorrect output. Nullifying the margin and padding on the root element or absolutely positioning the element (like in the below snippet) should solve the issue.
body {
background: #555;
}
img {
position: absolute;
top: 0px;
left: 0px;
clip-path: url(#svgPath);
-webkit-clip-path: url(#svgPath);
}
<svg height="0" width="0">
<defs>
<clipPath id="svgPath">
<path fill="#FFFFFF" d="M50,0 L450,0 Q500,0 500,50 L500,400 Q500,450 450,450 L200,450 L175,500 L150,450 L50,450 Q0,450 0,400 L0,50 Q0,0 50,0z" />
</clipPath>
</defs>
</svg>
<img src="http://lorempixel.com/500/500/" />
However, in a real life scenario the actual element that has to be clipped could be present anywhere within the body and hence I think it is a much better approach to use the objectBoundingBox as the units like in the below snippet:
body {
background: #555;
}
img {
clip-path: url(#svgPath);
-webkit-clip-path: url(#svgPath);
}
<svg height="0" width="0">
<defs>
<clipPath id="svgPath" clipPathUnits="objectBoundingBox">
<path fill="#FFFFFF" d="M0.1,0 L0.9,0 Q1,0 1,0.1 L1,0.8 Q1,0.9 0.9,0.9 L0.4,0.9 L0.35,1 L0.3,0.9 L0.1,0.9 Q0,0.9 0,0.8 L0,0.1 Q0,0 0.1,0z" />
</clipPath>
</defs>
</svg>
<img src="https://dummyimage.com/500" />
As mentioned in the question itself, this behavior is visible only in Chrome and not Firefox for reasons unknown to me. Firefox produces an output similar to the expected one even when (a) extra padding + margin is added to the body and (b) when the image itself is wrapped inside another container which also has padding + margin.
The only case where Firefox's output matches with Chrome is when a padding is added directly to the img tag itself. I believe this happens because padding is part of the element and thus affects the coordinates.
I'm trying to create a CSS animation for the fill color of a specific part of a SVG image. For that I'm using keyframes and an 'id' to link the animation and the SVG rectangle. You can see a working example here:
http://jsbin.com/deyaqo/3/
This works for most of the browsers except Safari (and maybe IE, I don't know). I'm not sure if this is because of my implementation or due to the lack of support from this vendor.
Thanks for your time !
You could use the animate element instead.
<svg id="logo" x="0" y="0" width="150" viewBox="12.304 3.974 74.952 22.051" enable-background="new 12.304 3.974 74.952 22.051">
<rect id="laukia"
x="56.74"
y="23.094"
width="17.895"
height="2.932"
fill="black" />
<animate xlink:href="#laukia"
attributeType="XML"
attributeName="fill"
from="red" to="rosybrown"
values="red; blue; green; teal; saddlebrown; peru; plum; rosybrown"
repeatCount="indefinite"
dur="5s" />
</svg>
Setting a background position works on Chrome, Safari and Firefox, but not on IE 8-11. What's wrong here?
DEMO on Dabblet
DEMO on Webdevout
.logo {
display: block;
width: 200px;
border: 2px solid red;
background: url("layout/logo.png") center right no-repeat; /* fallback image */
background-image: url('data:image/svg+xml;base64,...'), none; /* two bg to only use svg on supported browsers. IE 11 uses this image */
background-position: center right;
background-repeat: no-repeat;
background-size: auto 100%;
}
UPDATE:
IE seems to ignore background positioning on SVG images. Here's a WORKAROUND DEMO
I guess the best way of doing this with a guaranty of cross-browser working is by making the background image using a pattern and then set the attributes like x,y,width or height to position it as you want directly or later in jquery via the attr method for example: $("#img1").attr("width","500");
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="100" height="100">
<image xlink:href="layout/logo.png" x="0" y="0" width="100" height="100" />
</pattern>
</defs>
and set the pattern to fill the SVG path like this
<path fill="url(#img1)" id="my_svg" d="M5,50 l0,100 l100,0 l0,-100 l-100,0
M215,100
a50,50 0 1 1 -100,0 50,50 0 1 1 100,0
M265,50
l50,100 l-100,0 l50,-100
z"/>
or you can set the background in this very way but in the CSS like this
#my_svg{
fill:url(#img1);
}
There is also an alternative way which i do not recommend but may be the answer in some cases and that is the transform="translate(x,y)" for the image in pattern or the patternTransform="translate(x,y)" for the pattern which is quit like the css version if it..for example:
<pattern id="img1" patternUnits="userSpaceOnUse" width="100" height="100" patternTransform="translate(0,0)">
<image xlink:href="layout/logo.png" x="0" y="0" width="100" height="100" transform="translate(0,0)" />
</pattern>
anyway there is always good practice to know many different ways of doing something in our job to be able to survive ;-)