2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CSSアニメーション、実はこんなに簡単だった

Posted at

はじめに

「サイトに動きを付けたいけど、JavaScriptは大げさかな...」
「CSSアニメーションって難しそう」
「transitionとanimationの違いがわからない」

実は、CSSだけで素敵なアニメーションが作れるんです!しかも、思ってるより簡単。

今回は「ボタンにホバーエフェクトを付ける」レベルから「ローディングアニメーション」まで、実用的なCSSアニメーションを紹介します!

transitionとanimationの違い

まず、この2つの違いを理解しましょう。

transition = 状態の変化をなめらかに

「AからBへの変化」をスムーズにする

/* マウスを乗せたら色が変わる */
.button {
  background: blue;
  transition: background 0.3s; /* 0.3秒かけて変化 */
}

.button:hover {
  background: red; /* マウスを乗せたら赤に */
}

いつ使う?

  • ホバーエフェクト
  • クリック時の変化
  • メニューの開閉

animation = 自動で動き続ける

「勝手に動く」アニメーション

/* ずっと回転し続ける */
.spinner {
  animation: spin 2s infinite; /* 2秒で1回転を無限に繰り返す */
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

いつ使う?

  • ローディングアニメーション
  • 背景の動き
  • アテンションを引く演出

まずはtransitionから始めよう

1. 基本のホバーエフェクト

/* ボタンのホバーエフェクト */
.btn {
  padding: 10px 20px;
  background: #3498db;
  color: white;
  border: none;
  cursor: pointer;
  transition: all 0.3s ease; /* すべてのプロパティを0.3秒でアニメーション */
}

.btn:hover {
  background: #2980b9;
  transform: translateY(-2px); /* 少し上に浮く */
  box-shadow: 0 5px 15px rgba(0,0,0,0.3); /* 影を付ける */
}

ポイント:

  • transition: all 0.3s ease; で全プロパティをアニメーション化
  • easeは「最初と最後がゆっくり」な動き

2. メニューのスライド

/* ハンバーガーメニュー */
.menu {
  position: fixed;
  top: 0;
  right: -300px; /* 画面外に配置 */
  width: 300px;
  height: 100vh;
  background: white;
  transition: right 0.3s ease;
}

.menu.active {
  right: 0; /* 表示時は右端0に */
}

3. アコーディオンメニュー

/* 開閉するコンテンツ */
.accordion-content {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
}

.accordion-content.open {
  max-height: 500px; /* 十分な高さを指定 */
}

4. カードのフリップ

/* カードの表裏を切り替え */
.card {
  position: relative;
  width: 200px;
  height: 300px;
  transform-style: preserve-3d;
  transition: transform 0.6s;
}

.card:hover {
  transform: rotateY(180deg);
}

.card-front, .card-back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
}

.card-back {
  transform: rotateY(180deg);
}

animationでもっと派手に

1. ローディングスピナー

/* くるくる回るローディング */
.loader {
  width: 50px;
  height: 50px;
  border: 5px solid #f3f3f3;
  border-top: 5px solid #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

2. 脈打つボタン

/* 注目してほしいボタン */
.pulse-button {
  background: #e74c3c;
  color: white;
  padding: 15px 30px;
  border: none;
  border-radius: 5px;
  animation: pulse 2s infinite;
}

@keyframes pulse {
  0% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(231, 76, 60, 0.7);
  }
  50% {
    transform: scale(1.05);
    box-shadow: 0 0 0 10px rgba(231, 76, 60, 0);
  }
  100% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(231, 76, 60, 0);
  }
}

3. テキストのタイピングアニメーション

/* タイプライター風 */
.typewriter {
  overflow: hidden;
  border-right: 2px solid black;
  white-space: nowrap;
  animation: 
    typing 3.5s steps(40, end),
    blink-caret 0.75s step-end infinite;
}

@keyframes typing {
  from { width: 0 }
  to { width: 100% }
}

@keyframes blink-caret {
  from, to { border-color: transparent }
  50% { border-color: black }
}

4. フェードイン

/* スクロールで表示 */
.fade-in {
  opacity: 0;
  transform: translateY(30px);
  animation: fadeIn 1s forwards;
}

@keyframes fadeIn {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

実用的なアニメーションパターン

スケルトンローディング

/* コンテンツ読み込み中の表示 */
.skeleton {
  background: linear-gradient(
    90deg,
    #f0f0f0 25%,
    #e0e0e0 50%,
    #f0f0f0 75%
  );
  background-size: 200% 100%;
  animation: loading 1.5s infinite;
}

@keyframes loading {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

/* 使用例 */
.skeleton-text {
  height: 20px;
  margin: 10px 0;
  border-radius: 4px;
}

.skeleton-avatar {
  width: 50px;
  height: 50px;
  border-radius: 50%;
}

モーダルの表示

/* 背景のオーバーレイ */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0);
  visibility: hidden;
  transition: all 0.3s ease;
}

.modal-overlay.active {
  background: rgba(0, 0, 0, 0.5);
  visibility: visible;
}

/* モーダル本体 */
.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0);
  background: white;
  padding: 30px;
  border-radius: 10px;
  transition: all 0.3s ease;
}

.modal.active {
  transform: translate(-50%, -50%) scale(1);
}

ハンバーガーメニューのアニメーション

/* 三本線→×への変形 */
.hamburger {
  width: 30px;
  height: 20px;
  position: relative;
  cursor: pointer;
}

.hamburger span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background: black;
  transition: all 0.3s ease;
}

.hamburger span:nth-child(1) { top: 0; }
.hamburger span:nth-child(2) { top: 50%; transform: translateY(-50%); }
.hamburger span:nth-child(3) { bottom: 0; }

/* クリック時 */
.hamburger.active span:nth-child(1) {
  top: 50%;
  transform: translateY(-50%) rotate(45deg);
}

.hamburger.active span:nth-child(2) {
  opacity: 0;
}

.hamburger.active span:nth-child(3) {
  bottom: 50%;
  transform: translateY(50%) rotate(-45deg);
}

パフォーマンスを考えた書き方

1. transformとopacityを使う

/* ❌ 悪い例(レイアウトの再計算が発生) */
.bad-animation {
  animation: badMove 1s infinite;
}

@keyframes badMove {
  0% { left: 0; }
  100% { left: 100px; }
}

/* ✅ 良い例(GPUで処理される) */
.good-animation {
  animation: goodMove 1s infinite;
}

@keyframes goodMove {
  0% { transform: translateX(0); }
  100% { transform: translateX(100px); }
}

高速なプロパティ:

  • transform
  • opacity
  • filter

遅いプロパティ:

  • width, height
  • top, left
  • margin, padding

2. will-changeの活用

/* アニメーション前に最適化を予告 */
.will-animate {
  will-change: transform, opacity;
}

/* アニメーション後は削除 */
.animation-done {
  will-change: auto;
}

イージング関数(動きの緩急)

/* 基本のイージング */
.ease-demo {
  /* linear: 一定速度 */
  animation: move 2s linear;
  
  /* ease: 始めと終わりがゆっくり(デフォルト) */
  animation: move 2s ease;
  
  /* ease-in: ゆっくり始まって加速 */
  animation: move 2s ease-in;
  
  /* ease-out: 速く始まって減速 */
  animation: move 2s ease-out;
  
  /* ease-in-out: ゆっくり始まってゆっくり終わる */
  animation: move 2s ease-in-out;
}

/* カスタムイージング(ベジェ曲線) */
.custom-ease {
  animation: move 2s cubic-bezier(0.68, -0.55, 0.265, 1.55); /* バウンス効果 */
}

よく使うアニメーションライブラリ風CSS

スライドイン(4方向)

/* 左から */
.slide-in-left {
  animation: slideInLeft 0.5s ease forwards;
}

@keyframes slideInLeft {
  from {
    transform: translateX(-100%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

/* 右から */
@keyframes slideInRight {
  from { transform: translateX(100%); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}

/* 上から */
@keyframes slideInTop {
  from { transform: translateY(-100%); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

/* 下から */
@keyframes slideInBottom {
  from { transform: translateY(100%); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

バウンス

.bounce {
  animation: bounce 2s infinite;
}

@keyframes bounce {
  0%, 20%, 50%, 80%, 100% {
    transform: translateY(0);
  }
  40% {
    transform: translateY(-30px);
  }
  60% {
    transform: translateY(-15px);
  }
}

レスポンシブ対応

/* モバイルではアニメーションを軽くする */
@media (max-width: 768px) {
  * {
    animation-duration: 0.1s !important;
    transition-duration: 0.1s !important;
  }
}

/* アニメーション無効化の設定を尊重 */
@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }
}

まとめ

CSSアニメーションは、思ってるより簡単です!

基本の使い分け:

  • transition: 状態変化(ホバー、クリック)
  • animation: 自動で動く(ローディング、アピール)

覚えておくプロパティ:

  • transition: 変化をスムーズに
  • transform: 移動・回転・拡大縮小
  • @keyframes: アニメーションの定義
  • animation: キーフレームアニメーションの実行

パフォーマンスTips:

  • transformopacityを優先的に使う
  • 必要な時だけwill-change
  • モバイルでは控えめに

最初は簡単なホバーエフェクトから始めて、徐々に複雑なアニメーションに挑戦してみてください。JavaScriptを使わなくても、CSSだけで驚くほど豊かな表現ができますよ!

サイトに動きがあると、ユーザー体験がぐっと良くなります。ぜひ試してみてください ✨

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?