Animating SVG Gradients

• 7 minutes READ

SVG gradients are so handy. We can fill complex shapes and create depth and character for our artwork all while having access to it in the DOM.

Within SVG linear and radial gradient elements there are several attribute options available for thorough customization. Animating these gradients takes this customization even further and presents a unique opportunity that can be used to further communicate something to our users.

Slides

Slides: HTML Static Website Builder

Scalable Vector Graphics (SVG) gradients are a powerful way to add color transitions and visual effects to your web designs. They can be easily animated to create engaging and dynamic interfaces. In this article, we will explore the world of animating SVG gradients, covering the basics, advanced techniques, and practical applications.

Introduction to Animating SVG Gradients

Scalable Vector Graphics (SVG) gradients are a powerful way to add color transitions and visual effects to your web designs. They can be easily animated to create engaging and dynamic interfaces. In this article, we will explore the world of animating SVG gradients, covering the basics, advanced techniques, and practical applications.

Basics of SVG Gradients

There are two types of SVG gradients: linear and radial.

No-Code Email Template Builder

With Postcards Email Builder you can create and edit email templates online without any coding skills! Includes more than 100 components to help you create custom emails templates faster than ever before.

Free Email BuilderFree Email Templates

Linear Gradients

Linear gradients transition colors along a straight line. They are defined by specifying a starting and ending point, along with the colors to transition between.

Radial Gradients

Radial gradients transition colors from a central point, radiating outward in a circular pattern. They are defined by specifying the center, radius, and colors to transition between.

This article will cover the basics of SVG gradients and getting started with <animate>, and then dive into some demos for further understanding.

Browser Support

Basic SVG support is present across desktop and mobile browsers, going at least two versions back across the board for desktop.

Concerning SVG SMIL animation (animating within the SVG element itself) specifically there is no support in IE, IE mobile, or Opera Mini, but strong support in current and at least one version back in Chrome, Firefox, Safari, Opera, and on mobile.

SVG Gradients

Before we get started with animation, it’s important to have a basic understanding of how SVG gradients work.

Gradients are one of many paint server options we have available to use when we wish to add color to the fills and strokes of SVG. The idea here is that we can define gradients within our SVG but they have no visual output until we call on them with the use of the “fill” and/or “stroke” attributes.

The basic structure of a very simple linear SVG gradient looks something like this:

Low-Code Website Builders

With Startup App and Slides App you can build unlimited websites using the online website editor which includes ready-made designed and coded elements, templates and themes.

Try Startup App Try Slides AppOther Products
    <svg version="1.1" xmlns="https://www.w3.org/2000/svg" xmlns:xlink="https://www.w3.org/1999/xlink" x="0px" y="0px"
    width="180px" height="337px" viewBox="0 0 180.36 336.86" enable-background="new 0 0 180.36 336.86" xml:space="preserve">
      <path fill="#7A5034" stroke="7A5034" stroke-width="2.5448" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
      M159.337,292.35c0.863,0.605,1.073,1.795,0.469,2.658l-20.974,29.954c-0.605,0.863-1.795,1.073-2.658,0.469l-115.15-80.629
      c-0.863-0.605-1.073-1.795-0.469-2.658l20.974-29.954c0.605-0.863,1.795-1.073,2.658-0.469L159.337,292.35z M100.669,289.765
      L25.16,236.893 M149.278,309.079l-77.039-53.943 M73.154,244.329L38.237,219.88 M154.817,300.734l-25.015-17.516"/>
      <path fill="#7A5034" stroke="#7A5034" stroke-width="2.5448" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
      M44.187,325.431c-0.863,0.605-2.054,0.395-2.658-0.469l-20.974-29.954c-0.605-0.863-0.395-2.054,0.469-2.658l115.15-80.629
      c0.863-0.605,2.054-0.395,2.658,0.469l20.974,29.954c0.605,0.863,0.395,2.054-0.469,2.658L44.187,325.431z M66.681,271.185
      l75.509-52.872 M31.907,310.257l77.039-53.943 M118.788,260.87l34.917-24.449 M37.855,318.317l25.015-17.516"/>
      <path class="outer-flame" fill="url(#largeGradient)" stroke="url(#largeGradient)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
      M82.579,210.049c-4.315-0.393-8.678-1.158-12.676-2.352c-19.553-5.839-36.385-22.93-40.572-43.069
      c-1.102-5.301-1.471-11.261-0.887-16.656c1.646-15.209,8.889-31.008,16.749-43.975C55.992,86.183,67.031,68.265,74.26,48.634
      c2.079-5.647,3.825-11.421,5.117-17.299c2.019-9.181,3.897-21.151-3.384-28.647c14.729,15.163,27.537,32.13,38.675,50.078
      c4.029,6.492,7.841,13.117,11.454,19.849c3.744,6.976,7.259,14.075,10.524,21.288c4.38,9.678,7.966,19.728,10.488,30.052
      c4.66,19.078,9.751,43.266-2.968,60.391c-5.683,7.652-12.951,13.902-21.589,17.991c-10.308,4.879-22.085,8.124-33.541,8.032
      C86.931,210.352,84.761,210.248,82.579,210.049z">
      </path>
      <path class="inner-flame" fill="url(#smallGradient)" stroke="url(#smallGradient)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
      M90.043,116.799c-4.024,9.712-12.607,17.546-17.863,26.662c-5.921,10.268-11.892,23.039-9.362,35.209
      1.865,8.974,9.366,16.589,18.078,19.191c1.782,0.532,3.726,0.873,5.648,1.048c0.972,0.089,1.939,0.135,2.877,0.143
      c5.104,0.041,10.352-1.405,14.945-3.579c3.849-1.822,7.087-4.607,9.62-8.017c7.656-10.307,3.202-24.177-1.21-34.838
      c-6.142-14.841-15.085-28.459-22.297-42.793C91.464,111.781,91.118,114.204,90.043,116.799z">
      </path>
    </svg>

Green gradient

The gradient details are written within the <defs> element, but would have no output within our work until we call on it using its unique ID. At this point we would also add the shape within the same <svg> element, but outside of the <defs> element.

The <stop> nodes represent the color selections and their locations on our mapped gradient, which we will discuss further in the following section.

Gradient Attributes

The attribute values for <linearGradient> and <radialGradient> allow us to specify the colors and coordinates of our gradients.

Here is a quick look at the attributes that will be used in the demos to follow:

ID

A gradient requires a unique ID in order for it to be called on through “fill” and “stroke” attributes.

x1, x2, y1, y2

The values within the x1, x2, y1, y2 attributes specify the start and end coordinates for linear gradients along the appropriate axis. These values default to “0” if left unspecified, except for x2 which defaults to “100%”.

cx, cy, r, fx, fy

Radial gradient attributes are similar to those of linear, except our coordinates will be handled much differently. Instead of being based on a straight line, these gradients will be mapped circularly.

cx, cy, and r (radius) define the outermost circle for the gradient, with this outer perimeter being the 100% stop point. fx and fy define the focal point of the gradient, with the 0% stop mapping to these values.

<stop>

Within the gradient element itself we include the <stop> nodes. The attribute values within <stop> nodes define the colors for our gradient, where they should be placed, and any opacity that we want applied.

The offset property indicates where the gradient stop is located. For linear gradients this location will be a distance along the gradient line, for radial gradients it will be a distance from the focal point to the edge of the mapped circle.

stop-color indicates what color will be used at the correlating stop point, and stop-opacity sets an opacity at this same point. Depending on how many stops we wish to use we can choose between creating subtle, gradual color changes with only a few stops, or create stripes with several closely mapped stops.

<animate>

<animate> element will allow us to select gradient attributes and properties and then assign different values to them over a specified duration of time. In short, we can move them! The <animate> element will reside within the element we wish to animate. Here is the structure for a basic animation on a rectangle:

      <defs>
          <radialGradient id="smallGradient" fy="90%">
            <stop offset="0%" stop-color="#f4c708"></stop>
            <stop offset="100%" stop-color="#f7e69a"></stop>
            <animate attributeName="fy" dur="700ms" from="90%" to="0%" repeatCount="indefinite" />
          </radialGradient>
          <radialGradient id="largeGradient" fy="90%">
            <stop offset="0%" stop-color="#ff8806"></stop>
            <stop offset="100%" stop-color="#d9574a"></stop>
            <animate attributeName="fy" dur="700ms" from="90%" to="0%" repeatCount="indefinite" />
          </radialGradient>
      </defs>

The animation will move the rectangle along the x axis 400px pixels from its starting point. The animation will complete within 5 seconds, and repeat indefinitely.

Attributes

Within the <animate> element we will use attributes to select our target and specify the details of the animation. Here is a look at the specific attributes we will focus on in the demos:

attributeName

attributeName defines the name of the target attribute to be animated. In taking another look at the animation code above, the attributeName value is “x” so that we can target and animate our shape on the x axis.

to, from

The “to” and “from” attributes indicate the initial and final value of the targeted attribute.

values

Within the <values> attribute we can create a list of values separated by semicolons, and the animation will apply these values in order over the duration of the action.

By including this attribute any “from” or “to” values within the same <animate> element will be ignored, meaning that it takes the place of these values once included so there is no need for them.

dur

The duration defines within what time span the animation should complete.

fill

While “fill” often refers to the interior color of SVG, it has a different meaning in the context of an <animate> attribute. We can set a value of “freeze” within this attribute so that the animation freezes once it is complete and does not restart.

repeatCount

The repeatCount attribute specifies the number of times an animation should take place. This value can be either a number, or “indefinite”.

Animating Gradients

To target gradients specifically we need to have an idea of what properties we would like to animate, like the stop-color, offset, and/or the specific coordinates.

When we reviewed the code for the moving rectangle animation above the <animate> element resided within the shape’s element, the <rect>. In order to animate gradient stops we place the <animate> element within the specific <stop> we intend to animate. To animate an attribute directly within the a <linearGradient> or <radialGradient> element, like coordinates for example, we position <animate> within the gradient element, but outside of the <stop> elements.

Here’s a look at the structure for an animation on the stop-color of a <stop> node.

<stop offset="0%" stop-color="#f4c708"></stop>
<stop offset="100%" stop-color="#f7e69a"></stop>
<animate attributeName="fy" dur="700ms" from="90%" to="0%" repeatCount="indefinite" />

Demos

To demonstrate the possibilities of animating SVG gradients we will look at some potential effects for a fictional camping site. The demos consist of animated gradients on fire, trees, and a skyline.

Demo 1: Fire

SVG Gradients

Within the fire SVG we are targeting two flames to fill and animate, and as mentioned all the details are listed within a <defs> element in the <svg>.

      <defs>
          <radialGradient id="smallGradient" fy="90%">
            <stop offset="0%" stop-color="#f4c708"></stop>
            <stop offset="100%" stop-color="#f7e69a"></stop>
            <animate attributeName="fy" dur="700ms" from="90%" to="0%" repeatCount="indefinite" />
          </radialGradient>
          <radialGradient id="largeGradient" fy="90%">
            <stop offset="0%" stop-color="#ff8806"></stop>
            <stop offset="100%" stop-color="#d9574a"></stop>
            <animate attributeName="fy" dur="700ms" from="90%" to="0%" repeatCount="indefinite" />
          </radialGradient>
      </defs>

There are two radial gradients, “smallGradient” and “largeGradient”. The same animation is applied to each gradient targeting the fy coordinate point and moving it from 90% to 0% within 700ms. The animation is set to take place indefinitely.

The assignment of these gradients is done by adding the gradient ID to the “fill” of the shape via a URL, for example:

fill=&quot;url(#largeGradient)&quot;

Demo 2: Trees

Tree preview

For the trees demo we will be adding the animation to the gradient stop-color. There are two gradients to represent different colors for the trees, one with dark shades of green and one with light. Each animation is essentially the same, the only difference being the colors used.

      <defs>
        <linearGradient id="darkGradient" x1="30%" y1="70%">
          <stop offset="0%" stop-color="#0b2d13">
            <animate attributeName="stop-color" values="#0b2d13; #79c98c" dur="3s" fill="freeze" />
          </stop>
          <stop offset="100%" stop-color="#79c98c">
          <animate attributeName="stop-color" values="#79c98c; #0b2d13" dur="3s" fill="freeze" />
          </stop>
        </linearGradient>

        <linearGradient id="lightGradient" x1="30%" y1="70%">
          <stop offset="0%" stop-color="#054f16">
            <animate attributeName="stop-color" values="#054f16; #91bc9c" dur="3s" fill="freeze" />
          </stop>
          <stop offset="100%" stop-color="#91bc9c">
            <animate attributeName="stop-color" values="#91bc9c; #054f16" dur="3s" fill="freeze" />
          </stop>
        </linearGradient>
      </defs>

The <animate> element resides within the 100% stop point for each gradient and targets the stop-color. The color values are animated through the values attribute, over a period of 3 seconds, and the animation is set to stop, or “freeze” once it completes one cycle.

Demo 3: Sky

Sky preview

The concept of a sunset is an ideal example of when animating a stop’s offset would be needed. There are two gradients here, each having a series of animated color changes. With an additional animation on the offset of the 100% stop point the point moves down (to 0) and then back up again.

      <defs>
        <linearGradient id="skyGradient" x1="100%" y1="100%">
          <stop offset="0%" stop-color="lightblue" stop-opacity=".5">
            <animate attributeName="stop-color" values="lightblue;blue;red;red;black;red;red;purple;lightblue" dur="14s" repeatCount="indefinite" />
          </stop>
          <stop offset="100%" stop-color="lightblue" stop-opacity=".5">
            <animate attributeName="stop-color" values="lightblue;orange;purple;purple;black;purple;purple;blue;lightblue" dur="14s" repeatCount="indefinite" />
            <animate attributeName="offset" values=".95;.80;.60;.40;.20;0;.20;.40;.60;.80;.95" dur="14s" repeatCount="indefinite" />    
          </stop>
        </linearGradient>
      </defs>

For the stop-color animations there’s a list of color values the gradient will cycle through within 14s. The additional offset animation changes the location of the 100% stop point through a series of numerical values, also within 14s.

It is important to mention here that while you should technically be able to use percentages when animating offset, and can do so without problems in Firefox, Chrome and Safari will not render the animation on the offset when percentage values are used within <animate>. The work around here is to simply avoid using percentages, as shown in the code above.

Conclusion

For this article, we discussed the basic structure of SVG gradients, how to utilize SVG SMIL animation once they are created, and reviewed some demos regarding how this can be handy in communicating to users.

Hopefully, all this inspires you to take a look at writing gradients within SVG code and get them moving all within the same SVG element.

Joni Trythall

Joni Trythall learns web design by day, and forgets it all by night. She is constantly trying to combine her love of learning code with her long time obsession of coloring mostly in the lines. Joni lives in always sunny Seattle, WA. You can find her code ramblings at jonibologna.com, Google+ or @jonitrythall.

Posts by Joni Trythall