CSS vs SVG linear gradient challenge

SVG and its linearGradient element allow to achieve similar results to those obtained with CSS’s linear-gradient() function. A great benefit of using SVG is the possibility to create it using external graphic tools and then simply embedding in HTML. Once embedded, JS or CSS can be applied to it! In this post I bring back plenty of examples from CSS Linear Gradient post and try to reproduce the same effect with SVG.

Youtube Video – CSS vs SVG Linear Gradient

Demo and code (tl;dr)

See the Pen Untitled by Artur Karczmarczyk (@arturkarczmarczyk) on CodePen.

SVG linearGradient Basic Usage

Let’s jump right into the code. To create a basic linear gradient in SVG, simply use linearGradient element. This element needs to be specified in the defs (definitions) tag. Once the linear gradient is specified, you need to give it an id. Later you can reuse this linear gradient as a fill of any element using url(‘#my-gradient-id’) syntax. See the sample code:

HTML
<svg viewBox="0 0 100 100">
    <defs>
        <linearGradient id="gradientDefault">
            <stop offset="0%" stop-color="black" />
            <stop offset="100%" stop-color="darkcyan" />
        </linearGradient>
    </defs>
    <rect width="100" height="100" fill="url('#gradientDefault')" />
</svg>

Effect:

Basic SVG linearGradient added to a rectangle element.
Basic SVG linearGradient added to a rectangle element.

How to change direction of the SVG linearGradient?

Changing the default direction of the SVG linear gradient is simple. There are 2 options how to achieve that – either by setting the x1,y1 and x2,y2 points of the linear gradient, or by using CSS rotate() transform:

HTML
<svg viewBox="0 0 100 100">
    <defs>
        <linearGradient id="gradientXY" x1="0" y1="0" x2="100%" y2="100%">
            <stop offset="0%" stop-color="black" />
            <stop offset="100%" stop-color="darkcyan" />
        </linearGradient>
    </defs>
    <rect width="100" height="100" fill="url('#gradientXY')" />
</svg>

<svg viewBox="0 0 100 100">
    <defs>
        <linearGradient id="gradientRotate" style="transform: rotate(45deg);">
            <stop offset="0%" stop-color="black" />
            <stop offset="100%" stop-color="darkcyan" />
        </linearGradient>
    </defs>
    <rect width="100" height="100" fill="url('#gradientRotate')" />
</svg>

And here’s the effect:

Changing the direction of the SVG linearGradient.
Changing the direction of the SVG linearGradient.

For a very detailed explanation how and why it works – see this fragment of the YT video.

Hint Midpoint Position in SVG Linear Gradient

Unfortunately, there isn’t an easy way to hint the midpoint position in SVG. However, when you open any graphic tools, it does have this feature!

Graphic tools allow to hint the midpoint position in SVG linear gradients.

It’s great that SVG is an open XML format. It is very simple to export anything gradient we produce in the graphic software and then see how it produces the SVG. It turns out that for midpoint position hint in SVG linear gradient, a trick is used – additional color stops are added:

HTML
<svg viewBox="0 0 100 100">
    <defs>
        <linearGradient id="gradientMidpoint">
            <stop offset="0%" stop-color="darkcyan" />
            <!-- two stops need to be added - graphic tool needed -->
            <stop offset="0.2" stop-color="#416565"/>
            <stop offset="0.42" stop-color="#853D3D"/>

            <stop offset="100%" stop-color="brown" />
        </linearGradient>
    </defs>
    <rect width="100" height="100" fill="url('#gradientMidpoint')" />
</svg>
Preview of the SVG linear gradient midpoint hint workaround.
Preview of the SVG linear gradient midpoint hint workaround.

Multiple Gradient Colors

In order to add additional colors to your SVG linear gradient, all you need to do is add more stop elements within the gradient definition. At each stop you can specify both color and offset, either in 0-100% or 0.0-1.0 notation, to specify where the stop color should be:

HTML
<svg viewBox="0 0 100 100">
    <defs>
        <linearGradient id="gradientRainbow">
            <stop offset="0%" stop-color="red" />
            <stop offset="16%" stop-color="orange" />
            <stop offset="33%" stop-color="yellow" />
            <stop offset="50%" stop-color="green" />
            <stop offset="67%" stop-color="blue" />
            <stop offset="83%" stop-color="indigo" />
            <stop offset="100%" stop-color="violet" />
        </linearGradient>
    </defs>
    <rect width="100" height="100" fill="url('#gradientRainbow')" />
</svg>

This produces now a 7-color rainbow, same as with CSS:

A 7-color rainbow created with SVG linear gradient.
A 7-color rainbow created with SVG linear gradient.

We can add even more color stops, to force sharp stripes. Just specify the start and stop offset of each color, and make sure there is no space between colors. For example, orange starts at 14% and ends at 28%, and yellow follows immediately at 28% to 42%, followed by green etc.:

HTML
<svg viewBox="0 0 100 100">
    <defs>
        <linearGradient id="gradientRainbowStripes">
            <stop offset="14%" stop-color="red" />
            <stop offset="14%" stop-color="orange" />
            <stop offset="28%" stop-color="orange" />
            <stop offset="28%" stop-color="yellow" />
            <stop offset="42%" stop-color="yellow" />
            <stop offset="42%" stop-color="green" />
            <stop offset="58%" stop-color="green" />
            <stop offset="58%" stop-color="blue" />
            <stop offset="72%" stop-color="blue" />
            <stop offset="72%" stop-color="indigo" />
            <stop offset="86%" stop-color="indigo" />
            <stop offset="86%" stop-color="violet" />
            <stop offset="100%" stop-color="violet" />
        </linearGradient>
    </defs>
    <rect width="100" height="100" fill="url('#gradientRainbowStripes')" />
</svg>

This results in 7 sharp stripes:

How to obtain sharp stripes with SVG linear gradient.
How to obtain sharp stripes with SVG linear gradient.

Transparency in SVG linear gradient

There are 2 approaches for adding transparency in SVG linear gradients. The first one is by just using transparent color – either transparent keyword, or using hexadecimal value including alpha channel, e.g. #FF000000 (4 pairs RGBA instead of 3 pairs RGB):

HTML
<svg viewBox="0 0 100 100">
    <defs>
        <linearGradient id="gradientTransparent">
            <stop offset="0%" stop-color="red" />
            <stop offset="100%" stop-color="transparent" />
        </linearGradient>
    </defs>
    <rect width="100" height="100" fill="url('#gradientTransparent')" />
</svg>

The second option is to use a stop-opacity attribute of the stop element:

HTML
<svg viewBox="0 0 100 100">
    <defs>
        <linearGradient id="gradientTransparent">
            <stop offset="0%" stop-color="red" stop-opacity="1" />
            <stop offset="100%" stop-color="red" stop-opacity="0" />
        </linearGradient>
    </defs>
    <rect width="100" height="100" fill="url('#gradientTransparent')" />
</svg>

In both cases the effect will be the same:

Opacity for a stop color in SVG linear gradient.
Opacity for a stop color in SVG linear gradient.

How to mix multiple SVG linear gradients in layers?

It is possible to overlay one linear gradient over another, with semi-transparent gradients, to obtain an effect of mixing gradients. Here is what we achieved with CSS:

CSS used for mixing multiple linear gradients in layers one over another.

A single linearGradient SVG element cannot have information on many gradients. However, we can put multiple rectangle elements one over another:

HTML
<svg viewBox="0 0 100 100">
    <defs>
        <linearGradient id="gradientLayersRed" x1="0" y1="100%" x2="0" y2="0">
            <stop offset="0%" stop-color="red" stop-opacity="67%" />
            <stop offset="100%" stop-color="red" stop-opacity="0%"/>
        </linearGradient>
        <linearGradient id="gradientLayersGreen" x1="0" y1="0" x2="100%" y2="100%">
            <stop offset="0%" stop-color="green" stop-opacity="67%" />
            <stop offset="100%" stop-color="green" stop-opacity="0%"/>
        </linearGradient>
        <linearGradient id="gradientLayersBlue" x1="100%" y1="0" x2="0" y2="100%">
            <stop offset="0%" stop-color="blue" stop-opacity="67%" />
            <stop offset="100%" stop-color="blue" stop-opacity="0%"/>
        </linearGradient>
    </defs>
    <rect width="100" height="100" fill="url('#gradientLayersRed')" />
    <rect width="100" height="100" fill="url('#gradientLayersGreen')" />
    <rect width="100" height="100" fill="url('#gradientLayersBlue')" />
</svg>

In the code we have 3 gradients – red, green and blue – directed to top, to bottom right and to bottom left. Then we have 3 rectangles covering one another, each having different gradient assigned. Because the gradients are semi-transparent, the bottom rectangles are visible from below the top ones. Note, however, that the obtained effect is different than with CSS, and the order of rectangles does matter:

Similar effect obtained with SVG.
Similar effect obtained with SVG.

Repeating Linear Gradient

Finally, in this section we want to create a repeating linear gradient pattern:

Repeating linearGradient in SVG.

This is very simple. You need to set x1,y1 and x2,y2 points of the gradient to take less than 100% of your rectangle, and then simply apply a spreadMethod attribute of the gradient to repeat:

HTML
<svg viewBox="0 0 100 100">
    <defs>
        <linearGradient id="gradientRepeated" x1="0" y1="0" x2="20%" y2="0" spreadMethod="repeat">
            <stop offset="0%" stop-color="black" />
            <stop offset="50%" stop-color="darkcyan" />
            <stop offset="100%" stop-color="black" />
        </linearGradient>
    </defs>
    <rect width="100" height="100" fill="url('#gradientRepeated')" />
</svg>

Summary

In this post I showed you multiple ideas how to use SVG linear gradients. I was able to reproduce majority of the ideas from the CSS linear-gradient() blog post. This is an interesting alternative to keeping things in CSS, especially that you can use software like Adobe Illustrator or Affinity Designer or Inkscape to produce custom fancy gradients. I encourage you to check out the Youtube video of SVG vs CSS linear gradients. In the video I show you all the ideas above in detail, step by step!

If you’d like to learn more on HTML, CSS and LESS in a structured, no-nonsense, hands-on manner, try my Udemy HTML & CSS 2022: Hands-on No-nonsense Guide!

Leave a Reply

%d bloggers like this: