CSSで簡単フェードイン!初心者向けにアニメーションの基本と具体例を解説

CSS

Webサイトを見ていると、ページを開いたときやスクロールしたときに、文字や画像がふわっと現れるアニメーションをよく見かけます。

あれは**フェードイン(fade-in)**と呼ばれる演出で、CSSだけで簡単に実装できます。

この記事では、以下のことを初心者にもわかるように、ていねいに解説します:

  • CSSアニメーションでフェードインを作る方法
  • 実際に動くサンプルコードと活用例
  • よくある間違いや注意点
  • JavaScript と組み合わせた応用テクニック

これを読めば、あなたのWebサイトもぐっと洗練された印象になりますよ!

スポンサーリンク

フェードインってどんな動き?

フェードインの基本概念

フェードインとは、以下のような動きのアニメーションです:

動きの流れ

  1. 最初は透明(見えない状態)
  2. 徐々に不透明になって現れる
  3. 最終的に完全に見える状態になる

フェードインを使う効果

ユーザー体験の向上

なめらかな表示

  • 急にコンテンツが現れるよりもやさしい印象
  • ページの読み込みがスムーズに感じられる
  • ユーザーの注意を自然に引く

プロフェッショナルな印象

  • サイト全体がおしゃれに見える
  • 洗練されたデザインの演出
  • ブランドイメージの向上

よく使われる場面

Webサイトでの活用例

ページ読み込み時

  • ヒーローセクションの表示
  • ロゴやタイトルの登場
  • メインコンテンツの段階的表示

スクロール時の演出

  • セクションが見えたときの表示
  • 画像ギャラリーの段階的表示
  • 統計数字やグラフの登場

ユーザー操作への反応

  • ボタンのホバー効果
  • モーダルウィンドウの表示
  • メニューの開閉アニメーション

CSSアニメーションの基本仕組み

CSSアニメーションを作る2つの方法

1. @keyframes + animation

完全にカスタマイズ可能

  • 複雑なアニメーションに対応
  • タイミングを細かく制御
  • ページ読み込み時の自動再生

2. transition

シンプルで手軽

  • 状態変化のアニメーション
  • ホバーやクリック時の演出
  • 記述が簡潔

アニメーションを作る基本ステップ

@keyframes を使う場合の流れ

  1. @keyframes で動きを定義する
  2. 対象の要素に animation プロパティを指定する
  3. 必要に応じて細かい設定を調整する

基本のフェードインアニメーション

シンプルなフェードイン

最も基本的なコード

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.fade-in {
  animation: fadeIn 2s ease-in-out;
}

HTMLでの使用例

<div class="fade-in">
  <h2>このテキストはフェードインします</h2>
  <p>ページを読み込むと、ふわっと現れます。</p>
</div>

パーセンテージを使った詳細制御

より細かいタイミング調整

@keyframes detailedFadeIn {
  0% {
    opacity: 0;
    transform: translateY(20px);
  }
  50% {
    opacity: 0.5;
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

.detailed-fade {
  animation: detailedFadeIn 1.5s ease-out;
}

この例では、透明度の変化に加えて縦方向の移動も追加されています。

animation プロパティの詳細

個別プロパティでの記述

.fade-element {
  animation-name: fadeIn;
  animation-duration: 2s;
  animation-timing-function: ease-in-out;
  animation-delay: 0s;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-fill-mode: forwards;
}

短縮記法での記述

.fade-element {
  /* name | duration | timing-function | delay | iteration-count | direction | fill-mode */
  animation: fadeIn 2s ease-in-out 0s 1 normal forwards;
}

タイミング関数の種類

よく使われるタイミング関数

ease(デフォルト)

.ease-fade {
  animation: fadeIn 2s ease;
  /* ゆっくり始まって、速くなって、ゆっくり終わる */
}

ease-in

.ease-in-fade {
  animation: fadeIn 2s ease-in;
  /* ゆっくり始まって、だんだん速くなる */
}

ease-out

.ease-out-fade {
  animation: fadeIn 2s ease-out;
  /* 速く始まって、だんだんゆっくりになる */
}

linear

.linear-fade {
  animation: fadeIn 2s linear;
  /* 一定の速度で変化 */
}

cubic-bezier(カスタム)

.custom-fade {
  animation: fadeIn 2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  /* 完全にカスタマイズされた動き */
}

実践的なフェードインパターン

遅延を使った順次表示

複数要素の段階的表示

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.stagger-fade {
  opacity: 0;
  animation: fadeInUp 0.8s ease-out forwards;
}

.stagger-fade:nth-child(1) { animation-delay: 0.1s; }
.stagger-fade:nth-child(2) { animation-delay: 0.3s; }
.stagger-fade:nth-child(3) { animation-delay: 0.5s; }
.stagger-fade:nth-child(4) { animation-delay: 0.7s; }

HTMLでの使用例

<div class="card-container">
  <div class="card stagger-fade">カード1</div>
  <div class="card stagger-fade">カード2</div>
  <div class="card stagger-fade">カード3</div>
  <div class="card stagger-fade">カード4</div>
</div>

方向性のあるフェードイン

上から下へのフェードイン

@keyframes fadeInDown {
  from {
    opacity: 0;
    transform: translateY(-30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.fade-down {
  animation: fadeInDown 1s ease-out;
}

左から右へのフェードイン

@keyframes fadeInLeft {
  from {
    opacity: 0;
    transform: translateX(-30px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.fade-left {
  animation: fadeInLeft 1s ease-out;
}

拡大しながらフェードイン

@keyframes fadeInScale {
  from {
    opacity: 0;
    transform: scale(0.8);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

.fade-scale {
  animation: fadeInScale 1s ease-out;
}

回転しながらフェードイン

360度回転フェードイン

@keyframes fadeInRotate {
  from {
    opacity: 0;
    transform: rotate(-180deg) scale(0.5);
  }
  to {
    opacity: 1;
    transform: rotate(0deg) scale(1);
  }
}

.fade-rotate {
  animation: fadeInRotate 1.5s ease-out;
}

transitionを使ったフェードイン

ホバー時のフェードイン

基本的なホバー効果

.fade-hover {
  opacity: 0.7;
  transition: opacity 0.3s ease;
}

.fade-hover:hover {
  opacity: 1;
}

画像ギャラリーでの活用

.gallery-item {
  position: relative;
  overflow: hidden;
}

.gallery-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.7);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.4s ease;
}

.gallery-item:hover .gallery-overlay {
  opacity: 1;
}

クリック時のフェードイン

JavaScript と組み合わせた制御

.modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0.3s ease;
}

.modal.show {
  opacity: 1;
  visibility: visible;
}

.modal-content {
  background: white;
  padding: 2rem;
  border-radius: 8px;
  transform: scale(0.7);
  transition: transform 0.3s ease;
}

.modal.show .modal-content {
  transform: scale(1);
}

JavaScriptとの組み合わせ

スクロール連動フェードイン

Intersection Observer を使った実装

// スクロール時にフェードインするJavaScript
const observerOptions = {
  threshold: 0.1,
  rootMargin: '0px 0px -50px 0px'
};

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('animate');
    }
  });
}, observerOptions);

// 観察対象の要素を登録
document.querySelectorAll('.scroll-fade').forEach(el => {
  observer.observe(el);
});

CSSクラスの定義

.scroll-fade {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.8s ease, transform 0.8s ease;
}

.scroll-fade.animate {
  opacity: 1;
  transform: translateY(0);
}

要素ごとの遅延設定

data属性を使った柔軟な制御

document.querySelectorAll('.stagger-element').forEach((el, index) => {
  el.style.animationDelay = `${index * 0.2}s`;
});
.stagger-element {
  opacity: 0;
  animation: fadeInUp 0.8s ease forwards;
}
<div class="stagger-element">要素1</div>
<div class="stagger-element">要素2</div>
<div class="stagger-element">要素3</div>

パフォーマンスの最適化

GPU加速の活用

transform と opacity の使用

/* パフォーマンスの良い書き方 */
.optimized-fade {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.5s ease, transform 0.5s ease;
  will-change: opacity, transform;
}

.optimized-fade.show {
  opacity: 1;
  transform: translateY(0);
}

will-change プロパティの活用

.performance-fade {
  will-change: opacity, transform;
  /* アニメーション後は will-change を解除 */
}

避けるべきプロパティ

パフォーマンスに影響する書き方

/* 避けるべき:レイアウトを変更するプロパティ */
.slow-animation {
  animation: badFade 1s ease;
}

@keyframes badFade {
  from {
    width: 0px;      /* レイアウト再計算が発生 */
    height: 0px;     /* レイアウト再計算が発生 */
    margin: 0px;     /* レイアウト再計算が発生 */
  }
  to {
    width: 200px;
    height: 200px;
    margin: 20px;
  }
}
/* 推奨:transform と opacity のみ使用 */
.fast-animation {
  animation: goodFade 1s ease;
}

@keyframes goodFade {
  from {
    opacity: 0;
    transform: scale(0) translateY(20px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

よくある間違いと注意点

opacity の理解

レイアウトへの影響

重要なポイント

  • opacity: 0 は要素を透明にするだけ
  • レイアウト上のスペースは確保されたまま
  • マウスイベントも有効
/* 透明だがクリック可能 */
.transparent-clickable {
  opacity: 0;
  /* この要素は見えないがクリックできる */
}

/* 完全に非表示 */
.completely-hidden {
  display: none;
  /* この要素は存在しない扱い */
}

visibility との使い分け

/* パターン1: 透明だがスペース確保、イベント無効 */
.invisible {
  visibility: hidden;
}

/* パターン2: 透明だがスペース確保、イベント有効 */
.transparent {
  opacity: 0;
}

/* パターン3: 完全に削除 */
.gone {
  display: none;
}

animation-fill-mode の重要性

アニメーション前後の状態制御

/* 問題のある書き方 */
.problematic-fade {
  animation: fadeIn 2s ease;
  /* アニメーション前:通常状態(opacity: 1)で見える */
  /* アニメーション後:通常状態に戻る */
}

/* 正しい書き方 */
.correct-fade {
  opacity: 0; /* 初期状態を明示 */
  animation: fadeIn 2s ease forwards;
  /* forwards で最終状態を維持 */
}

fill-mode の種類

.fill-mode-examples {
  /* none: アニメーション前後は通常状態 */
  animation-fill-mode: none;
  
  /* forwards: 最終フレームの状態を維持 */
  animation-fill-mode: forwards;
  
  /* backwards: 最初のフレームの状態から開始 */
  animation-fill-mode: backwards;
  
  /* both: forwards + backwards */
  animation-fill-mode: both;
}

遅延アニメーションでの注意

FOUC(Flash of Unstyled Content)の防止

/* 問題: 遅延中に要素が見えてしまう */
.delayed-fade {
  animation: fadeIn 1s ease 2s; /* 2秒後に開始 */
  /* 2秒間は通常状態で見える */
}

/* 解決: 初期状態とfill-modeを適切に設定 */
.delayed-fade-correct {
  opacity: 0; /* 初期状態で非表示 */
  animation: fadeIn 1s ease 2s both; /* both で初期状態も制御 */
}

アクセシビリティの配慮

prefers-reduced-motion への対応

モーションを減らしたいユーザーへの配慮

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

.accessible-fade {
  animation: fadeIn 0.5s ease;
}

/* アニメーションを減らしたいユーザーへの対応 */
@media (prefers-reduced-motion: reduce) {
  .accessible-fade {
    animation: none;
    opacity: 1; /* 即座に表示 */
  }
}

フォーカス管理

キーボードナビゲーションでの配慮

.fade-button {
  opacity: 0.7;
  transition: opacity 0.3s ease;
}

.fade-button:hover,
.fade-button:focus {
  opacity: 1;
}

/* フォーカス時の視覚的フィードバック */
.fade-button:focus {
  outline: 2px solid #007acc;
  outline-offset: 2px;
}

実際のプロジェクトでの活用例

ヒーローセクション

ページトップの印象的な演出

.hero {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.hero-title {
  opacity: 0;
  transform: translateY(30px);
  animation: heroFadeIn 1s ease 0.5s forwards;
}

.hero-subtitle {
  opacity: 0;
  transform: translateY(30px);
  animation: heroFadeIn 1s ease 1s forwards;
}

.hero-button {
  opacity: 0;
  transform: translateY(30px);
  animation: heroFadeIn 1s ease 1.5s forwards;
}

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

カードグリッド

商品一覧やブログ記事の表示

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 2rem;
}

.card {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.8s ease, transform 0.8s ease;
}

.card.visible {
  opacity: 1;
  transform: translateY(0);
}

/* カードのホバー効果 */
.card:hover {
  transform: translateY(-5px);
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}

画像ギャラリー

写真の段階的表示

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 1rem;
}

.gallery-item {
  opacity: 0;
  transform: scale(0.8);
  transition: opacity 0.6s ease, transform 0.6s ease;
}

.gallery-item.loaded {
  opacity: 1;
  transform: scale(1);
}

.gallery-item img {
  width: 100%;
  height: 200px;
  object-fit: cover;
  border-radius: 8px;
}

まとめ

CSSフェードインアニメーションは、Webサイトの印象を大きく向上させる効果的な手法です。

重要なポイントの再確認

基本的な実装方法

  • @keyframesanimation で完全制御
  • transition でシンプルな状態変化
  • opacitytransform の組み合わせ

パフォーマンスの考慮

  • GPU加速を活用する書き方
  • レイアウト変更を避けるプロパティ選択
  • will-change の適切な使用

アクセシビリティ対応

  • prefers-reduced-motion への配慮
  • フォーカス管理とキーボードナビゲーション
  • 適切なタイミング設定

実装の成功要因

デザイン面

  1. 統一感:サイト全体で一貫したアニメーション
  2. 適度な演出:過度にならない自然な動き
  3. 目的の明確化:装飾ではなく UX 向上のため

技術面

  1. パフォーマンス重視:60fps を維持する実装
  2. 段階的強化:アニメーションなしでも機能する設計
  3. ブラウザ対応:古いブラウザでの fallback

コメント

タイトルとURLをコピーしました