CSSで作るローディングアニメーション10選

CSSで作るローディングアニメーション10選

ページやコンポーネントの読み込み時に使える、CSSだけで作るローディングアニメーションを10種類まとめました。軽量で使い回しやすい実装を中心に、アクセシビリティとパフォーマンスの注意点も解説します。

1. シンプルスピナー(円形スピン)

最も基本的なスピナー。軽量でどこでも使える定番。

HTML
<div class="spinner"></div>

<style>
.spinner{
  width: 40px;
  height: 40px;
  border: 4px solid rgba(0,0,0,0.08);
  border-top-color: #3498db;
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
  display:inline-block;
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* prefers-reduced-motion に配慮 */
@media (prefers-reduced-motion: reduce){
  .spinner {
    animation: none;
    opacity: 0.8;
  }
}
</style>

補足:prefers-reduced-motion(動き控えめ設定)について

prefers-reduced-motion は、OSやブラウザの設定で「アニメーションを減らす/無効にする」を選んだユーザーを尊重するためのCSSメディアクエリです。 視覚的な動きに不快感を覚えたり、めまいや注意散漫になりやすいユーザーが存在するため、アニメーションのあるUIでは必ず配慮を入れてください。

2. ドットパルス(点が膨らむ)

小さな点が順に膨らむシンプルなパターン。テキストの横などに最適。

HTML
<div class="dot-pulse">
  <span></span><span></span><span></span>
</div>

<style>
.dot-pulse {
  display: inline-flex;
  gap: 8px;
  align-items: center;
}
.dot-pulse span {
  display: block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: #2d9cdb;
  transform-origin: center;
  animation: dotPulse 0.9s cubic-bezier(.2,.6,.2,1) infinite;
}
.dot-pulse span:nth-child(2) {
  animation-delay: 0.12s;
}
.dot-pulse span:nth-child(3) {
  animation-delay: 0.24s;
}
@keyframes dotPulse {
  0%{ transform: scale(1); opacity:0.6; }
  50%{ transform: scale(1.6); opacity:1; }
  100%{ transform: scale(1); opacity:0.6; }
}
@media (prefers-reduced-motion: reduce) {
  .dot-pulse span {
    animation: none;
    opacity: 0.85;
    transform: none;
  }
}
</style>

3. バウンシングドット(3点の跳ねるアニメ)

短い遅延でリズミカルに跳ねるドット。ロード待ちの視覚的リズムに。

HTML
<div class="bouncing-dots">
  <span></span><span></span><span></span>
</div>

<style>
.bouncing-dots {
  display: inline-flex;
  gap: 8px;
  align-items: flex-end;
  height: 20px;
}
.bouncing-dots span {
  width: 8px;
  height: 8px;
  background-color: #ff6b6b;
  border-radius: 50%;
  animation: bounce 0.9s cubic-bezier(.28,.84,.42,1) infinite;
}
.bouncing-dots span:nth-child(2) {
  animation-delay: 0.12s;
}
.bouncing-dots span:nth-child(3) {
  animation-delay: 0.24s;
}
@keyframes bounce {
  0%{ transform: translateY(0); }
  50%{ transform: translateY(-10px); }
  100%{ transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .bouncing-dots span {
    animation: none;
  }
}
</style>

4. ローディングバー(インジケータ)

幅いっぱいに伸びるバー型のインジケータ。プレースホルダ読み込みに合う表現。

HTML
<div class="loading-bar">
  <div class="loading-bar__inner"></div>
</div>

<style>
.loading-bar {
  width: 260px;
  height: 6px;
  background-color: rgba(0,0,0,0.06);
  border-radius: 6px;
  overflow: hidden;
}
.loading-bar__inner {
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, #6a11cb, #2575fc);
  animation: barMove 1.2s cubic-bezier(.2,.6,.2,1) infinite;
}
@keyframes barMove {
  0%{ transform: translateX(-100%); }
  50%{ transform: translateX(20%); }
  100%{ transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce){
  .loading-bar__inner {
    animation: none;
  }
}
</style>

5. スケルトンシマー(骨組みプレースホルダ)

コンテンツ読み込み中のプレースホルダ。実用性が高くUXも良好。

HTML
<div class="skeleton">
  <div class="skeleton__thumb"></div>
  <div class="skeleton__lines">
    <div></div><div></div><div></div>
  </div>
</div>

<style>
.skeleton {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  width: 320px;
}
.skeleton__thumb {
  width: 100px;
  height: 80px;
  background-color: #e6e6e6;
  border-radius: 6px;
}
.skeleton__lines div {
  width: 220px;
  height: 12px;
  background: linear-gradient(90deg, #e6e6e6, #f5f5f5, #e6e6e6);
  background-size: 200% 100%;
  border-radius: 6px;
  margin-bottom: 8px;
  animation: shimmer 1.2s linear infinite;
}
@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position:-200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton__lines div { animation: none; }
}
</style>

6. デュアルリング(2重リング)

同心円が反時計回り/時計回りに動くことでリッチな表現。

HTML
<div class="dual-ring"></div>

<style>
.dual-ring {
  position: relative;
  display: inline-block;
  width: 48px;
  height: 48px;
}
.dual-ring::before,
.dual-ring::after {
  content: '';
  position: absolute;
  inset: 0;
  border: 4px solid rgb(204, 204, 204, 0.2);
  border-radius: 50%;
}
.dual-ring::before {
  border-top-color: #ffb86b;
  animation: spin 1.1s linear infinite;
}
.dual-ring::after {
  border-bottom-color: #6a11cb;
  scale: 0.75;
  animation: spin 1.6s linear reverse infinite;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .dual-ring::before,
  .dual-ring::after { animation:none; }
}
</style>

7. 回転角ブロック(四角が回る)

四角形が回転して入れ替わるアニメ。少しモダンな印象に。

HTML
<div class="rotating-squares">
  <span></span><span></span><span></span><span></span>
</div>

<style>
.rotating-squares {
  position: relative;
  display: inline-block;
  width: 48px;
  height: 48px;
}
.rotating-squares span {
  position: absolute;
  inset: 0;
  width: 18px;
  height: 18px;
  background-color: #1abc9c;
  margin: 0 auto;
  transform-origin: center;
  animation: rotateSquare 1.2s cubic-bezier(.2, .8, .2, 1) infinite;
}
.rotating-squares span:nth-child(1) {
  transform: translate(-12px, -12px);
  animation-delay: 0s;
}
.rotating-squares span:nth-child(2) {
  transform: translate(12px, -12px);
  animation-delay: 0.15s;
}
.rotating-squares span:nth-child(3) {
  transform: translate(12px, 12px);
  animation-delay: 0.3s;
}
.rotating-squares span:nth-child(4) {
  transform: translate(-12px, 12px);
  animation-delay: 0.45s;
}
@keyframes rotateSquare{
  0%{ transform: scale(0.6) rotate(0deg); opacity:0.6; }
  50%{ transform: scale(1.05) rotate(180deg); opacity:1; }
  100%{ transform: scale(0.6) rotate(360deg); opacity:0.6; }
}
@media (prefers-reduced-motion: reduce) {
  .rotating-squares span { animation:none; }
}
</style>

8. 円形プログレス(決まった割合の表示向け)

決まった進捗を表示するのに使える円形の疑似プログレス(CSSのみで簡易的に表現)。

HTML
<div class="circle-progress" data-progress="65"><span>65%</span></div>

<style>
/* シンプルな見せ方:conic-gradient を利用(対応ブラウザ要確認) */
.circle-progress {
  display: inline-grid;
  width: 80px;
  height: 80px;
  border-radius: 50%;
  place-items: center;
  background: conic-gradient(#3498db calc(var(--p, 65) * 1%), rgba(0, 0, 0, 0.08) 0);
  --p: 65;
  font-weight: 600;
  color: #222;
}
.circle-progress span {
  font-size: 14px;
  background-color: #fff;
  padding: 6px 8px;
  border-radius: 6px;
}
/* JSで data-progress を CSS 変数に反映する場合(任意) */
</style>

<script>
document.querySelectorAll('.circle-progress').forEach(function(el){
  var p = el.getAttribute('data-progress') || 0;
  el.style.setProperty('--p', p);
});
</script>
65%

9. 波形ローダー(横に流れる波)

幅いっぱいに横へ流れる波。背景ローディングやセクション読み込みに向く。

HTML
<div class="wave-loader"></div>

<style>
.wave-loader {
  position: relative;
  width: 100%;
  max-width: 320px;
  height: 10px;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.2));
  overflow: hidden;
}
.wave-loader::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,0.35), rgba(255,255,255,0));
  transform: translateX(-100%);
  animation: wave 1.1s linear infinite;
}
@keyframes wave {
  100% { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
  .wave-loader::before{ animation:none; }
}
</style>

10. パルスハロー(周囲がふわっと光る)

要素の周りがゆっくり拡大して消える。注目させたいときに有効。

HTML
<div class="pulse-halo"></div>

<style>
.pulse-halo {
  position: relative;
  display: inline-block;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background-color: #6a11cb;
}
.pulse-halo::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: 0 0 0 6px rgba(106, 17, 203, 0.18);
  animation: halo 1.4s ease-out infinite;
}
@keyframes halo {
  0%{ transform: scale(1); opacity:1; }
  100%{ transform: scale(1.9); opacity:0; }
}
@media (prefers-reduced-motion: reduce) {
  .pulse-halo::after{ animation:none; opacity:0.6; }
}
</style>

アクセシビリティと実装のポイント

  • prefers-reduced-motion を必ず用意して、アニメーションをオフにできるようにする。
  • 読み込みが長時間になる場合、ARIAで状態を伝える(例:role="status" aria-live="polite")とスクリーンリーダーへ通知される。
  • アニメーションはなるべく transformopacity に限定し、レイアウト再計算(reflow)を避けることでパフォーマンスを保つ。
  • モバイルでは複雑なアニメーションでバッテリーや描画負荷が上がるため、必要最低限の表現に留める。
  • 色やコントラストはアクセシビリティ配慮(色覚多様性)を考慮する。重要な情報は色以外でも識別できるようにする。

ワンポイント

ローディングは“待ち”の時間をどう使うかの工夫。短く分かりやすいアニメで安心感を与えよう!

まとめ

ここで紹介した10種はすべて軽量で使い回しやすい実装です。用途(小さなインジケータ、ページ全体、プレースホルダ)に合わせて選び、アクセシビリティとパフォーマンスに配慮して実装してください。必要ならサンプルの配色バリエーションやSVG版の実装、複数同時スタック表示の拡張も作成します。

関連記事

PAGE TOP