<div class="charts">
    <div class="chart _chart0">
      <div class="chart-main">
        <canvas id="chart0"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart1">
      <div class="chart-main">
        <canvas id="chart1"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart2">
      <div class="chart-main">
        <canvas id="chart2"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart3">
      <div class="chart-main">
        <canvas id="chart3"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart4">
      <div class="chart-main">
        <canvas id="chart4"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart5">
      <div class="chart-main">
        <canvas id="chart5"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart6">
      <div class="chart-main">
        <canvas id="chart6"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart7">
      <div class="chart-main">
        <canvas id="chart7"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart8">
      <div class="chart-main">
        <canvas id="chart8"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart9">
      <div class="chart-main">
        <canvas id="chart9"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart10">
      <div class="chart-main">
        <canvas id="chart10"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart11">
      <div class="chart-main">
        <canvas id="chart11"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart12">
      <div class="chart-main">
        <canvas id="chart12"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart13">
      <div class="chart-main">
        <canvas id="chart13"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart14">
      <div class="chart-main">
        <canvas id="chart14"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart15">
      <div class="chart-main">
        <canvas id="chart15"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart16">
      <div class="chart-main">
        <canvas id="chart16"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart17">
      <div class="chart-main">
        <canvas id="chart17"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart18">
      <div class="chart-main">
        <canvas id="chart18"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart19">
      <div class="chart-main">
        <canvas id="chart19"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart20">
      <div class="chart-main">
        <canvas id="chart20"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart21">
      <div class="chart-main">
        <canvas id="chart21"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart22">
      <div class="chart-main">
        <canvas id="chart22"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart23">
      <div class="chart-main">
        <canvas id="chart23"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart24">
      <div class="chart-main">
        <canvas id="chart24"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart25">
      <div class="chart-main">
        <canvas id="chart25"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart26">
      <div class="chart-main">
        <canvas id="chart26"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart27">
      <div class="chart-main">
        <canvas id="chart27"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart28">
      <div class="chart-main">
        <canvas id="chart28"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart29">
      <div class="chart-main">
        <canvas id="chart29"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart30">
      <div class="chart-main">
        <canvas id="chart30"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart31">
      <div class="chart-main">
        <canvas id="chart31"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart32">
      <div class="chart-main">
        <canvas id="chart32"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart33">
      <div class="chart-main">
        <canvas id="chart33"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart34">
      <div class="chart-main">
        <canvas id="chart34"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    <div class="chart _chart35">
      <div class="chart-main">
        <canvas id="chart35"></canvas>
        <p class="chart-txt"><span class="chart-number"></span><span class="chart-percentage">%</span></p>
      </div>
    </div>
    </div>

  <div class="scrollDown">
    <p>Scroll Down↓</p>
  </div>
.chart {
  min-height: 12vw;
  margin: 0 0 10vw;
  
  &-main {
    width: 100%;
    margin: auto;
    position: relative;
  }

  &-txt {
    margin: 0;
    position: absolute;
    top: 50%;
    left: 50%;
    font-size: 5vw;
    line-height: 1;
    transform: translateY(-0.4em) translateX(-1em);
  }
  
  &-number {
    display: inline-block;
    font-weight: bold;
    opacity: 0;
    transition: opacity .4s;

    .appear & {
      opacity: 1;
    }
  }

  &-percentage {
    font-size: 3vw;
    opacity: 1;
    transition: opacity .4s;
    opacity: 0;
    
    .appear & {
      opacity: 1;
    }
  }
 } 

 .charts {
    &-wrapper {
    width: 100%;
  }
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  margin: auto; 

  > * {
    flex: 0 0 auto;
    width: 22%;
  }
}

.scrollDown {
  position: fixed;
  bottom: 0.8vw;
  left: 50%;
  transform: translateX(-50%);
  display: grid;
  justify-items: center;
  font-size: 1.8vw;
  font-weight: bold;
  animation: blink 1.5s infinite;
}

@keyframes blink {
  from {opacity: 0;}
  to {opacity: 1;}
}
View Compiled
const makeChart = (chartIndex: number, maximunPercentage: number) => {
  const data = {
    datasets: [{
      data: [maximunPercentage, 100 - maximunPercentage],
      backgroundColor: [
        'rgba(255, 255, 0, 1)',
        'rgba(0, 0, 0, 0)'
      ],
      borderColor: 'rgba(0, 0, 0, 0)',
      cutout: '80%'
    }]
  }

  const ctx = document.querySelector<HTMLCanvasElement>(`#chart${chartIndex}`)!

  ctx.style.filter = `hue-rotate(${30 / 360 * chartIndex * 100}deg)`

  new Chart(ctx, {
    type: 'doughnut',
    data: data
  } )
  appearElement(chartIndex)
  countupPercentage(chartIndex, maximunPercentage)

}

const appearElement = (chartIndex: number) => {
  document.querySelector<HTMLImageElement>(`.chart._chart${chartIndex}`)?.classList.add('appear')
}

const countupPercentage = (chartIndex:number, maximunPercentage: number) => {
  let num = 0
  const countupSpeed = 8
  const percentageDOM = document.querySelector<HTMLSpanElement>(`.chart._chart${chartIndex} .chart-number`)
  
  setInterval(() => {
    if (num <= maximunPercentage) {
      percentageDOM!.innerText = String(num)
      num++
    }
  }, countupSpeed)
}

  const delayCoef = 300
  const chartNum = 28;
  const maximunPercentages: number[] = []

  for(let i = 0; i < chartNum; i++) {
    maximunPercentages.push(Math.floor(Math.random() * 50 + 50))
  }

  let currentIndex = 0

  let observer = new IntersectionObserver(
    entries => {
      entries.forEach((entry, index) => {
        if (entry.isIntersecting) {
          const delay = index * delayCoef
          setTimeout(() => {
            if (currentIndex > chartNum - 1) {
              return
            }
            makeChart(currentIndex, maximunPercentages[currentIndex])
            currentIndex++
            if (currentIndex >= chartNum) {
              const arrow = document.querySelector<HTMLDivElement>('.scrollDown')
              arrow?.classList.remove('appear')
            }
          }, delay)
        }
      })
    },
    {
      root: null,
      rootMargin: '0px 0px',
      threshold: 0.4
    },
  )

  let targets = document.querySelectorAll<HTMLDivElement>('.chart')
  targets.forEach(target => {
    observer.observe(target)
  })
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.min.js