Linda
Linda

Reputation: 2405

Change linear gradient background after a time

I want to change a background after a time. If the background has got a "clear" color there is no problem but if the color is a gradient set as the code doesn't work. is there a work around for that?

background: -webkit-linear-gradient(rgba(39,49,67,1), rgba(226,228,209,1)); /*For Safari 5.1 to 6.0 */
background: -o-linear-gradient(rgba(39,49,67,1), rgba(226,228,209,1));  /*For Opera 11.1 to 12.0 */
background: -moz-linear-gradient(rgba(39,49,67,1),rgba(39,49,67,1), rgba(226,228,209,1));  /*For Firefox 3.6 to 15 */
background: linear-gradient(rgba(39,49,67,1),rgba(51,90,109,1),rgba(83,142,144,1), rgba(226,228,209,1));  /*Standard syntax */

jsfiddle for normal color change

Upvotes: 4

Views: 6699

Answers (4)

stealson
stealson

Reputation: 21

You could try LinearGradient.js to create random and colorful linear gradients.

Upvotes: 2

Alec
Alec

Reputation: 942

Gradient Animations

CSS3 doesn't support linear gradient animations, so in order to achieve this effect you'll have to write the animation your self in Javascript or use a background-position trick like the one stated by Easwee. I prefer Javascript because it allows you to easily reuse the code, add dynamic effects, and quickly modify the effect. That being said Easwee's solution is really ingenious although somewhat limiting.

CSS based gradient animation:

Even though CSS doesn't natively support gradient animations as Easwee stated we can use a "hack" to create gradient animation in css by manipulating the background position of the image.

Example (Go full screen):

body {
  margin: 20px;
  background-color: #000;
}

.container {
  position: relative;
  margin: 0 auto;
  width: 480px;
  height: 140px;
  background-color: #333;
  border-radius: 8px;
}

button {
  position: absolute;
  width: 160px;
  height: 36px;
  top: calc(50% - 18px);
  left: 50px;
  border: solid 1px #ccc;
  border-radius: 8px;
  color: #fff;
  font: 16px sans-serif;
  
  /* set up background gradient and animation */
  background-image: linear-gradient(#5187c4, #1c2f45);
  background-size: auto 200%;
  background-position: 0 100%;
  transition: background-position 0.5s;
}
.container:hover button {
  /* shift background gradient position */
  background-position: 0 0;
}

.slider {
  position: absolute;
  top: calc(50% - 18px);
  right: 50px;
  margin-top: -36px;
  width: 160px;
  height: 72px;
  background-image: linear-gradient(#5187c4, #1c2f45);
  transition: margin-top .5s;
}
.container:hover .slider {
  margin-top: 0px;
}

.frame {
  position: absolute;
  top: calc(50% - 18px);
  right: 50px;
  box-sizing: border-box;
  width: 160px;
  height: 36px;
  border: solid 1px #ccc;
  border-radius: 8px;
}

.info {
  margin: 20px auto 0;
  color: #ccc;
  font: 18px/150% sans-serif;
  text-align: justify;
  width: 480px;
}
<div class="container">
  <button disabled>Some Button</button>
  <div class="slider"></div>
  <div class="frame"></div>
</div>

<div class="info">
  You can't animate gradient colors with pure CSS. Gradients are set via background-image, which is not (currently) an animatable property. But background-position is. So you can use background-size to make the background taller than the element it's on, then animate background-position to slide it up or down. The result is a simple animated fading gradient.
</div>

Code Pen Link

Javascript based gradient animation

In order to build a Javascript based gradient animation we need to:

  • Create a function that takes an element, a range of colors, the time delay between them, and a callback which run's after the function ends (allowing you to do things like make it repeat continuously or till a condition is met).
  • Have that function then use an interval that fires off 15 times a second and converts it's current time into a progress value from 0 - 100 on how close it is to finished.
  • Then we multiply the difference in colors for each matching r,g,b by the progress to get what stage in the transition we're currently on.
  • After we're finished we move on to the next color.
  • At the end of all of this we launch the callback, so we can then decide what to do.

(If you'd like a code solution let me know. It is a lengthy process to type up, so for that reason if you're only using this once and for two maybe three gradient colors use Eawee's solution. Otherwise Javascript's your friend.)

A simpler example of a Javascript gradient animation:

var colors = new Array(
  [62,35,255],
  [60,255,60],
  [255,35,98],
  [45,175,230],
  [255,0,255],
  [255,128,0]);

var step = 0;
//color table indices for: 
// current color left
// next color left
// current color right
// next color right
var colorIndices = [0,1,2,3];

//transition speed
var gradientSpeed = 0.002;

function updateGradient()
{
  
  if ( $===undefined ) return;
  
var c0_0 = colors[colorIndices[0]];
var c0_1 = colors[colorIndices[1]];
var c1_0 = colors[colorIndices[2]];
var c1_1 = colors[colorIndices[3]];

var istep = 1 - step;
var r1 = Math.round(istep * c0_0[0] + step * c0_1[0]);
var g1 = Math.round(istep * c0_0[1] + step * c0_1[1]);
var b1 = Math.round(istep * c0_0[2] + step * c0_1[2]);
var color1 = "rgb("+r1+","+g1+","+b1+")";

var r2 = Math.round(istep * c1_0[0] + step * c1_1[0]);
var g2 = Math.round(istep * c1_0[1] + step * c1_1[1]);
var b2 = Math.round(istep * c1_0[2] + step * c1_1[2]);
var color2 = "rgb("+r2+","+g2+","+b2+")";

 $('#gradient').css({
   background: "-webkit-gradient(linear, left top, right top, from("+color1+"), to("+color2+"))"}).css({
    background: "-moz-linear-gradient(left, "+color1+" 0%, "+color2+" 100%)"});
  
  step += gradientSpeed;
  if ( step >= 1 )
  {
    step %= 1;
    colorIndices[0] = colorIndices[1];
    colorIndices[2] = colorIndices[3];
    
    //pick two new target color indices
    //do not pick the same as the current one
    colorIndices[1] = ( colorIndices[1] + Math.floor( 1 + Math.random() * (colors.length - 1))) % colors.length;
    colorIndices[3] = ( colorIndices[3] + Math.floor( 1 + Math.random() * (colors.length - 1))) % colors.length;
    
  }
}

setInterval(updateGradient,10);
	body{
	 background-color: #000000;
   padding: 0px;
   margin: 0px;
 }

#gradient
{
  width: 100%;
  height: 800px;
  padding: 0px;
  margin: 0px;
}
<html>
  <head>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
  </head>
  <body>
    <div id="gradient" />
 </body>
</html>

   

Javascript Based Gradient Animator (Code Pen)

Helpful Resources:

CSS Gradient Animator Generator

CSS Gradient Animator Walkthrough

Upvotes: 8

easwee
easwee

Reputation: 15905

What Dbugger said is true - you can't animate a background image with css animations.

However, you could fake it with a 4 stop gradient (cleverly position your color stops - I suggest using a gradient generator as Colorzilla or similar - will make your work easier ) - since a gradient is treated as a background-image, you can animate it's position by using background-position. In order to animate the position you need to increase it's size so part of the gradient is outside your container.

You can use animation-delay to set the initial delay before the animation starts.

html, body {width:100%;height:100%;margin:0;}
div {
    width: 100%;
    height: 100%;
    background: -moz-linear-gradient(top,  rgba(30,87,153,1) 0%, rgba(118,191,36,1) 25%, rgba(224,117,35,1) 50%, rgba(242,38,42,1) 75%, rgba(130,100,70,1) 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(30,87,153,1)), color-stop(25%,rgba(118,191,36,1)), color-stop(50%,rgba(224,117,35,1)), color-stop(75%,rgba(242,38,42,1)), color-stop(100%,rgba(130,100,70,1)));
    background: -webkit-linear-gradient(top,  rgba(30,87,153,1) 0%,rgba(118,191,36,1) 25%,rgba(224,117,35,1) 50%,rgba(242,38,42,1) 75%,rgba(130,100,70,1) 100%);   
    background: linear-gradient(to bottom,  rgba(30,87,153,1) 0%,rgba(118,191,36,1) 25%,rgba(224,117,35,1) 50%,rgba(242,38,42,1) 75%,rgba(130,100,70,1) 100%);
    background-size: 100% 400%;
    background-position:0 0;
    -webkit-animation: animateGradient 5s ease 1;
    -moz-animation:    animateGradient 5s ease 1;
    animation:         animateGradient 5s ease 1;
    -webkit-animation-delay: 2s;
    -moz-animation-delay:    2s;
    animation-delay:         2s;
}


@-webkit-keyframes animateGradient {
    0%   {background-position: 0 0;}
    50%  {background-position: 0 100%;}
    100% {background-position: 0 0;}
}
@-moz-keyframes animateGradient {
    0%   {background-position: 0 0;}
    50%  {background-position: 0 100%;}
    100% {background-position: 0 0;}
}
@keyframes animateGradient { 
    0%   {background-position: 0 0;}
    50%  {background-position: 0 100%;}
    100% {background-position: 0 0;}
}
<div></div>


Alternative: Another approach you could take is to overlay one element over the other, set the initial gradient in top and ending gradient in the bottom element , and create an opacity animation, that fades out the top element after a certain amount of time (opacity: 0)

Below is an approach on how you can do it with a single element in markup (rely on the :after or :before pseudo element). The following approach has more compatibility cross devices:

html, body {width:100%;height:100%;margin:0;}
.gradient {
    position:relative;    
    width: 100%;
    height: 100%;
    background: -webkit-linear-gradient(rgba(39,49,67,1), rgba(226,228,209,1));
    background: -o-linear-gradient(rgba(39,49,67,1), rgba(226,228,209,1));
    background: -moz-linear-gradient(rgba(39,49,67,1),rgba(39,49,67,1), rgba(226,228,209,1));
    background: linear-gradient(rgba(39,49,67,1),rgba(39,49,67,1), rgba(226,228,209,1));
}
.gradient:after {
   content:"";
    position:absolute;
    top:0;
    left:0;
    width: 100%;
    height: 100%;
    background: -webkit-linear-gradient(rgba(226,228,209,1), rgba(39,49,67,1));
    background: -o-linear-gradient(rgba(226,228,209,1), rgba(39,49,67,1));
    background: -moz-linear-gradient(rgba(226,228,209,1), rgba(39,49,67,1));
    background: linear-gradient(rgba(226,228,209,1), rgba(39,49,67,1));
    opacity: 0;
    -webkit-animation: animateGradient 3s linear 1;
    -moz-animation: animateGradient 3s linear 1;
    animation: animateGradient 3s linear 1;
}

@-webkit-keyframes animateGradient {
    0%   {opacity:1;}
    100% {opacity:0;}
}
@-moz-keyframes animateGradient {
    0%   {opacity:1;}
    100% {opacity:0;}
}
@keyframes animateGradient {     
    0%   {opacity:1;}
    100% {opacity:0;}
}
<div class="gradient"></div>

Upvotes: 14

Enrique Moreno Tent
Enrique Moreno Tent

Reputation: 25267

A background-gradient is considered a background-image, and background images can NOT be animated through normal CSS transitions.

Upvotes: 4

Related Questions