<div class="rainbow">
  <div class="rainbow__top"></div>
  <div class="rainbow__bottom"></div>
</div>
<div class="contents">
  <h1>Infinite rainbow</h1>
</div>
// *******
// SASS Variables for loops and calculations
// *******
// These vars are mainly used for loops
  $visibleWaveCount: 4; // visible on screen
  $actuaWaveCountTop: $visibleWaveCount + 1; // extra top wave for animation
  $actuaWaveCountBottom: $visibleWaveCount + 2; // extra bottom waves for animation
  $nbrOfStripes: 7; // Color or transparency


// *******
// CSS Custom props for adjusting the look of it all
// *******
:root {
  // Available colors
  --color-transparent: transparent;
  --color-red: #F2C9B2;
  --color-yellow: #ECF4D6;
  --color-green: #AFDCC4;
  --color-blue: #91DAEA;
  --color-purple: #E4C1ED;
  
  --color-text: #222;
  --color-background: #F5E5EE;
  
  --animation-speed: 2000ms;
    
  --rainbow-width: calc(100/#{$visibleWaveCount}*1vw);
  --rainbow-stripe-width: calc(var(--rainbow-width)/2/#{$nbrOfStripes});
}
.rainbow {
  &__top {
    // Color scheme for top-half waves
    --color-0: var(--color-transparent);
    --color-1: var(--color-purple);
    --color-2: var(--color-blue);
    --color-3: var(--color-green);
    --color-4: var(--color-yellow);
    --color-5: var(--color-red);
    --color-6: var(--color-transparent);
    // Alignment for gradients in top half
    --gradient-y-align: 100%;
    --gradient-x-offset: 0.5;
  }
  &__bottom {
    // Color scheme for bottom half waves
    --color-0: var(--color-transparent);
    --color-1: var(--color-red);
    --color-2: var(--color-yellow);
    --color-3: var(--color-green);
    --color-4: var(--color-blue);
    --color-5: var(--color-purple);
    --color-6: var(--color-transparent);
    
    // Alignment for gradients in bottom half
    --gradient-y-align: 0;
    --gradient-x-offset: 0;
    
  }
}

// *******
// SASS functions for automation
// *******
// Function for printing a set of rainbow stripes in a background-image
// Output: a string of comma separated color stops for a radial-gradient()
@function getRainbowStripesForBackgroundImage($nbrOfStripes) {
  $output: '';
    @for $i from 0 to $nbrOfStripes {
      $color: var(--color-#{$i});
      $colorStopFrom: calc(var(--rainbow-stripe-width) * #{$i});
      $colorStopTo: calc(var(--rainbow-stripe-width) * #{$i+1});
      
      $output: #{$output}, $color $colorStopFrom $colorStopTo;
    }
  
  // extra outer transparency, so that the last color (if it's a color) does not obscure other waves
  $transparent: var(--color-transparent);
  $transparentColorStopFrom: calc(var(--rainbow-stripe-width) * #{$nbrOfStripes});
  $output: #{$output}, $transparent $transparentColorStopFrom;
  
  @return $output;
}

// Function for printing a set of rainbow gradients
// Outputs a string of comma separated radial-gradients for background-image
@function getRainbowBackgroundImages($nbrOfReps, $nbrOfStripes) {
  $output: '';
  @for $i from 0 to $nbrOfReps {
    $wavePositionX: calc(var(--rainbow-width)*calc(var(--gradient-x-offset) + #{$i}));
    $wavePositionY: var(--gradient-y-align);
    $output: #{$output}, 
      radial-gradient(circle at $wavePositionX $wavePositionY,
        getRainbowStripesForBackgroundImage($nbrOfStripes)
      );
  }
  @return $output;
}


// *******
// Styles
// *******
@import url('https://fonts.googleapis.com/css2?family=Fugaz+One&display=swap');
body {
  background-color: var(--color-background);
  margin: 0;
}
.rainbow {
  bottom: 0;
  height: var(--rainbow-width);
  margin: auto;
  position: absolute;
  top: 0;
  // Limit width in order to animate with transform on div-children (instead of background-position)
  overflow: hidden;
  width: 100vw;
  & div {
    animation: rainbowRoll var(--animation-speed) linear infinite;
    height: 50%;
    // Set width in order to animate this with transform instead of background-position
    width: calc(100vw + var(--rainbow-width));
  }
  &--reverse div {
    animation-direction: reverse;
  }
  
  &__top {
    // Print gradients with sass-functions
    background-image: 
      getRainbowBackgroundImages($actuaWaveCountTop, $nbrOfStripes);
  }
  
  &__bottom {
    // Print gradients with sass-functions
    background-image: 
      getRainbowBackgroundImages($actuaWaveCountBottom, $nbrOfStripes);
  }

}

.contents {
  display: flex;
  height: 100vh;
  position: relative;
  
  h1 {
    color: var(--color-text);
    font: calc(var(--rainbow-width)*0.27) 'Fugaz One', sans-serif;
    letter-spacing: -.02em;
    text-align: center;
    margin: auto;
  }
}

// Animate
@keyframes rainbowRoll {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(calc(var(--rainbow-width)*-1));
  }
}
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.