The hue-rotate()
filter function "rotates the hue of an element ... specified as an angle". If this were true, filter: hue-rotate(180deg) hue-rotate(180deg)
would have no effect. But it definitely does have an effect:
.square {
height: 3rem;
padding: 1rem;
background: linear-gradient( 90deg, rgba(255, 0, 0, 1) 0%, rgba(255, 154, 0, 1) 10%, rgba(208, 222, 33, 1) 20%, rgba(79, 220, 74, 1) 30%, rgba(63, 218, 216, 1) 40%, rgba(47, 201, 226, 1) 50%, rgba(28, 127, 238, 1) 60%, rgba(95, 21, 242, 1) 70%, rgba(186, 12, 248, 1) 80%, rgba(251, 7, 217, 1) 90%, rgba(255, 0, 0, 1) 100%);
font-family: monospace;
font-weight: bold;
color: white;
}
.double-invert {
filter: hue-rotate(180deg) hue-rotate(180deg);
}
<div class="square">filter: none</div>
<div class="square double-invert">filter: hue-rotate(180deg) hue-rotate(180deg)</div>
What is happening here? What does hue-rotate
actually do? And how can I achieve a hue rotation that is its own inverse? (Or, how can I come up with a filter that inverts the hue rotation?)
Update: following Temani Aiff's answer, it seems that hue-rotate(180deg)
is actually a matrix multiplication. However, it's unclear what matrix it's actually using. The following shows that we can reimplement the SVG filter type="hueRotate"
as a raw matrix, but the CSS filter hue-rotate
does not actually match either of those:
.square {
height: 3rem;
padding: 1rem;
background: linear-gradient( 90deg, rgba(255, 0, 0, 1) 0%, rgba(255, 154, 0, 1) 10%, rgba(208, 222, 33, 1) 20%, rgba(79, 220, 74, 1) 30%, rgba(63, 218, 216, 1) 40%, rgba(47, 201, 226, 1) 50%, rgba(28, 127, 238, 1) 60%, rgba(95, 21, 242, 1) 70%, rgba(186, 12, 248, 1) 80%, rgba(251, 7, 217, 1) 90%, rgba(255, 0, 0, 1) 100%);
font-family: monospace;
font-weight: bold;
color: white;
}
.hue-rotate {
filter: hue-rotate(180deg);
}
.hue-rotate-svg {
filter: url(#svgHueRotate180);
}
.hue-rotate-svg-matrix {
filter: url(#svgHueRotate180Matrix);
}
<svg style="position: absolute; top: -99999px" xmlns="http://www.w3.org/2000/svg">
<filter id="svgHueRotate180">
<feColorMatrix in="SourceGraphic" type="hueRotate"
values="180" />
</filter>
<!-- Following matrix calculated following spec -->
<filter id="svgHueRotate180Matrix">
<feColorMatrix in="SourceGraphic" type="matrix"
values="
-0.574 1.43 0.144 0 0
0.426 0.43 0.144 0 0
0.426 1.43 -0.856 0 0
0 0 0 1 0" />
</filter>
</svg>
<div class="square">filter: none</div>
<div class="square hue-rotate">filter: hue-rotate(180deg)</div>
<div class="square hue-rotate-svg">using SVG hueRotate</div>
<div class="square hue-rotate-svg-matrix">using SVG raw matrix</div>
At least in Chrome and Firefox, hue-rotate
is doing something distinct from the SVG filters. But what is it doing?!
hue-rotate(Xdeg)
means takinghsl(h,s,l)
tohsl(h+X, s, l)
, thenhue-rotate(180deg) hue-rotate(180deg)
takeshsl(h,s,l)
tohsl(h+360deg, s, l)
, which is equivalent tohsl(h,s,l)
– Xerodermargba
andhsla
as some colors cannot be converted correctly. And sincefilter
values are being applied one-by-one (the next one is being applied to the result of the previous one) the conversion bias is getting even worse. – Alisha