svg: styling a path within <use> - css

I'm trying to use CSS to style the fill of a specific <path> within a <symbol>. I've assigned fill:inherit to the path in the symbol <defs> and I can query the <use> instances of the symbol within the SVG DOM, but I can't seem to access that path within these instances. I looked into inherit for the CSS and currentColor for the fill of the <path> but no luck. Any help is appreciated.
<svg>
<defs>
<style>
symbol#DateCard path.purple {
fill:inherit;
}
use[*|href="#DateCard"] path.purple{
fill:#ff0095;
transition:fill .6s;
}
use[*|href="#DateCard"] path.purple:hover{
path:#ff0000;
}
</style>
<symbol id="DateCard">
<path class="purple" fill="currentColor" d="..."/>
</symbol>
</defs>
<use xlink:href="#DateCard"/>
<svg>
I can query the path within symbol, but when I query the specific paths within a <use> instance, this returns an empty NodeList:
document.querySelectorAll('use[*|href="#DateCard"] path.purple')

Styling inside the shadow DOM needs to be done inside the shadow DOM.
What I learned from Styling SVG Content with CSS | Codrops is that CSS variables are very useful in this case. So, here I created different ways of styling: using a style attribute and style element inside the symbol in combination with CSS variables from the "outside" of the symbol.
.card1 {
--path1-color: #0099CC;
--path2-color: #FFDF34;
}
.card2 {
--path1-color: #00008B;
--path2-color: #FF8C00;
}
.card2:hover {
--path1-color: #00BFFF;
}
<svg viewBox="0 0 200 100" width="400">
<defs>
<symbol id="DateCard">
<style>
.path2 {
fill: var(--path2-color);
transition: fill 1s;
}
.path2:hover {
fill: #800000;
}
</style>
<path class="path1" style="fill: var(--path1-color);transition: fill .6s;" d="M20 40 a 20 20 0 1 1 1 0"/>
<path class="path2" d="M40 60 a 20 20 0 1 1 1 0"/>
</symbol>
</defs>
<use href="#DateCard" class="card1"/>
<use href="#DateCard" class="card2" transform="translate(80 0)"/>
<svg>
Update
OP ask if the hover effect can be achieved using attributes in SVG. An alternative to the :hover pseudo class would be an animation started by the mouse entering and leaving the animated element. Unfortunately it is not as flexible as CSS -- it is difficult to style <animate>.
Here is an example on animating the second <path> in the symbol:
.card1 {
--path1-color: #0099CC;
--path2-color: #FFDF34;
}
.card2 {
--path1-color: #00008B;
--path2-color: #FF8C00;
}
.card2:hover {
--path1-color: #00BFFF;
}
<svg viewBox="0 0 200 100" width="400">
<defs>
<symbol id="DateCard">
<style>
.path2 {
fill: var(--path2-color);
}
</style>
<path class="path1" style="fill: var(--path1-color);transition: fill .6s;" d="M20 40 a 20 20 0 1 1 1 0"/>
<path class="path2" d="M40 60 a 20 20 0 1 1 1 0">
<animate attributeName="fill" dur="1s" values="#FF8C00;#800000" begin="mouseenter" fill="freeze" />
<animate attributeName="fill" dur="1s" from="#800000" to="#FF8C00" begin="mouseleave" fill="freeze" />
</path>
</symbol>
</defs>
<use href="#DateCard" class="card1"/>
<use href="#DateCard" class="card2" transform="translate(80 0)"/>
<svg>

Related

Why isn't the style tag in this SVG affecting elements?

I have a simple SVG with a single element, that has a fill of red:
<svg width="100" height="60" viewBox="0 0 100 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill="red" d="M4.93141 44.3745H2.8013V59.6912H4.93141V44.3745Z"/>
</svg>
I have added a stylesheet, and made the element use the class, but the element is not green per the code below:
<svg width="100" height="60" viewBox="0 0 100 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<style type="text/css" >
.foreground {
fill: "green";
}
</style>
<path class="foreground" d="M4.93141 44.3745H2.8013V59.6912H4.93141V44.3745Z"/>
</svg>
Why is the inline style not affecting the element with the class?
I have tried various combinations of CDATA, <defs> etc (per various examples) and haven't found a solution so far.
Because there is no need for the double quote around green.
<svg width="100" height="60" viewBox="0 0 100 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<style type="text/css" >
.foreground {
fill: green;
}
</style>
<path class="foreground" d="M4.93141 44.3745H2.8013V59.6912H4.93141V44.3745Z"/>
</svg>

SVG filter not visible when using custom viewBox

Why is setting an svg viewBox to say 0 0 1 1 causing my filter to disappear? I also tried playing around with x, y, height, and width attributes as well as changing primitiveUnits attribute, nothing did work. Any help would be appreciated.
svg {
border: 1px solid red;
height: 100px;
width: 100px;
}
svg circle {
fill: black;
}
<html>
<body>
<svg viewBox="0 0 1 1">
<defs>
<filter id="halo1">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
</defs>
<circle cx="50%" cy="50%" r="25%" filter="url(#halo1)"></circle>
</svg>
<svg>
<defs>
<filter id="halo2">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
</defs>
<circle cx="50%" cy="50%" r="25%" filter="url(#halo2)"></circle>
</svg>
</body>
</html>
Fiddle playground: https://jsfiddle.net/6x34urzg/14/
When the image is scaled from 1x1 (the viewBox="0 0 1 1") to 100x100 px the standard deviation (stdDeviation="3") is also scaled. The circle with the filter is still there but 100 time too big.
If you set the standard deviation to 1/100 (stdDeviation=".03") you will get the same result as the other SVG.
svg {
border: 1px solid red;
height: 100px;
width: 100px;
}
svg circle {
fill: black;
}
<html>
<body>
<svg viewBox="0 0 1 1">
<defs>
<filter id="halo1">
<feGaussianBlur in="SourceGraphic" stdDeviation=".03" />
</filter>
</defs>
<circle cx="50%" cy="50%" r="25%" filter="url(#halo1)"></circle>
</svg>
<svg>
<defs>
<filter id="halo2">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
</defs>
<circle cx="50%" cy="50%" r="25%" filter="url(#halo2)"></circle>
</svg>
</body>
</html>
Actually, in the CSS you know insert CSS to HTML like Internal CSS and Inline CSS. Internal CSS is you write css on in inside on tag and that tend general for use to give style on SVG. While, Inline CSS used to write css on unique element on tags like your program(coding). Although you have writenn css svg, your svg on "Hallo1" disappear because your program have write inline CSS viewBox="0 0 1 1"make your svg "Halo 1" disappear. Moreover, viewBox="0 0 1 1" make your circle dissapear because weight=1 and height=1 so that cirle which resulted so small and you cannot see that. To solve that problem you can change your viewBox become 'viewBox="0 0 100 100" '

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');
}

clipPath transform on :focus/:hover for multiple instances of same icon

I have an SVG icon with some masked shapes comprised of:
book-1: masked by clipPath mask-1
book-2: masked by clipPath mask-2
book-3: not masked, no transform required
On :focus / :hover I want mask-1 (but not book-1), and book-2 (but not mask-2) to transform. Straightforward enough…
<a href="whatevs" class="icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44 44">
<defs>
<style>
#book-1 {clip-path:url(#mask-1);}
#book-2 {clip-path:url(#mask-2);}
</style>
<clipPath id="mask-1">
<path class="nudge" fill="none" … />
</clipPath>
<clipPath id="mask-2">
<path fill="none" … />
</clipPath>
</defs>
<g id="book-1">
<path fill="#fff" … />
</g>
<g id="book-2">
<path fill="#fff" class="nudge" … />
</g>
<path fill="#fff" … /> <!-- book-3 -->
</svg>
</a>
/* CSS */
.icon .nudge {
transition: transform 0.2s ease-in;
}
.icon:focus .nudge,
.icon:hover .nudge {
transform: translate(-2px, 2px);
}
But the fun begins when there are multiple instances of the same icon in a page.
I have 3 Pens on CodePen, each with 2 instances of the linked icon, where:
MRYwBq fails with:
verbose code stating the full SVG each time it appears
class names for book-1 and book-2
unique id names for every instance of just the masks: mask-1 and mask-2
qwEZrG works with:
verbose code stating the full SVG each time it appears
unique id names for every instance of the books and the masks: book-1, mask-1, book-2 and mask-2
gybrvL fails with:
a <symbol> instance of the icon iterated via <use> in the page
Thoughts
This is just weird. I’d like to understand why it fails the way it does.
It’s good that this works but I would prefer not to have to iterate the IDs with JavaScript after they have been sent to the page undifferentiated.
This is what I’d like to get working, but I don’t know if that’s possible.
Since the clip-path requires an id of a svg def child, only one of these <clipPath> definitions will be taken into account in case multiple icons are placed on a page. That's why transforming the <clipPath> elements is a no-go, as all items referencing it will be affected. As a consequence, we need a solution that does not move or modify these elements based on :hover of :focus.
Fortunately, it is possible to move just the clipping path assigned to an element "without" moving the element itself by using the following trick:
Assign the clip path to the parent
Move the parent in the direction that the clip path should move
Move all children in the opposite direction
An example of this trick based on the code you provided can be found in the snippet below:
a .nudge, a .unnudge {
transition: transform 0.2s ease-in;
}
a:focus,
a:hover {
background-color: black;
}
a:focus .nudge,
a:hover .nudge {
transform: translate(-2px, 2px);
}
a:focus .unnudge,
a:hover .unnudge {
transform: translate(2px, -2px);
}
* {
box-sizing: border-box;
}
a {
display: block;
background-color: red;
padding: 0.5rem;
border-radius: 50%;
transition: background-color 0.2s ease-in;
width: 60px;
height: 60px;
}
body {
font-family: sans-serif;
line-height: 1.5;
max-width: 36em;
color: #333;
}
code {
background: #e5e5e5;
font-size: 1.125em;
border-radius: 2px;
}
<p>Instance 1:
<a href="#">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44 44" width="44" height="44">
<defs>
<style>
.book-1{clip-path:url(#mask-1-1);}
.book-2{clip-path:url(#mask-2-1);}
</style>
<clipPath id="mask-1-1">
<path fill="none" d="M13.823,33.1V18.293a4.738,4.738,0,0,1,1.4-3.371S24.6,5.531,25.085,5.048L20.019-.019H8.143V33.1Z"/>
</clipPath>
<clipPath id="mask-2-1">
<path fill="none" d="M31.814,10.117,21.12,20.822a4.733,4.733,0,0,0-1.4,3.371V39H12V7H28.7Z"/>
</clipPath>
</defs>
<g class="nudge book-1" >
<path fill="#fff" class="unnudge" d="M22.736,5.72a1.193,1.193,0,0,0-1.686,0l-7.516,7.516a1.191,1.191,0,0,1-1.685-1.685l7.516-7.516a1.192,1.192,0,0,0-1.686-1.686L10.163,9.865h0a3.565,3.565,0,0,0-1.047,2.529h0V26.625h0a3.576,3.576,0,0,0,6.1,2.528h0l7.516-7.516a1.188,1.188,0,0,0,.349-.843V6.563A1.188,1.188,0,0,0,22.736,5.72Z"/>
</g>
<g class="book-2">
<path fill="#fff" class="nudge" d="M21.723,22.193a4.733,4.733,0,0,1,1.4-3.371l5.865-5.871v-.488a1.192,1.192,0,0,0-2.035-.843l-7.516,7.516a1.192,1.192,0,0,1-1.686-1.686l7.516-7.516a1.191,1.191,0,1,0-1.685-1.685l-7.516,7.516a3.561,3.561,0,0,0-1.048,2.528h0V32.524h0a3.577,3.577,0,0,0,6.105,2.529h0l.6-.6Z"/>
</g>
<path fill="#fff" d="M34.535,17.52a1.19,1.19,0,0,0-1.685,0l-7.516,7.516a1.192,1.192,0,0,1-1.686-1.686l7.516-7.516a1.192,1.192,0,1,0-1.686-1.685l-7.516,7.516h0a3.564,3.564,0,0,0-1.047,2.528h0V38.424h0a3.576,3.576,0,0,0,6.1,2.529h0l7.516-7.516a1.188,1.188,0,0,0,.349-.843V18.363A1.188,1.188,0,0,0,34.535,17.52Z"/>
</svg>
</a>
</p>
<p>Instance 2, exact copy of instance 1:
<a href="#">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44 44" width="44" height="44">
<defs>
<style>
.book-1{clip-path:url(#mask-1-1);}
.book-2{clip-path:url(#mask-2-1);}
</style>
<clipPath id="mask-1-1">
<path fill="none" d="M13.823,33.1V18.293a4.738,4.738,0,0,1,1.4-3.371S24.6,5.531,25.085,5.048L20.019-.019H8.143V33.1Z"/>
</clipPath>
<clipPath id="mask-2-1">
<path fill="none" d="M31.814,10.117,21.12,20.822a4.733,4.733,0,0,0-1.4,3.371V39H12V7H28.7Z"/>
</clipPath>
</defs>
<g class="nudge book-1" >
<path fill="#fff" class="unnudge" d="M22.736,5.72a1.193,1.193,0,0,0-1.686,0l-7.516,7.516a1.191,1.191,0,0,1-1.685-1.685l7.516-7.516a1.192,1.192,0,0,0-1.686-1.686L10.163,9.865h0a3.565,3.565,0,0,0-1.047,2.529h0V26.625h0a3.576,3.576,0,0,0,6.1,2.528h0l7.516-7.516a1.188,1.188,0,0,0,.349-.843V6.563A1.188,1.188,0,0,0,22.736,5.72Z"/>
</g>
<g class="book-2">
<path fill="#fff" class="nudge" d="M21.723,22.193a4.733,4.733,0,0,1,1.4-3.371l5.865-5.871v-.488a1.192,1.192,0,0,0-2.035-.843l-7.516,7.516a1.192,1.192,0,0,1-1.686-1.686l7.516-7.516a1.191,1.191,0,1,0-1.685-1.685l-7.516,7.516a3.561,3.561,0,0,0-1.048,2.528h0V32.524h0a3.577,3.577,0,0,0,6.105,2.529h0l.6-.6Z"/>
</g>
<path fill="#fff" d="M34.535,17.52a1.19,1.19,0,0,0-1.685,0l-7.516,7.516a1.192,1.192,0,0,1-1.686-1.686l7.516-7.516a1.192,1.192,0,1,0-1.686-1.685l-7.516,7.516h0a3.564,3.564,0,0,0-1.047,2.528h0V38.424h0a3.576,3.576,0,0,0,6.1,2.529h0l7.516-7.516a1.188,1.188,0,0,0,.349-.843V18.363A1.188,1.188,0,0,0,34.535,17.52Z"/>
</svg>
</a>
</p>
Please note, that this solution is not perfect, and the trick with having two opposite movements that should sum up to no movement, can result in a bit of jerkiness of the .book-1 on some browsers (e.g. Firefox).

SVG mix-blend-mode not showing in firefox

Testing an svg using mix-blend-mode: multiply in Firefox 44 and it will not apply the blend-mode at all. But on another page I have a similar SVG and it shows fine. So it seems like the problem is with the SVG code itself...
I've seen a few other people having similar issues and have looked at all the proposed solutions, none of which worked for me. (adding background-color to div, adding a transparent border)
HTML:
<div class="about-background clearfix">
<object class="willItBlend" data="../svg/about-bg.svg" type="image/svg+xml"></object>
<img class="blender" src="../svg/about-bg.png" />
</div>
CSS (png fallback):
#supports not(mix-blend-mode: multiply) {
.blender {
display: block;
}
.willItBlend {
display: none;
}
SVG:
<svg width="489" height="441" viewBox="0 0 489 441" xmlns="http://www.w3.org/2000/svg">
<title>
about-bg
</title>
<style>
path { mix-blend-mode: multiply; }
ellipse { mix-blend-mode: multiply; }
</style>
<g fill="none" fill-rule="evenodd">
<g transform="translate(-236.973 -308)" stroke-width="33.6">
<ellipse stroke="#E2E42E" cx="345.986" cy="357.28" rx="345.986" ry="357.28"/>
<ellipse stroke="#ED1F71" cx="346.972" cy="358.298" rx="295.715" ry="305.368"/>
<ellipse stroke="#03A8DE" cx="346.972" cy="358.298" rx="244.458" ry="252.437"/>
</g>
<g transform="translate(-284 -294.56)">
<path d="M345.986 714.56c191.083 0 345.987-159.96 345.987-357.28C691.973 159.96 537.07 0 345.986 0 154.903 0 0 159.96 0 357.28 0 554.6 154.903 714.56 345.986 714.56z" stroke="#E2E42E" stroke-width="11.2"/>
<ellipse stroke="#ED1F71" stroke-width="22.4" cx="346.972" cy="358.298" rx="295.715" ry="305.368"/>
<ellipse stroke="#03A8DE" stroke-width="22.4" cx="346.972" cy="358.298" rx="244.458" ry="252.437"/>
</g>
<g transform="translate(-138.44 -164.64)">
<path d="M247.453 510.72c136.665 0 247.453-114.33 247.453-255.36C494.906 114.33 384.118 0 247.453 0 110.788 0 0 114.33 0 255.36c0 141.03 110.788 255.36 247.453 255.36z" stroke="#E2E42E" stroke-width="11.2"/>
<ellipse stroke="#ED1F71" stroke-width="5.6" cx="248.573" cy="256.48" rx="211.623" ry="218.4"/>
<ellipse stroke="#03A8DE" stroke-width="5.6" cx="247.453" cy="256.48" rx="174.673" ry="180.32"/>
</g>
</g>
</svg>

Resources