Webサイトを見ていると、ページを開いたときやスクロールしたときに、文字や画像がふわっと現れるアニメーションをよく見かけます。
あれは**フェードイン(fade-in)**と呼ばれる演出で、CSSだけで簡単に実装できます。
この記事では、以下のことを初心者にもわかるように、ていねいに解説します:
- CSSアニメーションでフェードインを作る方法
- 実際に動くサンプルコードと活用例
- よくある間違いや注意点
- JavaScript と組み合わせた応用テクニック
これを読めば、あなたのWebサイトもぐっと洗練された印象になりますよ!
フェードインってどんな動き?
フェードインの基本概念
フェードインとは、以下のような動きのアニメーションです:
動きの流れ
- 最初は透明(見えない状態)
- 徐々に不透明になって現れる
- 最終的に完全に見える状態になる
フェードインを使う効果
ユーザー体験の向上
なめらかな表示
- 急にコンテンツが現れるよりもやさしい印象
- ページの読み込みがスムーズに感じられる
- ユーザーの注意を自然に引く
プロフェッショナルな印象
- サイト全体がおしゃれに見える
- 洗練されたデザインの演出
- ブランドイメージの向上
よく使われる場面
Webサイトでの活用例
ページ読み込み時
- ヒーローセクションの表示
- ロゴやタイトルの登場
- メインコンテンツの段階的表示
スクロール時の演出
- セクションが見えたときの表示
- 画像ギャラリーの段階的表示
- 統計数字やグラフの登場
ユーザー操作への反応
- ボタンのホバー効果
- モーダルウィンドウの表示
- メニューの開閉アニメーション
CSSアニメーションの基本仕組み
CSSアニメーションを作る2つの方法
1. @keyframes + animation
完全にカスタマイズ可能
- 複雑なアニメーションに対応
- タイミングを細かく制御
- ページ読み込み時の自動再生
2. transition
シンプルで手軽
- 状態変化のアニメーション
- ホバーやクリック時の演出
- 記述が簡潔
アニメーションを作る基本ステップ
@keyframes を使う場合の流れ
@keyframes
で動きを定義する- 対象の要素に
animation
プロパティを指定する - 必要に応じて細かい設定を調整する
基本のフェードインアニメーション
シンプルなフェードイン
最も基本的なコード
@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サイトの印象を大きく向上させる効果的な手法です。
重要なポイントの再確認
基本的な実装方法
@keyframes
とanimation
で完全制御transition
でシンプルな状態変化opacity
とtransform
の組み合わせ
パフォーマンスの考慮
- GPU加速を活用する書き方
- レイアウト変更を避けるプロパティ選択
will-change
の適切な使用
アクセシビリティ対応
prefers-reduced-motion
への配慮- フォーカス管理とキーボードナビゲーション
- 適切なタイミング設定
実装の成功要因
デザイン面
- 統一感:サイト全体で一貫したアニメーション
- 適度な演出:過度にならない自然な動き
- 目的の明確化:装飾ではなく UX 向上のため
技術面
- パフォーマンス重視:60fps を維持する実装
- 段階的強化:アニメーションなしでも機能する設計
- ブラウザ対応:古いブラウザでの fallback
コメント