できない.dev

CSSで読み込み中のスピナーを作るには

1 要素の border と @keyframes rotate だけで回転するスピナーを作る基本形を示す。
画像も追加の DOM も要らないため、読み込み中の表示を最小のコストで用意できる。

実行確認済み

実行確認済みは、ブラウザで実際に描画して見た目を確認したものである。

公開:

プレビュー
<div class="loader" role="status" aria-live="polite">
  <span class="loader__spinner" aria-hidden="true"></span>
  <span class="loader__label">読み込み中…</span>
</div>
.loader {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 14px;
  color: #475569;
}
.loader__spinner {
  width: 32px;
  height: 32px;
  box-sizing: border-box;
  border: 4px solid #e2e8f0;      /* 円周の色 */
  border-top-color: #0f766e;      /* 1 辺だけ変えて回転を見せる */
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin {
  to {
    transform: rotate(1turn);
  }
}
@media (prefers-reduced-motion: reduce) {
  .loader__spinner {
    animation-duration: 2.4s;
  }
}

4 辺の border のうち 1 辺だけ色を変え、border-radius: 50% で円にしてから回すとスピナーになる。
全周が同じ色だと回転しても見た目が変わらないため、色差が「回っている」という手掛かりそのものになる。

つまずき

回らない・円にならないときは、まず幅と高さが同じか、border-radius: 50% が当たっているかを確認する。
span のようなインライン要素は width / height を無視するため、display: inline-block や flex アイテム化を忘れると潰れて見える。
また box-sizing: border-box を付けないと border の分だけ外形が太り、隣の要素とのすき間が設計値からずれる。
回転の中心がぶれる場合は transform-origin ではなく、要素自体が正方形になっていないことを疑うとよい。

動きを控えたい利用者への配慮

無限に回り続けるアニメーションは、前庭障害のある利用者にとって不快や体調不良の原因になりうる。
prefers-reduced-motion: reduce のメディアクエリを用意し、回転を止めるか十分に遅くするのが望ましい。
上の例では animation を消さずに周期を 2.4 秒へ伸ばしている。
完全に止めてしまうと「処理が進んでいる」という情報まで失われるため、遅くする形で残す判断もあるという点は覚えておきたい。

スクリーンリーダーへの伝え方

回転そのものは視覚的な表現でしかないので、スクリーンリーダーには文字で状態を伝える必要がある。
上の例では外側に role="status" と aria-live="polite" を置き、装飾でしかないスピナー本体には aria-hidden="true" を付けている。
こうすると「読み込み中…」というラベルだけが読み上げられ、意味のない要素は読み飛ばされる。
読み込みが終わったらラベルを結果の文言へ差し替えると、完了も同じ領域から伝わる。

この記事は役立ちましたか?