alt
alt

Reputation: 13947

Use CSS3 transitions with gradient backgrounds

I'm trying to transition on hover with CSS over a thumbnail so that on hover, the background gradient fades in. The transition isn't working, but if I simply change it to an rgba() value, it works fine.

Are gradients not supported? I tried using an image too, it won't transition the image either.

I know it's possible, as in another post someone did it, but I can't figure out how exactly. Any help? Here's some CSS to work with:

#container div a {
  -webkit-transition: background 0.2s linear;
  -moz-transition: background 0.2s linear;
  -o-transition: background 0.2s linear;
  transition: background 0.2s linear;
  position: absolute;
  width: 200px;
  height: 150px;
  border: 1px #000 solid;
  margin: 30px;
  z-index: 2
}

#container div a:hover {
  background: -webkit-gradient(radial, 100 75, 100, 100 75, 0, from(rgba(0, 0, 0, .7)), to(rgba(0, 0, 0, .4)))
}

Upvotes: 304

Views: 511570

Answers (21)

bprdev
bprdev

Reputation: 1048

(2025) I think I came up with a decent solution.

<body class='theme-light'>
  <div class="overlay" id="overlay_light_theme" role='presentation'></div>
  <div class="overlay" id="overlay_dark_theme" role='presentation'></div>
</body>


body {
  background-color: #EAFCFC;
}

.overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 0.7s ease-in-out;
}

.theme-light #overlay_light_theme {
  background: linear-gradient(135deg, #EAFCFC, #87D3CD, #EAFCFC);
  opacity: 1;
}

.theme-dark #overlay_dark_theme {
  background: linear-gradient(135deg, #6EACDA, #03346E, #6EACDA);
  opacity: 1;
}

And then you write some javascript to toggle the classes. Here is a Codepen example. Note the background color on <body>. Pick a color in one of your gradients to prevent a brief flash of a white background in between fades.

Upvotes: 0

Ricardo Zea
Ricardo Zea

Reputation: 10282

For what it's worth, here's a Sass mixin:

Usage:

@include gradientAnimation(red, blue, .6s);

Mixin:

@mixin gradientAnimation( $start, $end, $transTime ){
    background-size: 100%;
    background-image: linear-gradient($start, $end);
    position: relative;
    z-index: 100;
    &:before {
        background-image: linear-gradient($end, $start);
        content: "";
        display: block;
        height: 100%;
        position: absolute;
        top: 0; left: 0;
        opacity: 0;
        width: 100%;
        z-index: -100;
        transition: opacity $transTime;
    }
    &:hover:not(:disabled) {
        &:before {
            opacity: 1;
        }
    }
}

Here's a demo on CodePen: https://codepen.io/ricardozea/pen/wvVQBzQ/c68180a7523233c86a5df0279586d8a3?editors=1100

Taken from this awesome post on Medium from Dave Lunny: https://medium.com/@dave_lunny/animating-css-gradients-using-only-css-d2fd7671e759

Upvotes: 29

Mentalist
Mentalist

Reputation: 1689

Here's a quick and simple method using background-blend-mode

.grad {
  /* initial appearance (not relevant to background) */
  display: flex;
  justify-content: center;
  align-items: center;
  width: 180px;
  height: 100px;
  cursor: pointer;
  border-radius: 8px;
  font-family: sans-serif;
  border-width: 0;
  
  /* gradient styling */
  transition: 0.5s background-color;
  background-color: #888; /* initial luminosity */
  background-image: linear-gradient(DodgerBlue, MediumSlateBlue);
  background-blend-mode: color;
}
.grad:hover,
.grad:active {
  background-color: #aaa; /* hover (or active) state luminosity */
}
<!doctype html>
<html lang="en">
<head>
</head>
<body>
<button class="grad">hover or tap</button>
</body>
</html>

It only transitions between two luminosity values, so use it in cases where a simple effect is sufficient. It's a CSS only solution and doesn't require preparing an image. (Although it can of course be used with an image too.)

More on the background-blend-mode property

Reference of blend mode types

Upvotes: 1

Mahozad
Mahozad

Reputation: 24792

It is now possible to animate gradients with @property in CSS:

@property --myColor1 {
  syntax: '<color>';
  initial-value: magenta;
  inherits: false;
}

@property --myColor2 {
  syntax: '<color>';
  initial-value: #00ff00;
  inherits: false;
}

The rest is regular CSS.
Set the variables as initial gradient colors and also set the transition of those variables:

div {
  /* Optional: change initial value of the variables */
  /* --myColor1: #f64; --myColor2: brown; */

  background: linear-gradient(var(--myColor1), var(--myColor2));
  transition: --myColor1 3s, --myColor2 3s;
}

Then, on the desired rule, set new values for the variables:

div:hover {  
  --myColor1: #f00;
  --myColor2: yellow;
}

@property --myColor1 {
  syntax: '<color>';
  initial-value: #0f0;
  inherits: false;
}

@property --myColor2 {
  syntax: '<color>';
  initial-value: rgb(40, 190, 145);
  inherits: false;
}

div {
  width: 200px;
  height: 100px;
  background: linear-gradient(var(--myColor1), var(--myColor2));
  transition: --myColor1 3s, --myColor2 3s;
}

div:hover {
  --myColor1: red;
  --myColor2: #E1AF2F;
}
<div>Hover over me</div>

See the full description and example here and refer here for @property specification.
The @property rule is part of the CSS Houdini technology. For more information refer here and here and see this video.

Upvotes: 137

Michael Mullany
Michael Mullany

Reputation: 31805

This is now possible using the @property workaround. Please see @Mahozad's answer.


Original Answer:

Gradients don't support transitions yet (although the current spec says they should support like gradient to like gradient transitions via interpolation.).

If you want a fade-in effect with a background gradient, you have to set an opacity on a container element and 'transition` the opacity.

(There have been some browser releases that supported transitions on gradients (e.g IE10. I tested gradient transitions in 2016 in IE and they seemed to work at the time, but my test code no longer works.)

October 2018 Update: Gradient transitions with un-prefixed new syntax [e.g. radial-gradient(...)] now confirmed to work (again?) on Microsoft Edge 17.17134. I don't know when this was added. Still not working on latest Firefox & Chrome / Windows 10.

Upvotes: 226

BradChesney79
BradChesney79

Reputation: 678

Welcome to 2023 on a super old post. But, I landed here and obviously you did also.

CSS Only

https://jsfiddle.net/BradChesney79/rpa8v50t/

Markup:

<div class="fx-button">
<div class="button-content">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAhCAYAAAALboFLAAABhGlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV+/UKTFwQ4iHTJUB7EgKuKoVShChVArtOpgcukXNGlIUlwcBdeCgx+LVQcXZ10dXAVB8APE1cVJ0UVK/F9SaBHjwXE/3t173L0D/M0qU83gOKBqlpFJJYVcflXoeUUQIUQQw6jETH1OFNPwHF/38PH1LsGzvM/9OSJKwWSATyCeZbphEW8QT29aOud94igrSwrxOfGYQRckfuS67PIb55LDfp4ZNbKZeeIosVDqYrmLWdlQiaeI44qqUb4/57LCeYuzWq2z9j35C8MFbWWZ6zRjSGERSxAhQEYdFVRhIUGrRoqJDO0nPfxDjl8kl0yuChg5FlCDCsnxg//B727N4uSEmxROAqEX2/4YBnp2gVbDtr+Pbbt1AgSegSut4681gZlP0hsdLX4E9G8DF9cdTd4DLneAwSddMiRHCtD0F4vA+xl9Ux4YuAX61tze2vs4fQCy1FX6Bjg4BEZKlL3u8e7e7t7+PdPu7wdXSnKcEOSXsgAAAAZiS0dEAKMAmwCI3OECOgAAAAlwSFlzAAAuIwAALiMBeKU/dgAAAAd0SU1FB+cEBQ8XBXt+4EwAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAABn0lEQVQ4y02UQZJjIQxDn4Rz/7nCrOeEqQlWLww/vUlR+WDZTwL9+/snpAlBLAAs0QkSSKJs0b1YBCQiIUQZEgCoz/9NAh/CfIZtkTQILFPLphMiIALNRmKYFdU92sHPhiBkgRphyssALDFi0qkCWEimktCnQRlo5keCT4BN7b2JjBLSAhnRTz9I1FqLzowvmWQmCsMIgUnONMxpQZLZMH9SO5m1IOlv80cKRJGQDF0pY8eZjEu872hA0wP0yM9K1OtVdPdBsAhgBq41ttfuTXI49zTXBPnyC2V8FExuE4H0o0eNWZk83al4NKenz2c/p/FUUyYRQoQMzLsnV+qBO4rVCeked3tgXjsu+fJa57iQ/SQ9OpkCisMoYioC+1pzBql61bEl4DWkEyLBlXu/3xy3CB/SYOtJBECtVd/G7amkb/MEqrtJQnqPDDrs9QtB91euQ3efe3Dpi3oSmCm/amEy8nruXU8FgWRI0z4X9PZki9Z9KuYt8C+fsSgQT+btyXjOvUtIQslC+aYWglYNSHtg9t6TwA6Rz0vQ493J2g8fnASMeeRW2QAAAABJRU5ErkJggg==" />
<span class="button-text">DESKTOP BUTTON WITH COLOR SHIFT</span>
</div>
</div>
<p>
Drop shadow intrudes into immediate space around the element.
</p>
<p>
Not a particular issue, but something to be aware of.
</p>

CSS:

p {
   border: 1px red solid;
   margin: 0;
   padding: 0;"
}


.fx-button {
  background-image: linear-gradient(15deg, #a09486, #d2c7af);
  border: 1px red solid;
  box-shadow: 5px 5px 13px -4px rgba(0, 0, 0, 0.35);
  -webkit-box-shadow: 5px 5px 13px -4px rgba(0, 0, 0, 0.35);
  color: white;
  height: 33px;
  margin: 0;
  paddng: 0;
  position: relative;
  vertical-align: middle;
  width: fit-content;
  z-index: 1;
}

.fx-button::before {
  background-image: linear-gradient(15deg, #d2c7af, #a09486);
  bottom: 0;
  content: "";
  left: 0;
  opacity: 0;
  position: absolute;
  right: 0;
  top: 0;
  transition: opacity 0.2s linear;
  z-index: -1;
}
.fx-button:hover::before {
  opacity: 1;
}

.button-text {
  border: 0;
  font-family: sans-serif;
  font-size: 12px;
  height: auto;
  margin: 0;
  padding: 0 10px 0 2px;
  position: relative;
  top: -11px;
}
.button-content {
  border: 0;
  height: 33px;
  margin: 0;
  padding: 0;
  width: fit-content;
  vertical-align: middle;
}

Upvotes: 1

Matrix
Matrix

Reputation: 53

Thank You Very much

.element {
  position: relative;
  width: 200px;
  height: 150px;
  background-image: linear-gradient(45deg, blue, aqua);
  z-index: 2;
}

.element::before {
  position: absolute;
  content: "";
  inset: 0; /* same as { top: 0; right: 0; bottom: 0; left: 0; } */
  background-image: linear-gradient(to bottom, red, orange);
  z-index: 1;
  opacity: 0;
  transition: opacity 0.25s linear;
}

.element:hover::before {
  opacity: 1;
}
<body>
  <div class="element"></div>
</body>

Upvotes: 1

Felipe Chernicharo
Felipe Chernicharo

Reputation: 4547

::before, the CSS pseudo-element can easily do the trick!

.element {
  position: relative;
  width: 200px;
  height: 150px;
  background-image: linear-gradient(45deg, blue, aqua);
  z-index: 2;
}

.element::before {
  position: absolute;
  content: "";
  inset: 0; /* same as { top: 0; right: 0; bottom: 0; left: 0; } */
  background-image: linear-gradient(to bottom, red, orange);
  z-index: 1;
  opacity: 0;
  transition: opacity 0.25s linear;
}

.element:hover::before {
  opacity: 1;
}
<body>
  <div class="element"></div>
</body>

All you have to do is use the ::before pseudo-element with zero opacity.

On :hover, switch ::before's opacity to 1 and if you follow a few simple steps, you should get your transition working.

  1. Set the element's background gradient using background-image
  2. Use the ::before pseudo-element with opacity zero to setup your next gradient
  3. set opacity to 1 inside :hover::before
  4. make sure your ::before has:
    • position absolute
    • content: ""
    • a lower z-index than the default element
    • zero top, bottom, left, and right (or simply inset: 0)
    • transition targeting opacity with a time interval of your preference

And that's it! Now you should be able tweak your transition with whatever duration / delay / timing-function you like!

Upvotes: 29

Fralle
Fralle

Reputation: 937

A much cleaner solution would be to set the background color and use a mask-image.

#container div a {
  background-color: blue;
  transition: background 0.2s linear;
  width: 200px;
  height: 150px;
  mask-image: radial-gradient(circle at 50% 50%, rgba(0, 0, 0, .7), rgba(0, 0, 0, .4));
}

#container div a:hover { 
  background-color: red;
}

Upvotes: 1

Skylin R
Skylin R

Reputation: 2271

I know that is old question but mabye someone enjoy my way of solution in pure CSS. Gradient fade from left to right.

.contener{   
  width:300px;
  height:200px;
  background-size:cover;
  border:solid 2px black;
}
.ed {
    width: 0px;
    height: 200px;
    background:linear-gradient(to right, rgba(0,0,255,0.75), rgba(255,0,0,0.75));
    position: relative;
    opacity:0;
    transition:width 20s, opacity 0.6s;
}

.contener:hover .ed{
    width: 300px;
    background:linear-gradient(to right, rgba(0,0,255,0.75), rgba(255,0,0,0.75));
    position: relative;
    opacity:1;
    transition:width 0.4s, opacity 1.1s;
    transition-delay: width 2s;
    
    animation-name: gradient-fade;
    animation-duration: 1.1s;   
    -webkit-animation-name: gradient-fade; /* Chrome, Safari, Opera */
    -webkit-animation-duration: 1.1s; /* Chrome, Safari, Opera */
}




/* ANIMATION */
@-webkit-keyframes gradient-fade {
    0%   {background:linear-gradient(to right, rgba(0,0,255,0), rgba(255,0,0,0));}
    2%  {background:linear-gradient(to right, rgba(0,0,255,0.01875), rgba(255,0,0,0));}
    4%  {background:linear-gradient(to right, rgba(0,0,255,0.0375), rgba(255,0,0,0.0));}
    6%  {background:linear-gradient(to right, rgba(0,0,255,0.05625), rgba(255,0,0,0.0));}
    8% {background:linear-gradient(to right, rgba(0,0,255,0.075), rgba(255,0,0,0));}
    10%  {background:linear-gradient(to right, rgba(0,0,255,0.09375), rgba(255,0,0,0));}
    12%   {background:linear-gradient(to right, rgba(0,0,255,0.1125), rgba(255,0,0,0));}
    14%  {background:linear-gradient(to right, rgba(0,0,255,0.13125), rgba(255,0,0,0));}
    16%  {background:linear-gradient(to right, rgba(0,0,255,0.15), rgba(255,0,0,0));}
    18%  {background:linear-gradient(to right, rgba(0,0,255,0.16875), rgba(255,0,0,0));}
    20% {background:linear-gradient(to right, rgba(0,0,255,0.1875), rgba(255,0,0,0));}
    22%  {background:linear-gradient(to right, rgba(0,0,255,0.20625), rgba(255,0,0,0.01875));}
    24%   {background:linear-gradient(to right, rgba(0,0,255,0.225), rgba(255,0,0,0.0375));}
    26%  {background:linear-gradient(to right, rgba(0,0,255,0.24375), rgba(255,0,0,0.05625));}
    28%  {background:linear-gradient(to right, rgba(0,0,255,0.2625), rgba(255,0,0,0.075));}
    30%  {background:linear-gradient(to right, rgba(0,0,255,0.28125), rgba(255,0,0,0.09375));}
    32% {background:linear-gradient(to right, rgba(0,0,255,0.3), rgba(255,0,0,0.1125));}
    34%  {background:linear-gradient(to right, rgba(0,0,255,0.31875), rgba(255,0,0,0.13125));}
    36%   {background:linear-gradient(to right, rgba(0,0,255,0.3375), rgba(255,0,0,0.15));}
    38%  {background:linear-gradient(to right, rgba(0,0,255,0.35625), rgba(255,0,0,0.16875));}
    40%  {background:linear-gradient(to right, rgba(0,0,255,0.375), rgba(255,0,0,0.1875));}
    42%  {background:linear-gradient(to right, rgba(0,0,255,0.39375), rgba(255,0,0,0.20625));}
    44% {background:linear-gradient(to right, rgba(0,0,255,0.4125), rgba(255,0,0,0.225));}
    46%  {background:linear-gradient(to right, rgba(0,0,255,0.43125),rgba(255,0,0,0.24375));}
    48%   {background:linear-gradient(to right, rgba(0,0,255,0.45), rgba(255,0,0,0.2625));}
    50%  {background:linear-gradient(to right, rgba(0,0,255,0.46875), rgba(255,0,0,0.28125));}
    52%  {background:linear-gradient(to right, rgba(0,0,255,0.4875), rgba(255,0,0,0.3));}
    54%   {background:linear-gradient(to right, rgba(0,0,255,0.50625), rgba(255,0,0,0.31875));}
    56%  {background:linear-gradient(to right, rgba(0,0,255,0.525), rgba(255,0,0,0.3375));}
    58%  {background:linear-gradient(to right, rgba(0,0,255,0.54375), rgba(255,0,0,0.35625));}
    60%  {background:linear-gradient(to right, rgba(0,0,255,0.5625), rgba(255,0,0,0.375));}
    62% {background:linear-gradient(to right, rgba(0,0,255,0.58125), rgba(255,0,0,0.39375));}
    64%  {background:linear-gradient(to right,rgba(0,0,255,0.6), rgba(255,0,0,0.4125));}
    66%   {background:linear-gradient(to right, rgba(0,0,255,0.61875), rgba(255,0,0,0.43125));}
    68%  {background:linear-gradient(to right, rgba(0,0,255,0.6375), rgba(255,0,0,0.45));}
    70%  {background:linear-gradient(to right, rgba(0,0,255,0.65625), rgba(255,0,0,0.46875));}
    72%  {background:linear-gradient(to right, rgba(0,0,255,0.675), rgba(255,0,0,0.4875));}
    74% {background:linear-gradient(to right, rgba(0,0,255,0.69375), rgba(255,0,0,0.50625));}
    76%  {background:linear-gradient(to right, rgba(0,0,255,0.7125), rgba(255,0,0,0.525));}
    78%   {background:linear-gradient(to right, rgba(0,0,255,0.73125),,rgba(255,0,0,0.54375));}
    80%  {background:linear-gradient(to right, rgba(0,0,255,0.75), rgba(255,0,0,0.5625));}
    82%  {background:linear-gradient(to right, rgba(0,0,255,0.75), rgba(255,0,0,0.58125));}
    84%  {background:linear-gradient(to right, rgba(0,0,255,0.75),rgba(255,0,0,0.6));}
    86% {background:linear-gradient(to right, rgba(0,0,255,0.75), rgba(255,0,0,0.61875));}
    88%  {background:linear-gradient(to right, rgba(0,0,255,0.75), rgba(255,0,0,0.6375));}
    90%   {background:linear-gradient(to right, rgba(0,0,255,0.75), rgba(255,0,0,0.65625));}
    92%  {background:linear-gradient(to right, rgba(0,0,255,0.75), rgba(255,0,0,0.675));}
    94%  {background:linear-gradient(to right, rgba(0,0,255,0.75),rgba(255,0,0,0.69375));}
    96%  {background:linear-gradient(to right, rgba(0,0,255,0.75), rgba(255,0,0,0.7125));}
    98% {background:linear-gradient(to right, rgba(0,0,255,0.75), rgba(255,0,0,0.73125),);}
    100%  {background:linear-gradient(to right, rgba(0,0,255,0.75), rgba(255,0,0,0.75));}
}
<div class="contener" style="">
  <div class="ed"></div>
</div>

Upvotes: 17

rushkeldon
rushkeldon

Reputation: 1391

I wanted to have a div appear like a 3D sphere and transition through colors. I discovered that gradient background colors don't transition (yet). I placed a radial gradient background in front of the element (using z-index) with a transitioning solid background.

/* overlay */
z-index : 1;
background : radial-gradient( ellipse at 25% 25%, rgba( 255, 255, 255, 0 ) 0%, rgba( 0, 0, 0, 1 ) 100% );

then the div.ball underneath:

transition : all 1s cubic-bezier(0.25, 0.46, 0.45, 0.94);

then changed the background color of the div.ball and voila!

https://codepen.io/keldon/pen/dzPxZP

Upvotes: 3

Raymond
Raymond

Reputation: 1429

Based on the css code in your question, I have try code as follows and it works for me (run the code snippet), and please try by yourself :

#container div a {
  display: inline-block;
  margin-top: 10%;
  padding: 1em 2em;
  font-size: 2em;
  color: #fff;
  font-family: arial, sans-serif;
  text-decoration: none;
  border-radius: 0.3em;
  position: relative;
  background-color: #ccc;
  background-image: linear-gradient(to top, #C0357E, #EE5840);
  -webkit-backface-visibility: hidden;
  z-index: 1;
}
     
#container div a:after {
  position: absolute;
  content: '';
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 0.3em;
  background-image: linear-gradient(to top, #6d8aa0, #343436);
  transition: opacity 0.5s ease-out;
  z-index: 2;
  opacity: 0;
}
    
#container div a:hover:after {
  opacity: 1;
}
#container div a span {
  position: relative;
  z-index: 3;
}
<div id="container"><div><a href="#"><span>Press Me</span></a></div></div>

Based on the css code in your question, I have try code as follows and it works for me, and please try by yourself :

    #container div a {
  display: inline-block;
  margin-top: 10%;
  padding: 1em 2em;
  font-size: 2em;
  color: #fff;
  font-family: arial, sans-serif;
  text-decoration: none;
  border-radius: 0.3em;
  position: relative;
  background-color: #ccc;
  background-image: linear-gradient(to top, #C0357E, #EE5840);
  -webkit-backface-visibility: hidden;
  z-index: 1;
}

#container div a:after {
  position: absolute;
  content: '';
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 0.3em;
  background-image: linear-gradient(to top, #6d8aa0, #343436);
  transition: opacity 0.5s ease-out;
  z-index: 2;
  opacity: 0;
}

#container div a:hover:after {
  opacity: 1;
}
#container div a span {
  position: relative;
  z-index: 3;
}

Does it works for you? Change the color based on your need :)

Upvotes: 8

Alan
Alan

Reputation: 2087

One work-around is to transition the background position to give the effect that the gradient is changing: http://sapphion.com/2011/10/css3-gradient-transition-with-background-position/

CSS3 gradient transition with background-position

Although you can’t directly animate gradients using the CSS transition property, it is possible to animate the background-position property to achieve a simple gradient animation:

The code for this is dead simple:

#DemoGradient{  
    background: -webkit-linear-gradient(#C7D3DC,#5B798E);  
    background: -moz-linear-gradient(#C7D3DC,#5B798E);  
    background: -o-linear-gradient(#C7D3DC,#5B798E);  
    background: linear-gradient(#C7D3DC,#5B798E);  
  
    -webkit-transition: background 1s ease-out;  
    -moz-transition: background 1s ease-out;  
    -o-transition: background 1s ease-out;  
    transition: background 1s ease-out;  
  
    background-size:1px 200px;  
    border-radius: 10px;  
    border: 1px solid #839DB0;  
    cursor:pointer;  
    width: 150px;  
    height: 100px;  
}  
#DemoGradient:Hover{  
    background-position:100px;  
}  
<div id="DemoGradient"></div>  

Upvotes: 134

Shikkediel
Shikkediel

Reputation: 5205

Can't hurt to post another view since there's still not an official way to do this. Wrote a lightweight jQuery plugin with which you can define a background radial gradient and a transition speed. This basic usage will then let it fade in, optimised with requestAnimationFrame (very smooth) :

$('#element').gradientFade({

    duration: 2000,
    from: '(20,20,20,1)',
    to: '(120,120,120,0)'
});

http://codepen.io/Shikkediel/pen/xbRaZz?editors=001

Keeps original background and all properties intact. Also has highlight tracking as a setting :

http://codepen.io/Shikkediel/pen/VYRZZY?editors=001

Upvotes: 2

aug
aug

Reputation: 11714

Found a nice hack on codepen that modifies the opacity property but achieves that fade from one gradient to another by leveraging pseudo-elements. What he does is he sets an :after so that when you change the opacity of the actual element, the :after element shows up so it looks as if it were a fade. Thought it'd be useful to share.

Original codepen: http://codepen.io/sashtown/pen/DfdHh

.button {
  display: inline-block;
  margin-top: 10%;
  padding: 1em 2em;
  font-size: 2em;
  color: #fff;
  font-family: arial, sans-serif;
  text-decoration: none;
  border-radius: 0.3em;
  position: relative;
  background-color: #ccc;
  background-image: linear-gradient(to top, #6d8aa0, #8ba2b4);
  -webkit-backface-visibility: hidden;
  z-index: 1;
}
.button:after {
  position: absolute;
  content: '';
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 0.3em;
  background-image: linear-gradient(to top, #ca5f5e, #d68584);
  transition: opacity 0.5s ease-out;
  z-index: 2;
  opacity: 0;
}
.button:hover:after {
  opacity: 1;
}
.button span {
  position: relative;
  z-index: 3;
}
body {
  text-align: center;
  background: #ddd;
}
<a class="button" href="#"><span>BUTTON</span></a>

Upvotes: 3

Davton
Davton

Reputation: 89

I use this at work :) IE6+ https://gist.github.com/GrzegorzPerko/7183390

Don't forget about <element class="ahover"><span>Text</span></a> if you use a text element.

.ahover {
    display: block;
    /** text-indent: -999em; ** if u use only only img **/
    position: relative;
}
.ahover:after {
    content: "";
    height: 100%;
    left: 0;
    opacity: 0;
    position: absolute;
    top: 0;
    transition: all 0.5s ease 0s;
    width: 100%;
    z-index: 1;
}
.ahover:hover:after {
    opacity: 1;
}
.ahover span {
    display: block;
    position: relative;
    z-index: 2;
}

Upvotes: 2

Jens
Jens

Reputation: 324

As stated. Gradients aren't currently supported with CSS Transitions. But you could work around it in some cases by setting one of the colors to transparent, so that the background-color of some other wrapping element shines through, and transition that instead.

Upvotes: 2

vinzcelavi
vinzcelavi

Reputation: 838

A solution is to use background-position to mimic the gradient transition. This solution was used in Twitter Bootstrap a few months ago.

Update

http://codersblock.blogspot.fr/2013/12/gradient-animation-trick.html?showComment=1390287622614

Here is a quick example:

Link state

 .btn {
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 12px;
  font-weight: 300;
  position: relative;
  display: inline-block;
  text-decoration: none;
  color: #fff;
  padding: 20px 40px;
  background-image: -moz-linear-gradient(top, #50abdf, #1f78aa);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#50abdf), to(#1f78aa));
  background-image: -webkit-linear-gradient(top, #50abdf, #1f78aa);
  background-image: -o-linear-gradient(top, #50abdf, #1f78aa);
  background-image: linear-gradient(to bottom, #50abdf, #1f78aa);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff50abdf', endColorstr='#ff1f78aa', GradientType=0);
  background-repeat: repeat-y;
  background-size: 100% 90px;
  background-position: 0 -30px;
  -webkit-transition: all 0.2s linear;
     -moz-transition: all 0.2s linear;
       -o-transition: all 0.2s linear;
          transition: all 0.2s linear;
}

Hover state

.btn:hover {
   background-position: 0 0;
}

Upvotes: 36

Frantisek Were Bouska
Frantisek Were Bouska

Reputation: 41

Partial workaround for gradient transition is to use inset box shadow - you can transition either the box shadow itself, or the background color - e.g. if you create inset box shadow of the same color as background and than use transition on background color, it creates illusion that plain background is changing to radial gradient

.button SPAN {
    padding: 10px 30px; 
    border: 1px solid ##009CC5;

    -moz-box-shadow: inset 0 0 20px 1px #00a7d1;
    -webkit-box-shadow: inset 0 0 20px 1px#00a7d1;
    box-shadow: inset 0 0 20px 1px #00a7d1; 

    background-color: #00a7d1;
    -webkit-transition: background-color 0.5s linear;
    -moz-transition: background-color 0.5s linear;
    -o-transition: background-color 0.5s linear;
    transition: background-color 0.5s linear;
}

.button SPAN:hover {
    background-color: #00c5f7; 
}

Upvotes: 4

Anon
Anon

Reputation: 2874

Try use :before and :after (ie9+)

#wrapper{
    width:400px;
    height:400px;
    margin:0 auto;
    border: 1px #000 solid;
    position:relative;}
#wrapper:after,
#wrapper:before{
    position:absolute;
    top:0;
    left:0;
    width:100%;
    height:100%;
    content:'';
    background: #1e5799;
    background: -moz-linear-gradient(top, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#1e5799), color-stop(50%,#2989d8), color-stop(51%,#207cca), color-stop(100%,#7db9e8));
    background: -webkit-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%);
    background: -o-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%);
    background: -ms-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%);
    background: linear-gradient(to bottom, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%);
    opacity:1;
    z-index:-1;
    -webkit-transition: all 2s ease-out;
    -moz-transition: all 2s ease-out;
    -ms-transition: all 2s ease-out;
    -o-transition: all 2s ease-out;
    transition: all 2s ease-out;
}
#wrapper:after{
    opacity:0;
    background: #87e0fd;
    background: -moz-linear-gradient(top, #87e0fd 0%, #53cbf1 40%, #05abe0 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#87e0fd), color-stop(40%,#53cbf1), color-stop(100%,#05abe0));
    background: -webkit-linear-gradient(top, #87e0fd 0%,#53cbf1 40%,#05abe0 100%);
    background: -o-linear-gradient(top, #87e0fd 0%,#53cbf1 40%,#05abe0 100%);
    background: -ms-linear-gradient(top, #87e0fd 0%,#53cbf1 40%,#05abe0 100%);
    background: linear-gradient(to bottom, #87e0fd 0%,#53cbf1 40%,#05abe0 100%);
}
#wrapper:hover:before{opacity:0;}
#wrapper:hover:after{opacity:1;}

Upvotes: 2

PaulQ
PaulQ

Reputation: 31

In the following, an anchor tag has a child and a grandchild. The grandchild has the far background gradient. The child in the near background is transparent, but has the gradient to transition to. On hover, the child's opacity is transitioned from 0 to 1, over a period of 1 second.

Here is the CSS:

.bkgrndfar {
  position:absolute;
  top:0;
  left:0;
  z-index:-2;
  height:100%;
  width:100%;
  background:linear-gradient(#eee, #aaa);
}

.bkgrndnear {
  position:absolute;
  top:0;
  left:0;
  height:100%;
  width:100%;
  background:radial-gradient(at 50% 50%, blue 1%, aqua 100%);
  opacity:0;
  transition: opacity 1s;
}

a.menulnk {
  position:relative;
  text-decoration:none;
  color:#333;
  padding: 0 20px;
  text-align:center;
  line-height:27px;
  float:left;
}

a.menulnk:hover {
  color:#eee;
  text-decoration:underline;
}

/* This transitions child opacity on parent hover */
a.menulnk:hover .bkgrndnear {
  opacity:1;
}

And, this is the HTML:

<a href="#" class="menulnk">Transgradient
<div class="bkgrndfar">
  <div class="bkgrndnear">
  </div>
</div>
</a>

The above is only tested in the latest version of Chrome. These are the before hover, halfway on-hover and fully transitioned on-hover images:

Before Halfway After

Upvotes: 3

Related Questions