Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS: how to create an infinitely-moving repeating linear gradient?

So basically, I am trying to create a progress bar. In this example, I will just change the colors I was using to red, green and blue instead since that's obviously easier to understand than a load of hex values. Effectively, what I am going for is for the progress bar to have this RGB gradient background that gives the impression the gradient is moving from left to right, to signify that there is still activity (i.e. that the site hasn't frozen). I've tried a few things, starting with just setting background: linear-gradient(120deg, red, green, blue) and animating the background-position CSS property to simulate the gradient moving. However, once at the end of the animation, the progress bar jumped from being mostly blue (i.e. the end of the gradient), right back to green...I then tried manually-reflecting the gradient in the form rgbgr - i.e. background: linear-gradient(120deg, red, green, blue, green, red) and, while this looks better, there is still jumpiness. Finally, I tried using the repeating-linear-gradient CSS function - i.e. background: repeating-linear-gradient(120deg, red, green, blue, green, red). This is the closest to what I'm aiming for, but in the example, you can see the gradient colors 'jumping', rather than animating smoothly

html, body{
  height: 100%;
  background: #222;
  overflow: hidden;
}

body{
  display: flex;
  justify-content: center;
  align-items: center;
}

*{
  color: white;
  font-family: 'Tahoma', sans-serif;
}

#wrapper {
    height: 50px;
    width: 400px;
    position: relative;
    background: #131313;
}

p{
    text-align: center;
    position: absolute;
    width: 100%;
}

#bar {
    background: repeating-linear-gradient(120deg, red,green,blue, green, red);
    background-repeat:repeat-x;
    height: 100%;
    position: absolute;
    background-size: 400% 100%;
    -webkit-animation: AnimationName 3s linear infinite;
    -moz-animation: AnimationName 3s linear infinite;
    animation: AnimationName 3s linear infinite;
}

@-webkit-keyframes AnimationName {
    0%{background-position:100% 50%}
    100%{background-position:0% 50%}
}
@-moz-keyframes AnimationName {
    0%{background-position:100% 50%}
    100%{background-position:0% 50%}
}
@keyframes AnimationName {
    0%{background-position:100% 50%}
    100%{background-position:0% 50%}
}
<div id="wrapper">
    <div id="bar" style="width: 50%"></div>
    <p>Downloading 5 of 10</p>
  </div>

I've seen this effect on many sites before, so I assume it's possible in CSS. If anyone can point me in the right direction, I'd appreciate it. Thanks!

like image 799
CssProblem Avatar asked Sep 08 '20 04:09

CssProblem


People also ask

How do you repeat a linear gradient in CSS?

CSS Syntax Default is 180deg. Defines the position of the starting-point of the gradient line. It consists of two keywords: the first one indicates the horizontal side, left or right, and the second one the vertical side, top or bottom. The order is not relevant and each of the keyword is optional.


2 Answers

You can do it like below and it will work with any angle you want:

body {
  background: #222;
}

.wrapper {
  --d:100px;
  --angle:120deg; 
  --sinus:0.866; /* = sinus(angle) */
  
  height: 50px;
  width: 400px;
  position: relative;
  z-index:0;
  background: #131313;
  text-align: center;
  line-height:50px;
  color: white;
  margin:5px;
}

.wrapper::before {
  content:"";
  height: 100%;
  left:0;
  width:var(--w);
  position: absolute;
  z-index:-1;

  background: repeating-linear-gradient(var(--angle), red, green, blue, green, red var(--d));
  background-size: calc(var(--d)/var(--sinus)) 100%;
  animation: AnimationName 2s linear infinite reverse;
}

@keyframes AnimationName {
  0% {
    background-position: calc(var(--d)/var(--sinus)) 0;
  }
}
<div class="wrapper" style="--w:50%;">
  Downloading 5 of 10
</div>

<div class="wrapper" style="--w:70%;--d:200px;--angle:45deg;--sinus:0.707">
  Downloading 5 of 10
</div>

<div class="wrapper" style="--w:80%;--d:50px;--angle:-30deg;--sinus:0.5">
  Downloading 5 of 10
</div>
like image 65
Temani Afif Avatar answered Oct 07 '22 10:10

Temani Afif


You need to run the animation a bit longer before looping back.

@keyframes AnimationName {
    0%{background-position:100% 50%}
    100%{background-position:-33% 50%} /* instead of 0% 50% */
}

I also changed the gradient angle to 90deg because the initial value makes the start and end of the gradient not matching very well

/* instead of 120deg */
background: repeating-linear-gradient(90deg, red,green,blue, green, red); 

html, body{
  height: 100%;
  background: #222;
  overflow: hidden;
}

body{
  display: flex;
  justify-content: center;
  align-items: center;
}

*{
  color: white;
  font-family: 'Tahoma', sans-serif;
}

#wrapper {
    height: 50px;
    width: 400px;
    position: relative;
    background: #131313;
}

p{
    text-align: center;
    position: absolute;
    width: 100%;
}

#bar {
    background: repeating-linear-gradient(90deg, red,green,blue, green, red);
    background-repeat:repeat-x;
    height: 100%;
    position: absolute;
    background-size: 400% 100%;
    animation: AnimationName 3s linear infinite;
}

@keyframes AnimationName {
    0%{background-position:100% 50%}
    100%{background-position:-33% 50%}
}
<div id="wrapper">
    <div id="bar" style="width: 50%"></div>
    <p>Downloading 5 of 10</p>
  </div>
like image 41
NearHuscarl Avatar answered Oct 07 '22 10:10

NearHuscarl