SVG Sprite with <use> xlink in CSS ::after - css

I’m using a SVG sprite like this in the body:
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="bars" width="1792" height="1792" viewBox="0 0 1792 1792">
<path d="M1664 1344v128q0 26-19 45t-45 19h-1408q-26 0-45-19t-19-45v-128q0-26 19-45t45-19h1408q26 0 45 19t19 45zm0-512v128q0 26-19 45t-45 19h-1408q-26 0-45-19t-19-45v-128q0-26 19-45t45-19h1408q26 0 45 19t19 45zm0-512v128q0 26-19 45t-45 19h-1408q-26 0-45-19t-19-45v-128q0-26 19-45t45-19h1408q26 0 45 19t19 45z"/>
</symbol>
</svg>
If I need the symbol, I call it like this:
<svg class="icon left bars" style="fill: #000;">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#bars"></use>
</svg>
Now I need this SVG in a CSS ::after. I know that you can use a SVG as background image in the ::after but it won’t work with use:
.element::after {
background: url('data:image/svg+xml;utf8,<svg class="icon left bars" style="fill: #000;"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#bars"></use></svg>') no-repeat;
//background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='61' height='41' fill='#000' stroke='none'><path d='M0,0 6,10 L12,0 L0,0 Z'></path></svg>") no-repeat;
content: "";
display: block;
height: 16px;
width: 16px;
}
Demo: JSFiddle
Is there anyone who got this working?

.element::before {background-image:url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%' viewBox='0 0 75.33 68.119'>\ <polygon fill-rule='evenodd' clip-rule='evenodd' fill='red' points='8.125,11.865 75.33,0 73.794,37.574 70.938,68.119 0,64.603 '/>\ </svg>"); content:""; display:inline-block; width:75.33px; height:68.119px;}
<div class="element"></div>
However it only works on non-IE browsers, a shame as you could turn it into a mixin in less/sass so you dont bloat your working css.
I got it from
https://codepen.io/AmeliaBR/details/xijuv
And also worth a read https://manu.ninja/inline-svg-how-i-learned-to-stop-worrying-and-love-gzip/
EDIT working in IE 11
See this answer CSS: Using raw svg in the URL parameter of a background-image in IE

Related

CSS background-image .SVG not animating on IOS

I have the following CSS class:
&.loading {
background: url(/svg/loading_animated/fff.svg) $actionColor no-repeat center;
}
This loads this SVG image:
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; background: none; display: block;" width="200" height="200" viewBox="0 0 100 100">
<circle cx="50" cy="50" fill="none" stroke="#fff" stroke-width="15" r="41" stroke-dasharray="193 66">
<animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0 50 50" to="360 50 50" dur="1.1s" repeatCount="indefinite"></animateTransform>
</circle>
</svg>
This works fine on desktop, but on iPhone/IOS, the animation does not work. When I navigate straight to the SVG, I do see the animation.
When I embed the SVG into my CSS class, it also animates:
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' style='margin: auto; background: none; display: block;' width='200' height='200' viewBox='0 0 100 100'> <circle cx='50' cy='50' fill='none' stroke='white' stroke-width='15' r='41' stroke-dasharray='193 66'><animateTransform attributeName='transform' attributeType='XML' type='rotate' from='0 50 50' to='360 50 50' dur='1.1s' repeatCount='indefinite'></animateTransform></circle></svg>") $actionColor no-repeat center;
That seems to be the solution, but I'd rather have it work with the URL (this fits my code better).
Is there a way to keep the SVG animated on iOS, while using it as a background-image?

Any way to use SVG Sprite from CSS?

HTML:
<svg>
<use xlink:href="/assets/images/icons-sprite.svg#icon-name"></use>
</svg>
SVG sprite:
<svg width="0" height="0" class="hidden">
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="icon-name">
<path ... fill="currentColor"></path>
</symbol>
</svg>
Is there any way to use SVG sprite from CSS
Like this
<div class=“icon”></div>
.icon {
background-image: “/assets/images/icons-sprite.svg#icon-name”
height: 30px
}
I’m using the technique for including SVGs described here whereby you create a doc that looks something like this…
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="arrow-left" viewBox="0 0 10 16">
<path d="M9.4 1.4L8 0 0 8l8 8 1.4-1.4L2.8 8z"/>
</symbol>
<symbol id="arrow-right" viewBox="0 0 10 16">
<path d="M0 14.6L1.4 16l8-8-8-8L0 1.4 6.6 8z"/>
</symbol>
</svg>
Include it in the top of your HTML and then insert the SVG icons in your markup like this…
<svg class="arrow-right">
<use xlink:href="#arrow-right" />
</svg>
It’s easy and works great. However, I’m trying to use the same icons in my CSS pseudo classes :before and :after using an empty content attribute and the SVG in the background. Something like this…
.title:after {
float: right;
width: 16px;
height: 10px;
content: "";
background: url('#arrow-right');
}

SVG styling problems with <use>

I'm trying to change, with CSS, the size and color of an SVG element that's being rendered with <use>. The SVG in question:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path fill="#000000" fill-rule="evenodd" d="<all the actual svg path info>" clip-rule="evenodd"/>
</svg>
I do not have permission to change the contents of the SVG itself.
The way I'm using the SVG:
<svg>
<use xlink:href="#myIcon"></use>
</svg>
I've fought with this for hours, read through a pretty comprehensive article on the subject, and I still haven't had any success. I've tried applying classes to both the use element and the outer svg element, as well as referencing the path element inside. I can't seem to do anything to override the provided styles. How can I change the width, height, and fill color with this arrangement?
For the size it's easy if you correctly set the viewBox and then you adjust the width/height.
For the coloration you can rely on blending mode since the color of the SVG is black.
.icon {
display: inline-block;
background: #fff;
position: relative;
}
.icon::after {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background:var(--c);
mix-blend-mode:lighten;
}
.icon>svg {
display: block;
}
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
<symbol id="myIcon">
<path fill="#000" d="M81,40.933c0-4.25-3-7.811-6.996-8.673c-0.922-5.312-3.588-10.178-7.623-13.844 c-2.459-2.239-5.326-3.913-8.408-4.981c-0.797-3.676-4.066-6.437-7.979-6.437c-3.908,0-7.184,2.764-7.979,6.442 c-3.078,1.065-5.939,2.741-8.396,4.977c-4.035,3.666-6.701,8.531-7.623,13.844C22.002,33.123,19,36.682,19,40.933 c0,2.617,1.145,4.965,2.957,6.589c0.047,0.195,0.119,0.389,0.225,0.568l26.004,43.873c0.383,0.646,1.072,1.04,1.824,1.04 c0.748,0,1.439-0.395,1.824-1.04L77.82,48.089c0.105-0.179,0.178-0.373,0.225-0.568C79.855,45.897,81,43.549,81,40.933z M49.994,11.235c2.164,0,3.928,1.762,3.928,3.93c0,2.165-1.764,3.929-3.928,3.929s-3.928-1.764-3.928-3.929 C46.066,12.997,47.83,11.235,49.994,11.235z M27.842,36.301c0.014,0,0.027,0,0.031,0c1.086,0,1.998-0.817,2.115-1.907 c0.762-7.592,5.641-13.791,12.303-16.535c1.119,3.184,4.146,5.475,7.703,5.475c3.561,0,6.588-2.293,7.707-5.48 c6.664,2.742,11.547,8.944,12.312,16.54c0.115,1.092,1.037,1.929,2.143,1.907c2.541,0.013,4.604,2.087,4.604,4.631 c0,1.684-0.914,3.148-2.266,3.958H25.508c-1.354-0.809-2.268-2.273-2.268-3.958C23.24,38.389,25.303,36.316,27.842,36.301z M50.01,86.723L27.73,49.13h44.541L50.01,86.723z" fill-rule="evenodd" clip-rule="evenodd"/>
</symbol>
</svg>
<!-- your code -->
<div class="icon" style="--c:red;">
<svg viewBox="0 0 100 125" width="100">
<use xlink:href="#myIcon"></use>
</svg>
</div>
<div class="icon" style="--c:green;">
<svg viewBox="0 0 100 125" width="150">
<use xlink:href="#myIcon"></use>
</svg>
</div>
<div class="icon" style="--c:blue;">
<svg viewBox="0 0 100 125" width="200">
<use xlink:href="#myIcon"></use>
</svg>
</div>
Save svg as a image with svg format then add the color and width or whatever you want to your img then add this to the html file as a img tag and display: none the svg code.
If you can't reach the html code then you can't do anything.

SVG fill with css variables

I am trying to use CSS variables in my SVG (which is set as a background image) for the fill color, but am having difficulty in getting it to work. It shows the default black, but when I inspect it I can see that the css variable is there and showing my desired color.
HTML
<div class="test">
Testing the css variable color
</div>
<div class="icon">
</div>
CSS
:root {
--primary-color: hsl(332, 61%, 78%);
}
div {
width: 100px;
height: 100px;
}
.test {
background: var(--primary-color);
}
.icon {
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' fill='var(--primary-color)' /%3E%3C/svg%3E");
}
Here is a codepen to check out!
I've seen CSS Variables being used in SVG here but I'm not sure if it's possible to do with background images? I'm new to both using SVG and CSS variables so I'm not sure if I'm doing something wrong... Would love some insight as to why it's not rendering the color properly!
Now you can include SVG as mask-image instead of background. Don't forget set background color from css variables for .icon block.
.icon {
background: var(--primary-color);
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' /%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' /%3E%3C/svg%3E");
}
You can check it in this CodePan
Here is information from Caniuse about mask-image
And here documentation about mask property
Okay here we go... I will first explain why it does not work and then I will show an alternative.
Why your approach doesn't work
In your example the svg is not part of the DOM. So you cannot use css to modify the attributes of the svg.
What you are doing is adding an inline-style to the svg in your url. Since the browser does not recognise --primary-color as a color it doesn't work.
An alternative approach
An alternative approach is to put the svg in the html and fake a background. I did this by absolute positioning the svg and moving it to the background with z-index.
Do note you will have to modify the svg or the positioning to place the background in the way you want. Normally you would use background-size for this. But with some effort you can replicate this behaviour within the svg or position it better by using css.
:root {
--primary-color: hsl(332, 61%, 78%);
}
div {
width: 100px;
height: 100px;
}
.test {
background: var(--primary-color);
}
.icon{ /*postion relative for absolute positioning to work*/
position: relative;
}
.icon>svg{
position: absolute;
top: 0px;
right: 0px;
left: 0px;
bottom: 0px;
z-index: -1;
}
.icon>svg>path{ /*target the image with css*/
fill: var(--primary-color);
}
<div class="test">
Testing the css variable color
</div>
<div class="icon">
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129' id='background'><path d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z'/> </svg>
<p>Text goes here...</p>
</div>
Don't include svg as background, by doing that you don't have control over it's fill, instead try adding it inline in html and via css you can control the fill via css variable, please check the working example below, hope it helps :)
:root {
--primary-color: hsl(332, 61%, 78%);
}
div {
width: 100px;
height: 100px;
}
.test {
background: var(--primary-color);
}
.icon {
color: var(--primary-color);
fill: currentColor;
width: 64px;
height: 64px;
}
<div class="test">
Testing the css variable color
</div>
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 129 129">
<path d="m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z"/>
</svg>
Using the <symbol> tag and CSS variables
CSS variables inherit the fill property. Therefore, it is possible to assign (declare) a variable inside the <symbol> tag, the value of which can be subsequently changed many times for each instance of the svg element.
<symbol id="monstr">
<rect width="100%" height="100%" fill="transparent" />
<path id="face" fill="var(--color-face)" d="M15.4,34.1L24,37l8.6-2.9c1.9-0.6,3-2.6,2.6-4.6L33,20H15l-2.2,9.5C12.3,31.5,13.5,33.5,15.4,34.1z"/>
<path id="nose" fill="var(--color-nose)" d="M29,30l-3-3h-4l-3,3v7c0,1.1,0.9,2,2,2h6c1.1,0,2-0.9,2-2V30z"/>
Each path, circle, ellips, etc. can be assigned its own variable fill = "var (- color-face)" for fill and then change its value in the external style sheet:
.monstr-colors { --color-face: #7986CB; --color-nose: #9FA8DA; }
This technique creates powerful and flexible styling options for multicolor svg.
For example, for one state of an icon, we can assign one color scheme, and with : hover, assign a different color set to the same icon.
.monstr-colors {
--color-face: #7986CB;
--color-nose: #9FA8DA;
}
.monstr-colors:hover {
--color-face: #3F8B4D;
--color-nose: #58C46C;
)
Below is an example, according to your taste, the color scheme of the image is easily created and changed:
.monstr-colors {
--color-face: #7986CB;
--color-nose: #9FA8DA;
--color-hair-right:#3949AB;
--color-hair-right2:#3949AB;
--color-hair-left:#3949AB;
--color-hair-left2:#3949AB;
--color-eye-right:#1A237E;
--color-pupil-right:#77006B;
--color-eye-left:#1A237E;
--color-pupil-left:#77006B;
--color-ellipse1:#9FA8DA;
--color-ellipse2:#7986CB;
--color-ellipse3:#C5CAE9;
}
.monstr-colors:hover {
--color-face: #3F8B4D;
--color-nose: #58C46C;
--color-hair-right:gold;
--color-hair-right2:#FFBB00;
--color-hair-left:gold;
--color-hair-left2:#FFBB00;
--color-eye-right:#77006B;
--color-pupil-right:#FF4151;
--color-eye-left:#77006B;
--color-pupil-left:#FF4151;
--color-ellipse1:#FFDD00;
--color-ellipse2:#C1A700;
--color-ellipse3:#FFEE7D;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="192" height="192" viewBox="0 0 48 48" >
<symbol id="monstr">
<rect width="100%" height="100%" fill="transparent" />
<path id="face" fill="var(--color-face)" d="M15.4,34.1L24,37l8.6-2.9c1.9-0.6,3-2.6,2.6-4.6L33,20H15l-2.2,9.5C12.3,31.5,13.5,33.5,15.4,34.1z"/>
<path id="nose" fill="var(--color-nose)" d="M29,30l-3-3h-4l-3,3v7c0,1.1,0.9,2,2,2h6c1.1,0,2-0.9,2-2V30z"/>
<path id="hair-right" fill="var(--color-hair-right)" d="M31,7c-0.5,0-1,0.4-1,1c0,0,0,0,0,0c-0.4,0-0.8,0.2-0.9,0.6c-0.2,0.5,0,1.1,0.6,1.3 C30,10.1,40,14.4,40,32.4V37c0,0.6,0.4,1,1,1s1-0.4,1-1v-4.6c0-14.4-6.1-20.7-9.5-23.1C35.9,10.3,44,14.7,44,34c0,0.6,0.4,1,1,1 s1-0.4,1-1C46,7.7,31.6,7,31,7z"/>
<path id="hair-right2" fill="var(--color-hair-right2)" d="M29.5,10.1c-0.5-0.3-1.1-0.1-1.3,0.4c-0.3,0.5-0.1,1.1,0.4,1.4c0.1,0,7.5,4.3,7.5,20.1v8c0,0.6,0.4,1,1,1 s1-0.4,1-1v-8C38,14.9,29.8,10.3,29.5,10.1z"/>
<path id="hair-left" fill="var(--color-hair-left)" d="M18.4,9.9c0.5-0.2,0.8-0.8,0.6-1.3C18.8,8.2,18.4,8,18,8c0,0,0,0,0,0c0-0.6-0.5-1-1-1C16.4,7,2,7.7,2,34 c0,0.6,0.4,1,1,1s1-0.4,1-1c0-19.6,8.1-23.8,11.6-24.7C12.2,11.6,6,17.9,6,32.4V37c0,0.6,0.4,1,1,1s1-0.4,1-1v-4.6 C8,14.4,18,10.1,18.4,9.9z"/>
<path id="hair-left" fill="var(--color-hair-left2)" d="M18.5,10.1C18.2,10.3,10,14.9,10,32v8c0,0.6,0.4,1,1,1s1-0.4,1-1v-8c0-15.8,7.4-20.1,7.5-20.1 c0.5-0.3,0.7-0.9,0.4-1.4C19.6,10,19,9.9,18.5,10.1z"/>
<path id="eye-right" fill="var(--color-eye-right)" d="M25,24.9c0,0,0.2,1.3,0.6,1.7s3.3,2.5,5.9-0.9c1.2-1.5,0.6-3.8,0.6-3.8S29.4,24.1,25,24.9z"/>
<circle id="pupil-right" cx="28" cy="25" r="1.5" fill="var(--color-pupil-right)" />
<path id="eye-left" fill="var(--color-eye-left)" d="M15.8,21.8c0,0-0.6,2.3,0.6,3.8c2.6,3.4,5.5,1.4,5.9,0.9c0.4-0.4,0.6-1.7,0.6-1.7 C18.6,24.1,15.8,21.8,15.8,21.8z"/>
<circle id="pupil-left" fill="var(--color-pupil-left)" cx="20" cy="25" r="1.5" fill="red" />
<ellipse id="ellipse1" fill="var(--color-ellipse1)" cx="24" cy="15" rx="12" ry="10"/>
<ellipse id="ellipse2" fill="var(--color-ellipse2)" cx="24" cy="13.8" rx="10" ry="7.8"/>
<ellipse id="ellipse3" fill="var(--color-ellipse3)" cx="24.2" cy="12.2" rx="8" ry="6.2"/>
</symbol>
<svg class="monstr-colors">
<use xlink:href="#monstr" />
</svg>
</svg>
Below is a combined example with styling three instances of the same image.
Each instance of the created <use xlink: href = "# monstr"/> has its own color scheme, which is linked to the nested svg class.
<div class="container">
<svg class="color-monstr">
<use xlink:href="#monstr" transform="scale(3)" />
</svg>
</div>
<div class="container2">
<svg class="color-monstr2">
<use xlink:href="#monstr" transform="scale(2)" />
</svg>
</div>
<div class="container3">
<svg class="color-monstr3">
<use xlink:href="#monstr" transform="scale(3)" />
</svg>
</div>
With :hover, each instance replaces the color scheme with the color scheme of the adjacent instance.
.parent {
position:relative;
}
.container {
width:400px;
height:400px;
position:absolute;
top:0;
}
.container2 {
position: absolute;
top:0;
left:150px;
}
.container3 {
position: absolute;
top:0;
left:240px;
}
.color-monstr {
--color-ears: #459E48;
--color-horn-right: #388E3C;
--color-horn-left: #388E3C;
--color-face:#4CAF50;
--circle-horn-left:#8BC34A;
--circle-horn-right:#8BC34A;
--eye-right:#FFF9C4;
--eye-left:#FFF9C4;
--pupil-right:#263238;
--pupil-left:#263238;
--mouth:#173027;
}
.color-monstr:hover {
--color-ears: #504F7A;
--color-horn-right: #504FF6;
--color-horn-left: #504FF6;
--color-face:#807FC4;
--circle-horn-left:#FF00AE;
--circle-horn-right:#FF00AE;
--eye-right:#FFDBF4;
--eye-left:#FFDBF4;
--pupil-right:#263238;
--pupil-left:#263238;
--mouth:#FFDBF4;
}
.color-monstr2 {
--color-ears: #504F7A;
--color-horn-right: #504FF6;
--color-horn-left: #504FF6;
--color-face:#807FC4;
--circle-horn-left:#FF00AE;
--circle-horn-right:#FF00AE;
--eye-right:#FFDBF4;
--eye-left:#FFDBF4;
--pupil-right:#263238;
--pupil-left:#263238;
--mouth:#FFDBF4;
}
.color-monstr2:hover {
--color-ears: #770051;
--color-horn-right: #388E3C;
--color-horn-left: #388E3C;
--color-face:#FFDD00;
--circle-horn-left:#D0FF00;
--circle-horn-right:#A0C400;
--eye-right:#FFF9C4;
--eye-left:#FFF9C4;
--pupil-right:#263238;
--pupil-left:#263238;
--mouth:#FFF9C4;
}
.color-monstr3 {
--color-ears: #770051;
--color-horn-right: #388E3C;
--color-horn-left: #388E3C;
--color-face:#FFDD00;
--circle-horn-left:#D0FF00;
--circle-horn-right:#A0C400;
--eye-right:#FFF9C4;
--eye-left:#FFF9C4;
--pupil-right:#263238;
--pupil-left:#263238;
--mouth:#FFF9C4;
}
.color-monstr3:hover {
--color-ears: #459E48;
--color-horn-right: #388E3C;
--color-horn-left: #388E3C;
--color-face:#4CAF50;
--circle-horn-left:#8BC34A;
--circle-horn-right:#8BC34A;
--eye-right:#FFF9C4;
--eye-left:#FFF9C4;
--pupil-right:#263238;
--pupil-left:#263238;
--mouth:#173027;
}
<div class="parent">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48" >
<symbol id="monstr">
<path id="ears"
fill="var(--color-ears)"
d="M12,31c-2.3,0-3.7-3.2-4-5c0.7-1.3,3.3-2,4-2c5.7-2.4,17.8-2.9,24,0c0.7,0,3.3,0.7,4,2c-0.3,1.8-1.7,5-4,5 C33.6,32.8,14.7,34.2,12,31z"/>
<g>
<path id="horn-right"
fill="var(--color-horn-right)" d="M40,8c-0.6,0-1,0.4-1,1c0,2.7-3.3,5-6,5c-0.6,0-1,0.4-1,1s0.4,1,1,1c3.7,0,8-3.1,8-7C41,8.4,40.6,8,40,8z"/>
<path id="horn-left"
fill="var(--color-horn-left)" d="M8,8c0.6,0,1,0.4,1,1c0,2.7,3.3,5,6,5c0.6,0,1,0.4,1,1s-0.4,1-1,1c-3.7,0-8-3.1-8-7C7,8.4,7.4,8,8,8z"/>
</g>
<path id="face"
fill="var(--color-face)" d="M12,31v-7c0-9.2,5.3-16,12-16s12,6.8,12,16v7c-1.2,5.6-7,12-12,12S13.2,36.6,12,31z"/>
<g>
<circle id="circle-horn-left" fill="var(--circle-horn-left)" cx="8" cy="9" r="3"/>
<circle id="circle-horn-right" fill="var(--circle-horn-right)" cx="40" cy="9" r="3"/>
</g>
<g>
<ellipse id="eye-right" fill="var(--eye-right)" cx="29" cy="26" rx="2" ry="4"/>
<ellipse id="eye-left" fill="var(--eye-left)" cx="19" cy="26" rx="2" ry="4"/>
</g>
<g>
<circle id="pupil-right" fill="var(--pupil-right)" cx="29" cy="27" r="1"/>
<circle id="pupil-left" fill="var(--pupil-left)" cx="19" cy="27" r="1"/>
</g>
<path id="mouth" fill="var(--mouth)" d="M24,33c-4,0-5.8,3-5.8,3s2.6,0,5.8,0s5.8,0,5.8,0S28,33,24,33z"/>
</symbol>
</svg>
<div class="container">
<svg class="color-monstr">
<use xlink:href="#monstr" transform="scale(3)" />
</svg>
</div>
<div class="container2">
<svg class="color-monstr2">
<use xlink:href="#monstr" transform="scale(2)" />
</svg>
</div>
<div class="container3">
<svg class="color-monstr3">
<use xlink:href="#monstr" transform="scale(3)" />
</svg>
</div>
</div>
Here is a better way or how I color my SVGs. As Inline SVGs have a bitter taste on readability of the rest of the code and adding them as background or mask, they can not be colored by a dark theme switch. Include them externally and load them inside an html object:
<object id="background-anim" class="svg" aria-hidden="true" data="./media/Background-fluid-lines-anim.svg" type="image/svg+xml"></object>
This SVG is now added externally.
To set the colors you need to set for the desired colors a class inside of the SVG.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080">
<defs>
<style>
.svg-element__clrText{
fill:rgb(255,255,255);
}
.svg-element__clrPrimary{
fill:rgb(155,155,155);
}
.svg-element__clrBackground{
fill:rgb(55,55,55);
}
</style>
</defs>
<path class="svg-element__clrText"></path>
</svg>
In your paths, you will set those classes to the desired elements that should adapt colors.
Now you will manipulate those fill values with JavaScript and add the correct CSS Custom Porperties:
/*Optional: Listening to the clicked switch if you have one*/
document.querySelectorAll('.theme-toggle').forEach((toggle) => {
toggle.addEventListener('click', () => themeToggle);
});
window.themeToggle = function themeToggle() {
document.documentElement.classList.toggle('darkMode');
//this .darkmode{} class changes the values of my variables set to white mode in the ':root{}' in the css file
loadTheme()
}
function loadTheme(){
/* For loading more than just the colors */
loadThemeIcon();
loadSVGColors();
}
/* Now here comes the important part */
function loadSVGColors() {
const svgs = document.querySelectorAll('.svg'); //getting NodeList of SVGs
const style = getComputedStyle(document.body), //getting CSS variables inside of js
svgs.forEach(svg => {
element = svg.contentDocument; //get the actual svg that is loaded into the object element
const clrText = svg.querySelectorAll('.svg-element__textClr'), //searching inside of the SVG after my classes
textClr.forEach(element => { //NodeList to Array
element.style.fill = style.getPropertyValue('--clr-text');//whatever variables you have set or you can toggle a class that has only this css variable inside
});
/* [...and so on]*/
const primeClr = element.querySelectorAll('.svg-element__primeClr');
primeClr.forEach(e => {
e.style.fill = style.getPropertyValue('--clr-primary');
});
});
}
I guess there is a better performance when you add the SVGs inside the HTML with fill: var(--clr-text), however after having 50kb of code per SVG leads to lots of scrolling
I know this goes further than the question but I would have been glad to find this before under these SO posts.
I stumbled upon this for a very similar case and want to share a completely different approach.
Use the css multi background feature (MDN Docs)
First you need to make the part of your svg that you want to color transparent with fill="transparent"
Now you can just specify multiple backgrounds, where one can be your variable, for example
body {
background: url('path/to/your/svg/or/data-url'), var(--background);
}
If you need to control only one color, you can use currentColor keyword in the fill property and change it through css color property.
.icon {
color: var(--primary-color);
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' fill='currentColor' /%3E%3C/svg%3E");
}
<path class="class-name"/>
:root {
--color : #123456;
}
.class-name {
fill : var(--color)
}
try this

Firefox and responsive SVG

Here is a thing.
I have a 700x700px image that i would need to mask with SVG.
For Chrome and Safari i did that by using -webkit-mask-box-image with external SVG and it works properly.
For Firefox, i used clip-path property, and again, it functions properly.
The responsive part is problem.On Chrome&Safari, that part is working nicely, but on Firefox only the main image is resized, mask stays the same.
I am a complete newbie at this and i tried tons of solutions that i found online and i really couldn’t make it work.
<style>
body {
background: yellow;
}
.img-mask {
-webkit-mask-box-image: url('http://imgh.us/mask_3.svg');
mask-border: url('http://imgh.us/mask_3.svg');
clip-path: url(#mask);
}
</style>
<img src="http://gto-live.com/wp-content/uploads/2015/04/charm-elegance-colorful-sofa-living-room-decor-718x718.jpg" class="img-mask">
enter code here
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid" width="700" height="700" viewBox="0 0 700 700">
<clipPath id="mask">
<path d="M718.004,358.999 C718.004,160.726 557.272,-0.007 358.998,-0.007 C160.725,-0.007 -0.007,160.726 -0.007,358.999 C-0.007,557.272 160.725,718.005 358.998,718.005 C557.272,718.005 718.004,557.272 718.004,358.999 Z"/>
</clipPath>
</svg>
Any help would really really be gratefully appreciated!
Fiddle can be found here https://jsfiddle.net/y7zaw4bz/1/
You need to use objectBoundingBox units (and make the path run from 0 to 1) e.g.
body {
background: yellow;
}
img {
width: 100%;
}
.img-mask {
-webkit-mask-box-image: url('http://imgh.us/mask_3.svg');
mask-border: url('http://imgh.us/mask_3.svg');
clip-path: url(#mask);
}
<img src="http://gto-live.com/wp-content/uploads/2015/04/charm-elegance-colorful-sofa-living-room-decor-718x718.jpg" class="img-mask">
<svg preserveAspectRatio="xMidYMid" width="700" height="700" viewBox="0 0 700 700">
<clipPath id="mask" clipPathUnits="objectBoundingBox">
<path transform="scale(0.0014)" d="M718.004,358.999 C718.004,160.726 557.272,-0.007 358.998,-0.007 C160.725,-0.007 -0.007,160.726 -0.007,358.999 C-0.007,557.272 160.725,718.005 358.998,718.005 C557.272,718.005 718.004,557.272 718.004,358.999 Z"/>
</clipPath>
</svg>
Here I've scaled the path to correct the units 0.0014 is roughly 1 / 700

Resources