Reputation: 4166
I have a list of SVG icons that has colors in them which I use to display like below
I want to be able to re-use these SVG elsewhere in my webapp but change the color of the icons so that instead of showing color it only shows a certain shade of color. (Blue)
Is there a way to change this to blue similar to grayscale via CSS? (I'd rather not upload a separate SVG to do this)
The closest I got was something from following this How change hue of image with different colors with css filter to hue of blue
But I don’t want the square background right behind the icon. (I just want the SVG to change color)
.background {
padding: 16px;
background: rgb(199, 229, 242);
}
.donut {
width: 32px;
height: 32px;
position: relative;
}
.donut::before, .donut::after {
content: '';
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
.donut::before {
background-color: gray;
mix-blend-mode: color;
}
.donut::after {
mix-blend-mode: overlay;
background-color: blue;
}
<div class="background">
<div class="donut">
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<path d="M23.778 4.36A14 14 0 0016 2v5a9 9 0 11-9 9H2A14 14 0 1023.778 4.36z" fill="#E1BD16"/>
<path d="M6.1 6.1A14 14 0 002 16h5a9 9 0 019-9V2a14 14 0 00-9.9 4.1z" fill="#F85F4E"/>
</svg>
</div>
</div>
Upvotes: 1
Views: 2610
Reputation: 17155
You could also apply a css filter directly on your donut icon like so:
filter: hue-rotate(180deg) saturate(75%);
Simple color shift example
.background {
padding: 16px;
background: rgb(199, 229, 242);
}
.icon-use {
width: 32px;
height: 32px;
display: inline-block;
}
.filter-blue-hover:hover,
.filter-blue {
filter: hue-rotate(180deg) saturate(75%);
}
<svg class="donut" style="display:none" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<symbol id="icon">
<path d="M23.778 4.36A14 14 0 0016 2v5a9 9 0 11-9 9H2A14 14 0 1023.778 4.36z" fill="#E1BD16" />
<path d="M6.1 6.1A14 14 0 002 16h5a9 9 0 019-9V2a14 14 0 00-9.9 4.1z" fill="#F85F4E" />
</symbol>
</svg>
<div class="background">
<svg viewBox="0 0 32 32" class="icon-use filter-blue">
<use href="#icon" />
</svg>
</div>
<p>
<svg viewBox="0 0 32 32" class="icon-use filter-blue-hover">
<use href="#icon" />
</svg> Filter on hover - no background color needed.
</p>
Edit: normalized colorizing
This example avoids undesired colors caused by relative hue shifts.
We first tint everything to a sepia tone by sepia(100%)
.
By this normalizing step, we can make sure all filtered colors will be in the desired hue range ("blueish" in this case).
//toggleFilter
function toggleFilter() {
let filterItems = document.querySelectorAll(".toggleFilter");
filterItems.forEach(function(el, i) {
el.classList.toggle("filter-blue");
});
}
.icon-use {
width: 1em;
height: 1em;
display: inline-block;
font-size: 10vw;
transition: 0.3s;
}
.filter-blue {
transition: 0.3s filter ease-in-out;
filter: invert(0%) sepia(100%) saturate(300%) hue-rotate(-180deg);
}
.filter-blue:hover {
filter: invert(0%) sepia(0%) saturate(100%) hue-rotate(0deg);
}
.icon-wrp {
position: relative;
display: inline-block;
width: 1em;
font-size: 10vw;
}
<p>
<button id="btnFilter" onclick="toggleFilter()">Toggle Filter</button>
</p>
<svg class="donut" style="display:none" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<symbol id="slice">
<circle cx="50%" cy="50%" r="25%" fill="none" pathLength="99" />
</symbol>
</svg>
<div class="icon-wrp">
<!-- pie chart-->
<svg viewBox="0 0 32 32" class="toggleFilter">
<use href="#slice" stroke="#E1BD16" stroke-width="16" />
<use href="#slice" stroke="#F85F4E" stroke-width="16" stroke-dasharray="33 100" />
<use href="#slice" stroke="purple" stroke-width="16" stroke-dashoffset="-33" stroke-dasharray="33 100" />
</svg>
</div>
<div class="icon-wrp">
<!-- pie chart-->
<svg viewBox="0 0 32 32" class="toggleFilter " transform="scale(1.5)">
<use href="#slice" stroke="blue" stroke-width="4" />
<use href="#slice" stroke="green" stroke-width="4" stroke-dasharray="33 100" />
<use href="#slice" stroke="orange" stroke-width="4" stroke-dashoffset="-33" stroke-dasharray="33 100" />
</svg>
</div>
<div class="icon-wrp">
<!-- pie chart-->
<svg viewBox="0 0 32 32" class="toggleFilter ">
<use href="#slice" stroke="yellow" stroke-width="16" />
<use href="#slice" stroke="cyan" stroke-width="16" stroke-dasharray="33 100" />
<use href="#slice" stroke="magenta" stroke-width="16" stroke-dashoffset="-33" stroke-dasharray="33 100" />
</svg>
</div>
This approach is based on the popular svg coloring concept described here (How to change the color of an svg element?).
The main benefit:
you don't need additional (background) elements to control the mix-blendmode color calculations.
Drawbacks:
you will have to tweak the different hue-shift properties to get the desired color result.
Upvotes: 2
Reputation: 208
Using filter with just the SVG's paths not the background to change color based on the original colors:
.background {
margin: 1rem;
}
.donut {
height: 32px;
width: 32px;
}
.donut svg:hover {
filter: hue-rotate(180deg);
}
<div class="background">
<div class="donut">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<path d="M23.778 4.36A14 14 0 0016 2v5a9 9 0 11-9 9H2A14 14 0 1023.778 4.36z" fill="#E1BD16"/>
<path d="M6.1 6.1A14 14 0 002 16h5a9 9 0 019-9V2a14 14 0 00-9.9 4.1z" fill="#F85F4E"/>
</svg>
</div><br>
Hover over image.
</div>
Upvotes: 0
Reputation: 4166
I found that you can add a position absolute SVG with a fill of the color that you want. Then using mix-blend-mode: overlay;
and filter: grayscale(1);
you can get the shade of color that you want
.background {
padding: 16px;
background: rgb(199, 229, 242);
}
.donut {
width: 32px;
height: 32px;
filter: grayscale(1);
mix-blend-mode: overlay;
z-index: 1;
}
.donut-background {
width: 32px;
height: 32px;
position: absolute;
z-index: 0;
}
.donut-background * {
fill: #2C93BF;
}
<div class="background">
<svg class="donut-background" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<path d="M23.778 4.36A14 14 0 0016 2v5a9 9 0 11-9 9H2A14 14 0 1023.778 4.36z" fill="#E1BD16"/>
<path d="M6.1 6.1A14 14 0 002 16h5a9 9 0 019-9V2a14 14 0 00-9.9 4.1z" fill="#F85F4E"/>
</svg>
<svg class="donut" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<path d="M23.778 4.36A14 14 0 0016 2v5a9 9 0 11-9 9H2A14 14 0 1023.778 4.36z" fill="#E1BD16"/>
<path d="M6.1 6.1A14 14 0 002 16h5a9 9 0 019-9V2a14 14 0 00-9.9 4.1z" fill="#F85F4E"/>
</svg>
</div>
Upvotes: 0