The initial SVG figure with pattern:
<svg width="200" height="200" viewBox="0 0 100 100">
<defs>
<pattern id="img-dotted-dots" x="0" y="0" height=".08" width="7.69%">
<circle cx="2" cy="2" fill="white" r="0.8"></circle>
</pattern>
<mask id="img-dotted-mask">
<rect width="100" height="100" fill="url(#img-dotted-dots)"></rect>
</mask>
</defs>
<path d="M0 0 H 100 V 100 H 0 Z" mask="url(#img-dotted-mask)" fill="#1063B1"></path>
</svg>
Need to achieve:
One instance of the SVG figure with pattern for refferencing with CSS as clip-path.
I have tried to create SVG clipPath element and bind to CSS clip-path by this way
.figure {
width: 300px;
height: 300px;
clip-path: url(#img-dotted-clip-path);
background-color: #1063B1;
}
<div class="figure"></div>
<svg width="0" height="0" viewBox="0 0 100 100">
<defs>
<clipPath
clipPathUnits="objectBoundingBox"
id="img-dotted-clip-path">
<pattern
patternUnits="objectBoundingBox"
patternContentUnits="objectBoundingBox"
x="0" y="0" height="0.1" width="0.1">
<circle cx="0" cy="0" fill="white" r="0.5"></circle>
</pattern>
</clipPath>
</defs>
</svg>
Nothing happens.
Expected result - the same as the previous snippet.
For comparing:
If I use SVG rect - CSS clip-path works.
If pattern - doesn't
.figure {
width: 300px;
height: 300px;
clip-path: url(#img-dotted-clip-path);
background-color: #1063B1;
}
<div class="figure"></div>
<svg width="0" height="0" viewBox="0 0 100 100">
<defs>
<clipPath
clipPathUnits="objectBoundingBox"
id="img-dotted-clip-path">
<rect width="1" height="1"></rect>
</clipPath>
</defs>
</svg>
The only things that are valid inside a clip path are:
Shape elements (‘circle’, ‘ellipse’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’)
‘text’
‘use’
Plus you can use animation elements etc to animate the clip path. However, only the shapes of those elements are used. Effects such as patterns, filters, etc are ignored.
The only way you could get the effect you want to work as a clipping path would be to add numerous <circle> elements to your <clipPath>.
<clipPath>
<circle>
<circle>
<circle>
<circle>
... etc ...
</clipPath>
But you could use a mask instead. Masks allow patterns.
.figure {
width: 300px;
height: 300px;
-webkit-mask: url(#img-dotted-mask);
mask: url(#img-dotted-mask);
background-color: #1063B1;
}
<p>This only works in Firefox</p>
<div class="figure"></div>
<svg width="0" height="0">
<defs>
<pattern id="img-dotted-pattern"
viewBox="0 0 1 1"
patternUnits="userSpaceOnUse" x="0" y="0" width="20" height="20">
<rect width="1" height="1" fill="black"/>
<circle cx="0.5" cy="0.5" fill="white" r="0.15"></circle>
</pattern>
<mask id="img-dotted-mask">
<rect width="2000" height="2000" fill="url(#img-dotted-pattern)"/>
</mask>
</defs>
</svg>
However inline SVG masks applied to HTML elements, like my example above, only work in Firefox. To get an SVG mask to work in Chrome, you would need to use mask or mask-image with an external or Data URL (as Temani has done in their answer).
You can recreate the same thing using mask combined with radial-gradient
.figure {
width: 300px;
height: 300px;
background:linear-gradient(to right,red,#1063B1);
/*radius here size here*/
-webkit-mask:radial-gradient(3px, #fff 97%,transparent 100%) 0 0/20px 20px;
mask:radial-gradient(3px, #fff 97%,transparent 100%) 0 0/20px 20px;
}
body {
background:#f2f2f2;
}
<div class="figure"></div>
Or consider the SVG inside the mask property. Make sure to escape the # and correctly set the viewbox and width/height to have a perfect repeat
.figure {
width: 300px;
height: 300px;
background:linear-gradient(to right,red,#1063B1);
-webkit-mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200" height="192" viewBox="0 0 100 90"><defs><pattern id="img-dotted-dots" x="0" y="0" height=".08" width="7.69%"><circle cx="2" cy="2" fill="white" r="0.8"></circle></pattern><mask id="img-dotted-mask"><rect width="100" height="100" fill="url(%23img-dotted-dots)"></rect></mask></defs><path d="M0 0 H 100 V 100 H 0 Z" mask="url(%23img-dotted-mask)" fill="%231063B1"></path></svg>');
mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200" height="192" viewBox="0 0 100 90"><defs><pattern id="img-dotted-dots" x="0" y="0" height=".08" width="7.69%"><circle cx="2" cy="2" fill="white" r="0.8"></circle></pattern><mask id="img-dotted-mask"><rect width="100" height="100" fill="url(%23img-dotted-dots)"></rect></mask></defs><path d="M0 0 H 100 V 100 H 0 Z" mask="url(%23img-dotted-mask)" fill="%231063B1"></path></svg>');
}
body {
background:#f2f2f2;
}
<div class="figure"></div>
I'm trying to change the fill colour on an SVG symbol when it is inside a <use> element. Because there are going to be multiple instances of the symbol on the page, I can't do this is the <symbol> element, because the different instances of <use> will be different colours.
I've can't seem to get it work though. In the example below I would like to the bottom instance to be a blue twitter icon.
In the CSS I've done #bottom-twitter svg path {fill:blue;} which doesn't work. And I can't seem to get anything to work.
Any help would be amazing.
#box1 {
height: 5rem;
width: 5rem;
}
/* NOT WORKING */
#bottom-twitter svg path {
fill:blue;
}
<svg id="twitter" style="display: none;">
<defs>
<symbol id="twitter-symbol" viewBox="0 0 19.19 15.95">
<path id="twitter-path" d="M19.19,1.92a8.76,8.76,0,0,1-2.28.64A3.9,3.9,0,0,0,18.63.32a6.87,6.87,0,0,1-2.52,1A3.87,3.87,0,0,0,13.23,0,4,4,0,0,0,9.32,4,3.41,3.41,0,0,0,9.44,5,11,11,0,0,1,1.32.72a4.29,4.29,0,0,0-.52,2A4,4,0,0,0,2.56,6.12,3.61,3.61,0,0,1,.76,5.6v0a4,4,0,0,0,3.16,4,4.35,4.35,0,0,1-1,.16,4.9,4.9,0,0,1-.76-.08,4,4,0,0,0,3.68,2.8A7.79,7.79,0,0,1,.92,14.19a6.78,6.78,0,0,1-.92,0A10.83,10.83,0,0,0,6,16c7.24,0,11.19-6.16,11.19-11.47V4a6.83,6.83,0,0,0,2-2">
</path>
</symbol>
</defs>
</svg>
<div class="box" id="box1">
<svg id="top-twitter" viewBox="0 0 19.19 15.95">
<use xlink:href="#twitter-symbol"/>
</svg>
<svg id="bottom-twitter" viewBox="0 0 19.19 15.95">
<use xlink:href="#twitter-symbol"/>
</svg>
</div>
The problem is the fill="#000" in the svg path. Remove that or just change it to be the color you want.
#box1 {
height: 5rem;
width: 5rem;
}
/* NOT WORKING */
#bottom-twitter {
fill: blue;
}
<svg id="twitter" style="display: none;">
<defs>
<symbol id="twitter-symbol" viewBox="0 0 19.19 15.95">
<path id="twitter-path" d="M19.19,1.92a8.76,8.76,0,0,1-2.28.64A3.9,3.9,0,0,0,18.63.32a6.87,6.87,0,0,1-2.52,1A3.87,3.87,0,0,0,13.23,0,4,4,0,0,0,9.32,4,3.41,3.41,0,0,0,9.44,5,11,11,0,0,1,1.32.72a4.29,4.29,0,0,0-.52,2A4,4,0,0,0,2.56,6.12,3.61,3.61,0,0,1,.76,5.6v0a4,4,0,0,0,3.16,4,4.35,4.35,0,0,1-1,.16,4.9,4.9,0,0,1-.76-.08,4,4,0,0,0,3.68,2.8A7.79,7.79,0,0,1,.92,14.19a6.78,6.78,0,0,1-.92,0A10.83,10.83,0,0,0,6,16c7.24,0,11.19-6.16,11.19-11.47V4a6.83,6.83,0,0,0,2-2" >
</path>
</symbol>
</defs>
</svg>
<div class="box" id="box1">
<svg id="top-twitter" viewBox="0 0 19.19 15.95">
<use xlink:href="#twitter-symbol"/>
</svg>
<svg id="bottom-twitter" viewBox="0 0 19.19 15.95">
<use xlink:href="#twitter-symbol"/>
</svg>
</div>
On an element with a background (image or solid color don't really matter):
<header id="block-header"></header>
I am trying to apply a clip-path using SVG. To achieve this, I am putting SVG inline into the same element like this:
<header id="block-header">
…
<svg width="100%" height="100%" viewBox="0 0 4000 1696" preserveAspectRatio="none">
<defs>
<clipPath id="myClip">
<path d="M0 1568.18V0h4000v1568.18S3206.25 1696 2000 1696C984.37 1696 0 1568.18 0 1568.18z"/>
</clipPath>
</defs>
</svg>
…
</header>
You can run the code snippet below or check the JSFiddle. You can see original SVG image (in black) put inline, having curviness along the bottom and being responsive. In contrast, the red rectangle shows the same image applied (or, rather, not applied) as a clip-path.
I guess I misunderstand either viewBox or preserveAspectRatio attributes though can not find what is exactly wrong here. Any help would be appreciated.
#block-header {
background: Red;
min-height: 100px;
-webkit-clip-path: url(#myClip);
clip-path: url(#myClip);
}
<h1>SVG image</h1>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100" viewBox="0 0 4000 1696" preserveAspectRatio="none"><path d="M0 1568.18V0h4000v1568.18S3206.25 1696 2000 1696C984.37 1696 0 1568.18 0 1568.18z"/></svg>
<h1><code>clip-path</code> using the same SVG</h1>
<header id="block-header">
<svg width="100%" height="100" viewBox="0 0 4000 1696" preserveAspectRatio="none">
<defs>
<clipPath id="myClip">
<path d="M0 1568.18V0h4000v1568.18S3206.25 1696 2000 1696C984.37 1696 0 1568.18 0 1568.18z"/>
</clipPath>
</defs>
</svg>
</header>
References to SVG clip paths are to the clip path definitions themselves and the dimensions or other attributes of the <svg> are meaningless in this context.
What is happening in your example is that you are applying a 4000 px wide clip path to your header. Which is probably only of the order of 900 px wide. So the curvature isn't visible.
If you want a responsive clip path, you should define it using clipPathUnits="objectBoundingBox".
#block-header {
background: Red;
min-height: 100px;
-webkit-clip-path: url(#myClip);
clip-path: url(#myClip);
}
<h1>SVG image</h1>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100" viewBox="0 0 1 1" preserveAspectRatio="none"><path d="M0,0 1,0 1,0.9 C 1,0.9, 0.77,1, 0.5,1 0.23,1, 0,0.9,0,0.9z"/></svg>
<h1><code>clip-path</code> using the same SVG</h1>
<header id="block-header">
<svg width="0" height="0">
<defs>
<clipPath id="myClip" clipPathUnits="objectBoundingBox">
<path d="M0,0 1,0 1,0.9 C 1,0.9, 0.77,1, 0.5,1 0.23,1, 0,0.9,0,0.9z"/>
</clipPath>
</defs>
</svg>
</header>
Fiddle here