- Transitioning Gradients
- Smooth CSS Gradient Transitions
- Animating and Transitioning Gradients with CSS and Javascript
- Transitioning between two gradients in CSS smoothly
- Multiple color gradient transitions
- Conclusion
- More Tips and Tricks for CSS
- Adding a Gradient Hover Effect to Buttons with CSS
- Alex Ivanovs
- Read also
- How to Get Gradient Hover Colors to Work
- HTML
- CSS
Transitioning Gradients
In, CSS, you can’t transition a background gradient. It sure would be nice if you could:
.gradient background-image: linear-gradient( to right, hsl(211, 100%, 50%), hsl(179, 100%, 30%) ); transition: background-image 0.5s linear; > .gradient:hover background-image: linear-gradient( to bottom, hsl(344, 100%, 50%), hsl(31, 100%, 40%) ); >
But, no. It jumps from one gradient to the other immediately, with no smooth transition between the two. So let’s hack it!
We can achieve this effect with the help of a pseudo-element and an opacity transform instead.
First, apply one gradient to the element. Then, position its pseudo-element to fill the element and apply the second gradient to that. To transition between the two gradients, transition the opacity of the pseudo-element.
.gradient position: relative; background-image: linear-gradient( to right, hsl(211, 100%, 50%), hsl(179, 100%, 30%) ); z-index: 1; > .gradient::before position: absolute; content: ''; top: 0; right: 0; bottom: 0; left: 0; background-image: linear-gradient( to bottom, hsl(344, 100%, 50%), hsl(31, 100%, 40%) ); z-index: -1; transition: opacity 0.5s linear; opacity: 0; > .gradient:hover::before opacity: 1; >
The pseudo-element is initially hidden via opacity: 0 . On hover, that transitions to an opacity: 1 . This produces the illusion of the main gradient transitioning to the pseudo-element’s gradient. It also takes a little bit of z-index work to ensure the pseudo-element stays positioned behind the content of the main element.
This takes a fair bit of code, unfortunately. But if you need this effect, this is the best (and only) way I’ve found so far to accomplish it.
Check out the full working example:
Smooth CSS Gradient Transitions
If you try to animate or transition a gradient in pure CSS, we end up with a little bit of an issue. All modern browsers do not natively transition colours in gradients smoothly. As such, we end up with a sudden change. That can be seen in the example below, where the transform transitions perfectly fine but the gradient does not, even though we are using transition: all 0.1s ease-out .
#gradient-button background: linear-gradient(180deg, #ff7147, #e0417f); padding: 0.5rem 1.5rem; transition: all 0.1s ease-out; font-weight: 500; font-size: 1.25rem; border-radius: 100px; transform: scale(1); margin: 0 0 2rem 1rem; > #gradient-button:hover background: linear-gradient(45deg, #0037ff, #00adff); transform: scale(1.1); >
Animating and Transitioning Gradients with CSS and Javascript
In this article, we’ll be looking at how to solve this problem, and we’ll cover how to smoothly animate a gradient transition with Javascript. That means creating a function which will be able to transition between two colors smoothly.
Although there is no native way to do this effect, we can do it with Javascript. The below button solves the problem, allowing us to smoothly animate gradient transitions with Javascript and some CSS when you hover over the button.
Transitioning between two gradients in CSS smoothly
The first step, is we need to create a function which allows us figure out a color between two colors. For this to work, we’ll need the color we start with, and the one we want to transition to.
The function we’ll create is shown below. It can support gradients with more than 2 colors — but for this we’ll just use two. We’ll also take the initial gradient color, and apply that to our button — so we can manipulate the gradient completely from our Javascript.
let element = 'gradient-button-transition'; // // DEFINE YOUR GRADIENT COLORS HERE // Pct refers to the percentage position of the gradient stop point. const gradientStopOne = [ pct: 0, color: r: 255, g: 113, b: 71 > >, // The first color in your gradient pct: 100, color: r: 0, g: 55, b: 255 > > // The color you want your first color to transition to ]; const gradientStopTwo = [ pct: 0, color: r: 224, g: 65, b: 127 > >, // The second color in your gradient pct: 100, color: r: 0, g: 173, b: 255 > > // The color you want your second color to transition to ] // Apply our gradient programmatically so we can completely manipulate the gradient from JS rather than CSS let c1 = gradientStopOne[0].color; let c2 = gradientStopTwo[0].color; document.getElementById('gradient-button-transition').style.background = `linear-gradient($angle>deg, rgb($c1.r>, $c1.g>, $c1.b>), rgb($c2.r>, $c2.g>, $c2.b>))`; // This function transitions between two rgb colors const getColor = function(pct, colorSet) for (var i = 1; i colorSet.length - 1; i++) if (pct colorSet[i].pct) break; > > // This conversion figures out the transition between two rgb values var lower = colorSet[i - 1]; var upper = colorSet[i]; var range = upper.pct - lower.pct; var rangePct = (pct - lower.pct) / range; var pctLower = 1 - rangePct; var pctUpper = rangePct; var color = r: Math.floor(lower.color.r * pctLower + upper.color.r * pctUpper), g: Math.floor(lower.color.g * pctLower + upper.color.g * pctUpper), b: Math.floor(lower.color.b * pctLower + upper.color.b * pctUpper) >; // And returns the rgb code return `rgb($color.r>, $color.g>, $color.b>)`; >
Now that we have a function which will let us transition between two colors, and have defined our gradients, We can start transitioning between them. We’ll create one function which will set an interval — depending on whether the user hovers or not, we will manipulate the direction of the animation.
Comments in the code below explains what we’re trying to do here. The interval runs every 16.67 miliseconds — or 60 times a second. This will give us a smooth 60 frames per second animation. Within the interval function, we calculate the total number of frames, and stop the animation when the transition time is up.
let transitionTime = 1000 // let previousTime, start = 0; // let angle = 180; // let animationDirection = 'forwards' // let intervalFrame; // let currentPct = 0; // let elapsed = 0; // // This is our animation which we run on hover const animateGradient = function() if(intervalFrame === undefined) intervalFrame = setInterval(() => let time = transitionTime / 1000; // time in seconds let numberOfFrames = time * 60; // 60 frames per second -> 1 second = 60 frames // If the animation is going forward if(animationDirection === 'forwards') // Add 1 to elapsed elapsed += 1; // The elapsed frames out of max frames currentPct = Math.min(elapsed / numberOfFrames, 1) * 100; > else // Otherwise we're going back - subtract 1 from ellapsed elapsed -= 1; // The elapsed frames out of max frames currentPct = Math.max(elapsed / numberOfFrames, 0) * 100; > // Calculate current color in this time for each gradient color let colorOne = getColor(currentPct, gradientStopOne); let colorTwo = getColor(currentPct, gradientStopTwo); // Generate CSS string let generateGradient = `linear-gradient($angle>deg, $colorOne>, $colorTwo>)`; // Add it to our background. document.getElementById(element).style.backgroundImage = generateGradient; // End the interval when we're done if(currentPct === 100 || currentPct === 0) clearInterval(intervalFrame); intervalFrame = undefined; > >, 16.667); // 60 frames per second > >;
Finally, we run all of this on hover in, and hover out. When the user hovers, we update the animation direction, so we can move the gradient towards the colors we want it to.
// On hover, run our animation document.getElementById('gradient-button-transition').addEventListener('mouseover', function() animationDirection = 'forwards'; animateGradient(); >); // On hover out, run our animation again, but backwards document.getElementById('gradient-button-transition').addEventListener('mouseleave', function() animationDirection = 'backwards'; animateGradient(); >);
Multiple color gradient transitions
Since we can have this run for multiple colors, and also run whenever we want — we can create some fun effects. Here is a button that automatically transitions between 4 different gradients:
Conclusion
Although not possible with CSS today, Javascript actually gives us a lot more flexibility to animate our gradient transitions smoothly. If you’ve found this useful, don’t forget to subscribe or follow me on twitter.
More Tips and Tricks for CSS
Adding a Gradient Hover Effect to Buttons with CSS
This is a practical example of how you can create a gradient-like hover effect for links and buttons, using the transition property. First, let’s create our link button, and then style it. And then if we render that, this is going to be the outcome: Hover over me! The first thing we have to do […]
| Reader Disclosure Disclosure: Our content is reader-supported. This means if you click on some of our links, then we may earn a commission.
This is a practical example of how you can create a gradient-like hover effect for links and buttons, using the transition property. First, let’s create our link button, and then style it.
.gradient-hover-effect < display: flex; padding: 0.875em 2em; background: linear-gradient(90deg, #3f51b5, transparent) #2196f3; font-family: inherit; color: #fff; text-decoration: none; transition: background-color 1s; place-content: center; >.gradient-hover-effect:hover, .gradient-hover-effect:focus
And then if we render that, this is going to be the outcome:
The first thing we have to do is style our button or link. In this example, I am directly applying a background to the element as a linear-gradient . The nice thing about this is that you can actually just use a normal color as well, and then apply a different color for the transition.
Then, we specify transition which we use to call background-color and we also apply a transition time of 1s but this can be lower or higher, depending on the speed that you’re after for the animation itself. Feel free to check out my article on CSS animations.
And finally, we create a new :hover & :focus specification for our button, in which we set the actual background color we want to use for the gradient effect.
The CSS transition shorthand has a lot of possible properties. Including the ability to shift direction, but also to query multiple elements at once. MDN has all the goodies on the topic.
Alex Ivanovs
Alex is a full-stack developer with more than 15 years of experience. After many years of threading the self-taught path, he discovered a natural passion for writing. His past work includes helping build the Huffington Post Code column and working with publishers such as Entrepreneur, TheNextWeb, and many prominent tech startups.
Read also
How to Get Gradient Hover Colors to Work
Even the most skilled of designers and developers struggle with small little elements of code. One of the trickiest things to nail down are gradients and transition effects. They rarely play nicely with each other.
However, gradient hovers and transitions can give your web design and navigation a slight boost by emphasizing an icon or button a little more for your website visitors. This tutorial will help you avoid the tricky pitfalls of perfecting CSS gradients in order to create a seamless transition functionality.
HTML
The HTML is fairly simple, with a few Bootstrap 4 classes for spacing classes.
CSS
CSS styles are used to form your gradients and create the transition functionality.
Try this out for your own website! Before you code, be sure to check out the finished product on the JSFiddle below. In order to see just how this works, hover your mouse over either of the two buttons and notice the subtle (yet definitive) gradient differences before and after you hover.
Scott Madara
Contributions Editor here at Solodev. Want to be featured on the Solodev Blog? Get in touch.
Follow me on Twitter
RELATED POSTS