h1 No delay
h1 Delay
h1 Negative Delay
h1 Staggered
h1 Staggered w/ Negative Delay
h1 Reverse Stagger
h1 Reverse Stagger w/ Negative Delay
p Animate simulataneously with no delay
p Animate simulataneously with a delay
p Animate simulataneously with a negative delay
p Use a variable to create a stagger
p Use an offset to make the delays negative so that the elements retain stagger but don't stagger in
p Use the total amount of blocks to reverse the stagger
p Use a negative coefficient to create a stagger in the opposite direction
pre
  code .block {
  code   animation-delay: 0s;
  code }
pre
  code .block {
  code   animation-delay: 2s;
  code }
pre
  code .block {
  code   animation-delay: -0.5s;
  code }
pre
  code .block {
  code   animation-delay: calc(var(--index) * 0.25s);
  code }
pre
  code .block {
  code   animation-delay: calc((var(--index) - 5) * 0.25s);
  code }
pre
  code .block {
  code   animation-delay: calc((5 - var(--index)) * 0.25s);
  code }
pre
  code .block {
  code   animation-delay: calc(var(--index) * -0.25s);
  code }
.container
  - let b = 0
  while (b < 5)
    .block(style=`--index: ${b};`)
    - b++

input(type='range', min="0", max="6", value="0")
View Compiled
*
  box-sizing border-box

:root
  --delay 0
  --duration 2
  --stagger-step 0
  --coefficient 1
  --offset 0

body
  background linear-gradient(-45deg, #111, #444)
  min-height 100vh
  display flex
  color hsl(0, 0%, 100%)
  align-items center
  font-family sans-serif
  justify-content center
  flex-direction column
  text-align center

pre
  background hsl(0, 0%, 0%)
  font-weight bold
  padding 1rem
  border-radius 6px

.block
  animation party calc(var(--duration, 1) * 1s) linear infinite
  animation-delay calc((((var(--delay, 0) + (var(--index) * var(--stagger-step))) + var(--offset)) * var(--coefficient)) * 1s)
  background hsl(0, 0%, 0%)
  padding-top 100%

.reversed .block
  animation-delay calc((((var(--delay, 0) + ((5 - var(--index)) * var(--stagger-step))) + var(--offset)) * var(--coefficient)) * 1s)

.container
  display grid
  grid-template-columns repeat(5, 1fr)
  grid-gap 1vmin
  width 25vmin
  margin 4rem 0

h1
p
pre
  display none
  text-align left
  max-width 550px

code
  line-height 1.75
  display block

@keyframes party
  for $frame in (0..100)
    {$frame * 1%}
      background 'hsl(%s, 65%, 40%)' % ($frame * 3.6)


[hidden] *
  animation none
View Compiled
// Get started!
const RANGE = document.querySelector('input')
const CONTAINER = document.querySelector('.container')
const TITLES = [...document.querySelectorAll('h1')]
const BLURBS = [...document.querySelectorAll('p')]
const CODES = [...document.querySelectorAll('pre')]

// Each config reps delay, duration, stagger, coefficient, offset
const STEP_CONFIGS = [
  [0, 2, 0, 1, 0],
  [2, 2, 0, 1, 0],
  [-0.5, 2, 0, 1, 0],
  [0, 2, 0.25, 1, 0],
  [0, 2, 0.25, 1, -5],
  [0, 2, 0.25, 1, 0],
  [0, 2, 0.25, -1, 0],
]

const update = () => {
  // Show/Hide elements
  for (let e = 0; e < TITLES.length; e++) {
    TITLES[e].style.display = BLURBS[e].style.display = CODES[e].style.display =
      e === parseInt(RANGE.value, 10) ? 'block' : 'none'
  }
  // Running the step function
  const CONFIG = STEP_CONFIGS[parseInt(RANGE.value, 10)]
  document.documentElement.style.setProperty('--delay', CONFIG[0])
  document.documentElement.style.setProperty('--duration', CONFIG[1])
  document.documentElement.style.setProperty('--stagger-step', CONFIG[2])
  document.documentElement.style.setProperty('--coefficient', CONFIG[3])
  document.documentElement.style.setProperty('--offset', CONFIG[4])
  if (parseInt(RANGE.value, 10) === 5) {
    CONTAINER.classList.add('reversed')
  } else {
    CONTAINER.classList.remove('reversed')
  }
  // Retrigger the animation
  CONTAINER.hidden = true
  requestAnimationFrame(() => (CONTAINER.hidden = false))
}

RANGE.addEventListener('change', update)
// Run the first time to show step 0 👍
update()
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.