What you can do, however, is have two gradients, stacked on top of each other, and then transition the opacity of the top element. The opacity property is ubiquitous and animatable, making it perfect for this job.

The method I am going to show you makes use of the :before psudo-element. You, of course, could add an additional element to your HTML if you’d like, but for the sake of keeping our markup clean and concerns separated, I prefer to use the :before element.

Let’s start with our main element. Let’s give it some basic styles and a gradient (once again prefix-free):

I’m using Less here, but plain old CSS will do the trick (if you’re still living in 2005).

The important part here is that there is an element with a gradient, and it’s z-index is set to 100. I avoid z-index as a rule, as it adds another dimension of complexity that otherwise would not need to be present in most projects. The only reason I’m setting it here is so that any content inside our element (such as text) will appear in front of the psudo-element, which will have a background gradient that obstructs the view of the element’s content.

Speaking of, lets style out our psudo-element:

Some of the styles are purely presentational (like border-radius) and are not crucial to this experiment.

The takeaway here is that the :before element has the opposite (or whatever) gradient that we want to transition to, it’s z-index is set to negative and it’s opacity is set to zero.

We’ll wrap this up by adding our transitions and hover states:

Now when we hover over our .button, the :before element (with it’s opposite/different gradient) fades in smoothly. Pretty neat trick, eh? You can check out a live example in the CodePen example below:

What I’ve done above is made this effect into a reusable mixin, and then applied it to the <body> element as well to create an interesting effect whenever the window is hovered over. I’ve created mixins for both Less and Sass if you’d like to drop this somewhere and test it out:

I still like this solution more than other ones, because CSS is my homeboy. Having said that, I still feel like SVG is probably the “correct” solution. Sometimes animating between two gradients in CSS can cause the color to get kind of muddy mid-transition in some browsers, something that I believe SVG would be a lot better at handling. But I mean you can’t beat the ease of CSS, so it’s damn temping to take this route.

Let me know how this works for you, as well as any suggestions you may have to build upon what’s been done here.

Special Thanks to Webucator

I would like to thank Brian and the team from Webucator for producing the following video that discusses this technique. You should definitely go watch their other videos and follow them on the Twitter. Thanks guys!