Smooth Background Color Looping Animation

November 24, 2015Category: Tutorial, WebTags: ,

I recently had a need to have the background color of an element on a webpage slowly change color, fading through the rainbow. Since it’s 2015, we don’t want to use JS; we want to use CSS animation. The question is what to animate. After looking around, the only method I found is the most obvious one: animate the element’s background.

Method 1 – Animate Background

#fading1 {
    height:200px;
    width:100%;
    background: black;
    animation:fadingAnimation 40s infinite;
}
@keyframes fadingAnimation {
    0%   { background: red; }
    10%  { background: orange; }
    20%  { background: yellow; }
    30%  { background: Chartreuse; }
    40%  { background: rgb(0,170,0); }
    50%  { background: teal; }
    60%  { background: turquoise; }
    70%  { background: blue; }
    80%  { background: indigo; }
    90%  { background: purple; }
    100% { background: red; }
}

The problem with the above method is that it isn’t smooth. It’s jerky. Each color fades to the next, and then pauses. I want a smooth transition that never stops. However, there is a solution, and that solution is a combination of linear-gradient and animating the background-position style.


Method 2 – Animate Background-Position

Say we take an element and give it a linear gradient of the entire rainbow:

#fading2 {
    height:200px;
    width:100%;
    background:linear-gradient(to bottom, red, orange, yellow, Chartreuse, rgb(0,170,0), teal, turquoise, blue, indigo, purple, red);
}

Next, we use the background-size style to stretch the gradient vertically, set it to not repeat, and set it to center horizontally but start at the top vertically. The further we stretch, the more smooth the final animation is going to be. So lets go all the way to 100000%. I get that it’s a lot, but the browser won’t have any trouble.

#fading3 {
    height:200px;
    width:100%;
    background:linear-gradient(to bottom, red, orange, yellow, Chartreuse, rgb(0,170,0), teal, turquoise, blue, indigo, purple, red);
    background-repeat:no-repeat;
    background-size:100% 100000%;
    background-position:center 0%;
}

It helps to imagine that the rainbow is now stretched down, way way down, out of view, and that it’s a very smooth transition between colors. Now all we have to do is animate the background-position and slide the background upwards. The animation code is actually a lot more simple than Method 1’s code.

#fading4 {
    height:200px;
    width:100%;
    background:linear-gradient(to bottom, red, orange, yellow, Chartreuse, rgb(0,170,0), teal, turquoise, blue, indigo, purple, red);
    background-repeat:no-repeat;
    background-size:100% 100000%;
    background-position:center 0%;
    animation:smoothFadingAnimation 40s infinite;
}
@keyframes smoothFadingAnimation {
    0%   {background-position:center 0%;}
    100%  {background-position:center 100%;}
}

As you can see above, it’s smoothly changing colors, without ever stopping.


Side by Side Comparison

Full Demo

Further Thoughts, Room For Improvement

The method could be improved with tweaks to the color sequence. There are some places where the colors change faster than others, and tweaks to the actual linear gradient would improve the final transition. Even so it’s better than existing methods

Additionally, the color red lasts for twice as long as any other color, because it’s the beginning and end color. It’s necessary to ensure a smooth transition from 100% back go 0, but is does cause that color to last longer.

Feel free to leave a comment with ideas for addressing these issues.