CSSでスプライトアニメーションをコンテンツの背景にフィットさせる方法です。

縦一列にコマが5つ分並べられたスプライト画像を想定して、それをコンテンツの背景いっぱいに表示させるCSSです。

<body>
  <div class="sprite-container"></div>
</body>
$frame-count: 5;
$seconds-per-frame: 1;

.sprite-container {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: -1;
  background-image: url("sprite.png");
  background-repeat: no-repeat;
  background-size: 100% $frame-count * 100%;
  animation: sprite #{$frame-count * $seconds-per-frame}s steps($frame-count) infinite;
}

@keyframes sprite {
  from {
    background-position: left top;
  }
  to {
    background-position: left 100% * $frame-count / ($frame-count - 1);
  }
}

background-sizeで、スプライト画像のうち一コマで要素のサイズいっぱいになるように指定します。

アニメーションをJavaScriptで制御する場合は、

let frameCount = 5;
let currentFrame = 3; // 0 から 4 の間
el.style.backgroundPosition = `${100 * currentFrame / frameCount - 1}%`;

みたいな感じにすれば良いですが、CSS Animationのstepsでやる場合は若干注意点がありました。

background-positionの値を100%に設定すると、はみ出さずに、左の図で言うと紫のブロックがぴったりに表示されるようになります。

animation-timing-functionに指定するsteps関数には第二引数があり、デフォルト値はendです。詳しくはMDNを見てください。

steps関数の第二引数がendになっていると、キーフレームの100%までは実行されません。

上記の例のようにsteps(5)となっていると、キーフレームの0%20%40%60%80%の状態だけが実行されます。

そのため、80%の状態で最後のコマを表示するために、キーフレームの完了時の状態として6コマ目の位置にあたるbackground-positionを指定します。

計算方法は、左の図と上記のコードを見ていただいた通りです。

こうして今日も平和にCSSを書くことができました。ありがとうございました。