I’m trying to convert this simple SVG gradient to CSS:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_2" data-name="Layer 2" width="107.097" height="26.024" viewBox="0 0 107.097 26.024">
<defs>
<style>
.cls-1 {
fill: url(#linear-gradient);
stroke-width: 0px;
}
</style>
<linearGradient id="linear-gradient" x1="795.61" y1="-6.181" x2="707.657" y2="35.941" gradientTransform="translate(-701.986 26.024) scale(1 -1)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#f0ce45" stop-opacity="0"/>
<stop offset="1" stop-color="#fd00ac"/>
</linearGradient>
</defs>
<g id="Layer_1-2" data-name="Layer 1">
<rect class="cls-1" x="0" y="0" width="107.097" height="26.024" transform="translate(107.097 26.024) rotate(-180)"/>
</g>
</svg>
But I can’t find the equivalent of stop-opacity
in CSS. From MDN docs:
The stop-opacity attribute defines the opacity of a given color
gradient stop.The opacity value used for the gradient calculation is the product of
the value of stop-opacity and the opacity of the value of the
stop-color attribute. For stop-color values that don’t include
explicit opacity information, the opacity is treated as 1.
There is a stop-opacity
property in CSSm but it doesn’t behave the same.
.gradient {
width: 200px;
height: 20px;
stop-opacity: 0;
background-image: linear-gradient(to left, #f1109b, #f0ce45)
}
<div class="gradient">
</div>
How can I recreate that gradient in CSS?
2
Answers
You can use a
mask-image
and apply a gradient as the image. However keep in mind that it is not fully supported everywhere yet.This question sent me into some kind of rabbit hole of re-learning CSS and SVG (or correcting my false beliefs thereof) and I’d like to preserve a memento here for future reference. Same as @enxameta in comments, I thought that translating such simple linear gradient from SVG to CSS must be quite straightforward. There are two problems that prevents it to be … simply doable:
1: Hue of fully transparent colour does not affect CSS gradient
Honestly, I would have sworn that
linear-gradient(#FFF, #FFF0)
must be different fromlinear-gradient(#FFF, #0000)
, but, in CSS gradients, it is not.Neither in animations.
Yes, it makes very little sense, especially compared to SVG, where gradient stops with
stop-opacity="0"
(or with colours of zero alpha) affect its surroundings. Another example, comparing SVG and CSS gradient:2: CSS gradients are positioned differently than SVG
In CSS "0%"/"100%" stop is the tangent that crosses closest/farthest corner and is perpendicular to angled gradient axis. Is SVG you basically throw a line segment somewhere and gradient lines are perpendicular to only that starting and ending on x1 y1 – x2 y2. So translating any non-orthogonal gradient could be also a challenge, since you have to re-compute and last offset stops with regard to dimensions (ratio) of target element.
Some garbaj produced along the way, for making illustrations above.
CSS VS SVG gradients:
OP’s code iterated to the point where it should be identical, but …
(So with
background-blend-mode
in the last try I got pretty close to the goal (on black background it is indistinguishable from SVG), but lost the transparency, what renders it quite useless.)