Blend colors in CSS animation

Viewed 233

My CSS and a snippet for demonstration:

/*compatibility*/
@-moz-keyframes rainbow {
    from {background-position: -100vh 0}
    to {background-position: 100vh 0}
}
@-webkit-keyframes rainbow {
    from {background-position: -100vh 0}
    to {background-position: 100vh 0}
}
@-ms-keyframes rainbow {
    from {background-position: -100vh 0}
    to {background-position: 100vh 0}
}
@-o-keyframes rainbow {
    from {background-position: -100vh 0}
    to {background-position: 100vh 0}
}

 .rainbow {
    padding:0 0 3px 0 !important;
    border-bottom: 1px solid transparent;
    border-radius: 10px;

     /*added a colourstop here, without the third colourstop you get a hard edge*/
    background: linear-gradient(#181717, #181717), 
    linear-gradient(60deg, #ff2400, #e81d1d, #e8b71d, #e3e81d, #1de840, #1ddde8, #2b1de8, #dd00f3, #dd00f3);
    background-origin: border-box;
    background-clip: content-box, border-box;

    
    animation-name: rainbow;
    animation-duration:  4s;

    /*set animation to continue forever, and to move at a single rate instead of easing*/
    animation-iteration-count: infinite;
    animation-timing-function: linear;
}

https://codepen.io/jhendrix13/pen/zYrMZQz

Is there a way to further increase the gradient/blend between the colors?

I'm trying to get it similar to this snippet, which has a much smoother blend/transition between colors:

https://codepen.io/mike-schultz/pen/NgQvGO

But my knowledge of CSS is minimal, and I'm not sure how to get that result. I think it has something to do with the animation definition itself, but when I try to take the animation definition from the second snippet and put it in the first snippet the animation stops working and goes static.

1 Answers

If you use ::after you can achieve a better effect:

.box {
  margin: 20px;
}

.text {
  color: white;
  padding: 10px 0;
  text-align: center;
}

@-webkit-keyframes rainbow {
  0% {
    background-position: 500% 0%;
  }
  100% {
    background-position: 0% 0%;
  }
}

.rainbow {
  border-radius: 6px;
  background: #000;
}

.rainbow::after {
  content: "";
  display: block;
  border-bottom-left-radius: 10px;
  border-bottom-right-radius: 10px;
  height: 5px;
  width: 100%;
  background: linear-gradient( 60deg, #ff2400, #e81d1d, #e8b71d, #e3e81d, #1de840, #1ddde8, #2b1de8, #dd00f3, #dd00f3, #ff2400);
  background-size: 500% 500%;
  animation-name: rainbow;
  animation-duration: 50s;
  animation-iteration-count: infinite;
  animation-timing-function: linear;
}
<div class="box rainbow">
  <div class="text">
    This is a box with a rainbow border.
  </div>
</div>

Set it to display block so the width can be set to 100%, move most of the CSS you had in .rainbow over and set the background-size property, then use percent in the keyframes to loop round to the start (use 200% for this, if you use 100% it won't animate).

EDIT

I've just realised this didn't exactly answer your original question. For blending the colors more smoothly, you can increase the background-size of the element and background-position of the animation, then increase the duration, just tweak until it looks right.

I've edited my snippet to show an example.

Related