Reputation: 36672
I have an SVG sprite as shown below.
It doesn't seem to be possible to access the individual parts of the SVG from CSS when using the <use>
tag technique.
I am aware that by using fill: currentColor
(see .path1
in the #icon-two-parts
symbol) it is possible to apply two different colours to different parts of the same SVG from CSS by using both color
and fill
values.
Is there any method to apply more than two colours to the same element when using SVGs in this way?
For example, is it possible to apply four colours to the four paths within the #icon-four-part
symbol?
div {
display: inline-block;
}
.icon {
display: inline-block;
width: 80px;
height: 40px;
fill: currentColor;
}
.icon-one-part {
color: green;
}
.icon-two-part {
color: green;
fill: red;
}
<svg display="none" width="0" height="0" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="icon-one-part" viewBox="0 0 670 1024">
<title>icon-one-part</title>
<path class="path1" d="M355.486 512l-343.355-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.362-105.551c16.148-15.833 42.023-15.833 58.171 0l479.823 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.862 471.473c-16.108 15.833-41.984 15.833-58.171 0l-107.362-105.551c-16.148-15.833-16.148-41.275 0-57.147l343.394-337.408z"></path>
</symbol>
<symbol id="icon-two-part" viewBox="0 0 1339 1024">
<title>icon-two-part</title>
<path class="path1" fill="currentColor" d="M314.092 512l343.355 337.408c16.148 15.872 16.148 41.314 0 57.147l-107.362 105.551c-16.148 15.833-42.023 15.833-58.171 0l-479.783-471.513c-16.148-15.872-16.148-41.354 0-57.226l479.783-471.513c16.108-15.833 41.984-15.833 58.171 0l107.362 105.551c16.148 15.833 16.148 41.275 0 57.147l-343.355 337.447z"></path>
<path class="path2" d="M1025.024 512l-343.316-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.323-105.551c16.148-15.833 42.063-15.833 58.171 0l479.862 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.902 471.473c-16.069 15.833-41.984 15.833-58.171 0l-107.323-105.551c-16.148-15.833-16.148-41.275 0-57.147l343.355-337.408z"></path>
</symbol>
<symbol id="icon-four-part" viewBox="0 0 2272 1024">
<title>icon-four-part</title>
<path class="path1" d="M777.413 512l343.355 337.408c16.148 15.872 16.148 41.314 0 57.147l-107.362 105.551c-16.148 15.833-42.023 15.833-58.171 0l-479.783-471.473c-16.148-15.872-16.148-41.354 0-57.226l479.823-471.513c16.108-15.833 41.984-15.833 58.171 0l107.362 105.551c16.148 15.833 16.148 41.275 0 57.147l-343.394 337.408z"></path>
<path class="path2" d="M1488.384 512l-343.316-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.323-105.551c16.148-15.833 42.063-15.833 58.171 0l479.862 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.902 471.473c-16.069 15.833-41.984 15.833-58.171 0l-107.323-105.551c-16.148-15.833-16.148-41.275 0-57.147l343.355-337.408z"></path>
<path class="path3" d="M314.092 512l343.355 337.408c16.148 15.911 16.148 41.314 0 57.147l-107.362 105.551c-16.148 15.833-42.023 15.833-58.171 0l-479.783-471.473c-16.148-15.872-16.148-41.354 0-57.226l479.783-471.513c16.108-15.833 41.984-15.833 58.171 0l107.362 105.551c16.148 15.833 16.148 41.275 0 57.147l-343.355 337.408z"></path>
<path class="path4" d="M1958.203 512l-343.316-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.323-105.551c16.148-15.833 42.063-15.833 58.171 0l479.862 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.902 471.473c-16.069 15.833-41.984 15.833-58.171 0l-107.323-105.551c-16.148-15.833-16.148-41.236 0-57.147l343.355-337.408z"></path>
</symbol>
</defs>
</svg>
<div>
<svg class="icon icon-one-part"><use xlink:href="#icon-one-part"></use></svg>
</div>
<div>
<svg class="icon icon-two-part"><use xlink:href="#icon-two-part"></use></svg>
</div>
<div>
<svg class="icon icon-four-parts"><use xlink:href="#icon-icon-four-part"></use></svg>
</div>
Upvotes: 10
Views: 9061
Reputation: 81
In addition to ManUtopiK's CSS custom properties method, you can also create a third colour by blending color
(via currentcolor
) and fill
addressed SVG elements with an opacity
Demo (Codepen project) | Detailed explainer (Twitter thread)
You also have stroke
at your disposal giving you 3+ addressable colours if your sprite can be composed of both stroke only (fill: none
) and fill only (stroke: none
) elements
Upvotes: 2
Reputation: 4714
In fact, the <use>
element is a reference which clones the content it’s pointing to into the shadow DOM. It’s not a placeholder that gets replaced by your SVG definition. That's why you can style the symbols definitions themselves and not the icon. Styling the definitions propagate to the icon like any css properties. The ancestor isn’t aware of the children, but the inheritable styles are still propagated...
But we want to fill each path with a different color, without altering other instances, and we want to be able to override it if necessary.
To do that, we can use CSS variables.
CSS variables are declared within rulesets just like any other property. Then, you declare it as a value for itself, or any child property, and it will be inherited.
Let's apply this concept for our SVG elements:
div {
display: inline-block;
margin-bottom: 20px;
}
.icon {
display: inline-block;
width: 80px;
height: 40px;
fill: currentColor;
}
.icon-one-part.green {
--color-1: green;
}
.icon-one-part.red {
--color-1: red;
}
.icon-two-part.style1 {
--color-1: #ff9900;
--color-2: #78ae90;
}
.icon-two-part.style2 {
--color-1: #2124af;
--color-2: #ef5b59;
}
.icon-four-part.style1 {
--color-1: #FB7C1F;
--color-2: #F38D68;
--color-3: #FB7C1F;
--color-4: #F38D68;
}
.icon-four-part.style2 {
--color-1: #007978;
--color-2: #23518C;
--color-3: #83B692;
--color-4: #4AA0CF;
}
<svg display="none" width="0" height="0" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="icon-one-part" viewBox="0 0 670 1024">
<title>icon-one-part</title>
<path class="path1" fill="var(--color-1)" d="M355.486 512l-343.355-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.362-105.551c16.148-15.833 42.023-15.833 58.171 0l479.823 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.862 471.473c-16.108 15.833-41.984 15.833-58.171 0l-107.362-105.551c-16.148-15.833-16.148-41.275 0-57.147l343.394-337.408z"></path>
</symbol>
<symbol id="icon-two-part" viewBox="0 0 1339 1024">
<title>icon-two-part</title>
<path class="path1" fill="var(--color-1)" d="M314.092 512l343.355 337.408c16.148 15.872 16.148 41.314 0 57.147l-107.362 105.551c-16.148 15.833-42.023 15.833-58.171 0l-479.783-471.513c-16.148-15.872-16.148-41.354 0-57.226l479.783-471.513c16.108-15.833 41.984-15.833 58.171 0l107.362 105.551c16.148 15.833 16.148 41.275 0 57.147l-343.355 337.447z"></path>
<path class="path2" fill="var(--color-2)" d="M1025.024 512l-343.316-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.323-105.551c16.148-15.833 42.063-15.833 58.171 0l479.862 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.902 471.473c-16.069 15.833-41.984 15.833-58.171 0l-107.323-105.551c-16.148-15.833-16.148-41.275 0-57.147l343.355-337.408z"></path>
</symbol>
<symbol id="icon-four-part" viewBox="0 0 2272 1024">
<title>icon-four-part</title>
<path class="path1" fill="var(--color-1)" d="M777.413 512l343.355 337.408c16.148 15.872 16.148 41.314 0 57.147l-107.362 105.551c-16.148 15.833-42.023 15.833-58.171 0l-479.783-471.473c-16.148-15.872-16.148-41.354 0-57.226l479.823-471.513c16.108-15.833 41.984-15.833 58.171 0l107.362 105.551c16.148 15.833 16.148 41.275 0 57.147l-343.394 337.408z"></path>
<path class="path2" fill="var(--color-2)" d="M1488.384 512l-343.316-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.323-105.551c16.148-15.833 42.063-15.833 58.171 0l479.862 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.902 471.473c-16.069 15.833-41.984 15.833-58.171 0l-107.323-105.551c-16.148-15.833-16.148-41.275 0-57.147l343.355-337.408z"></path>
<path class="path3" fill="var(--color-3)" d="M314.092 512l343.355 337.408c16.148 15.911 16.148 41.314 0 57.147l-107.362 105.551c-16.148 15.833-42.023 15.833-58.171 0l-479.783-471.473c-16.148-15.872-16.148-41.354 0-57.226l479.783-471.513c16.108-15.833 41.984-15.833 58.171 0l107.362 105.551c16.148 15.833 16.148 41.275 0 57.147l-343.355 337.408z"></path>
<path class="path4" fill="var(--color-4)" d="M1958.203 512l-343.316-337.408c-16.148-15.872-16.148-41.314 0-57.147l107.323-105.551c16.148-15.833 42.063-15.833 58.171 0l479.862 471.513c16.148 15.872 16.148 41.354 0 57.226l-479.902 471.473c-16.069 15.833-41.984 15.833-58.171 0l-107.323-105.551c-16.148-15.833-16.148-41.236 0-57.147l343.355-337.408z"></path>
</symbol>
</defs>
</svg>
<div>
<svg class="icon icon-one-part green"><use xlink:href="#icon-one-part"></use></svg>
</div>
<div>
<svg class="icon icon-one-part red"><use xlink:href="#icon-one-part"></use></svg>
</div>
<br>
<div>
<svg class="icon icon-two-part style1"><use xlink:href="#icon-two-part"></use></svg>
</div>
<div>
<svg class="icon icon-two-part style2"><use xlink:href="#icon-two-part"></use></svg>
</div>
<br>
<div>
<svg class="icon icon-four-part style1"><use xlink:href="#icon-four-part"></use></svg>
</div>
<div>
<svg class="icon icon-four-part style2"><use xlink:href="#icon-four-part"></use></svg>
</div>
We don’t have to declare the color for all CSS variable. Instead, we can declare a single fill
because CSS variables aren’t defined, it will fall back on this fill
declaration.
We can also apply a default to css variable:
var(--color-1, red)
and avoid to declare a default color for each icon.
And best of all, CSS variables are now compatible with most modern browsers!
Upvotes: 10
Reputation: 101820
You can style the symbols definitions themselves. Eg.:
#icon-one-part {
fill: green;
}
#icon-two-part .path1 {
fill: green;
}
#icon-two-part .path2 {
fill: red;
}
But if you need to re-use the same icon, and have each instance be a different colour, then you are are stuck with using the currentColor
technique.
Upvotes: 4