CATEGORIES:CSS / TAGS:
CSSだけでローディングアニメーションを作る#03
A:大きくなる
B:小さくなる

JavaScriptを使わず、CSSだけで5つのドットが左から順番に大きくなる(または小さくなる)ローディングアニメーションを作る方法。位置は動かさず、サイズだけを途中で補間せずに切り替えて、機械的な「ピピピ」という動きにする。色・サイズの変化量・速さは数字の変更だけで調整できる。

パターンは次の2つ。

パターン動きクラス
A:大きくなる10px → 12px → 14px → 12px → 10pxhop grow
B:小さくなる10px → 8px → 6px → 8px → 10pxhop shrink

動きは1周期1.2秒で、次の順番で繰り返す。

  • ドットは横一列に並んでいて、位置は動かない
  • 1つのドットが、0.05秒ごとに「中間 → 最大(最小)→ 中間 → 元のサイズ」と切り替わる
  • 1回の変化は0.2秒。前のドットが戻る頃に、次のドットが変わる
  • 右端が変わり終わると、少し静止して左端から繰り返す

サイズが一瞬で切り替わるのは、animation-timing-function の step-end による。途中の動きが補間されず、デジタルな動きになる。ドットごとに animation-delay をずらすだけで、順番に変わっていく。サイズは transform: scale() で変えているので、ドットの中心を基準に、上下左右に均等に広がる(縮む)。

HTML(表示したい場所に置く。span は必ず5つ)

<div class="hop grow" role="status" aria-label="読み込み中">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

小さくなる版は、class="hop shrink" にする。

/* 入れ物(ドット5つの置き場所) */
.hop {
  display: flex;
  align-items: center;             /* ドットを縦の中央にそろえる */
  gap: 10px;                       /* ドットの間隔 */
}

/* ドット(共通) */
.hop span {
  display: block;
  width: 10px;                     /* ドットの大きさ(直径) */
  height: 10px;
  border-radius: 50%;
  background: #555555;             /* ドットの色 */
  animation-duration: 1.2s;        /* 1周期 */
  animation-timing-function: step-end;   /* 途中を補間せず一瞬で切り替える */
  animation-iteration-count: infinite;
}

/* 版の切り替え */
.hop.grow span   { animation-name: hop-grow; }     /* A: 大きくなる */
.hop.shrink span { animation-name: hop-shrink; }   /* B: 小さくなる */

/* 左から順番にずらす(周期 ÷ 6 = .2秒ずつ) */
.hop span:nth-child(2) { animation-delay: .2s; }
.hop span:nth-child(3) { animation-delay: .4s; }
.hop span:nth-child(4) { animation-delay: .6s; }
.hop span:nth-child(5) { animation-delay: .8s; }

/* A: 大きくなる動き */
@keyframes hop-grow {
  0%      { transform: scale(1); }
  4.17%   { transform: scale(1.2); }
  8.33%   { transform: scale(1.4); }   /* 最大 */
  12.5%   { transform: scale(1.2); }
  16.67%  { transform: scale(1); }
  100%    { transform: scale(1); }
}

/* B: 小さくなる動き */
@keyframes hop-shrink {
  0%      { transform: scale(1); }
  4.17%   { transform: scale(.8); }
  8.33%   { transform: scale(.6); }    /* 最小 */
  12.5%   { transform: scale(.8); }
  16.67%  { transform: scale(1); }
  100%    { transform: scale(1); }
}

/* OSで「視差効果を減らす」設定のときは止める */
@media (prefers-reduced-motion: reduce) {
  .hop span { animation: none; }
}

調整するときの変更箇所は次のとおり。

変えたいもの変更する場所
ドットの色.hop span の background
ドットの大きさ.hop span の width / height(同じ値に)
大きくなる倍率(A)@keyframes hop-grow の 1.4(中間はその半分の変化に)
小さくなる倍率(B)@keyframes hop-shrink の .6(中間はその半分の変化に)
全体の速さanimation-duration の 1.2s と、animation-delay の4つ(周期 ÷ 6 の1〜4倍)
1回の変化の速さ@keyframes の % の刻み(今は4.17% = 0.05秒ずつ)
次に変わるまでの間animation-delay の幅。1回の変化(0.2秒)以上にすると、前が戻ってから次が変わる

周期とずらし幅は、セットで変える必要がある。1.2秒なら .2 / .4 / .6 / .8、0.9秒なら .15 / .3 / .45 / .6 になる。Aで大きくするときは、ドットの間隔(gap)が足りているか確認する。1.4倍なら14pxになる。

実際のサイトでは、ページの読み込みが終わるまで表示して、完了したらフェードアウトさせる形で使える。表示環境によって動きの見え方が異なる場合があるため、本番に反映する前に確認を推奨。

NOTICES

  • 記事内容は実装させたものがほとんどですが自己責任で参考にしてください。

TO HEADER