Day 9: トランジションとアニメーション
今日学ぶこと
- CSSトランジション
- transform プロパティ
- CSSアニメーション(@keyframes)
- パフォーマンスの考慮
- アクセシビリティへの配慮
CSSトランジション
トランジションは、プロパティの変化を滑らかに補間する仕組みです。
.button {
background-color: #3b82f6;
color: white;
padding: 12px 24px;
border: none;
border-radius: 8px;
transition: background-color 0.3s ease;
}
.button:hover {
background-color: #1d4ed8;
}
transition プロパティ
/* 個別指定 */
transition-property: background-color;
transition-duration: 0.3s;
transition-timing-function: ease;
transition-delay: 0s;
/* ショートハンド */
transition: background-color 0.3s ease 0s;
/* 複数プロパティ */
transition: background-color 0.3s ease, transform 0.2s ease;
/* すべてのプロパティ */
transition: all 0.3s ease;
タイミング関数
| 値 | 特徴 |
|---|---|
ease |
ゆっくり→速く→ゆっくり(デフォルト) |
ease-in |
ゆっくり開始 |
ease-out |
ゆっくり終了 |
ease-in-out |
両端がゆっくり |
linear |
一定速度 |
cubic-bezier() |
カスタムカーブ |
flowchart LR
subgraph Timing["タイミング関数"]
Ease["ease<br>自然な動き"]
Linear["linear<br>一定速度"]
EIO["ease-in-out<br>滑らかな開始と終了"]
end
style Ease fill:#3b82f6,color:#fff
style Linear fill:#22c55e,color:#fff
style EIO fill:#f59e0b,color:#fff
transform
要素を変形させるプロパティです。レイアウトに影響を与えません。
/* 移動 */
transform: translateX(20px);
transform: translateY(-10px);
transform: translate(20px, -10px);
/* 拡大・縮小 */
transform: scale(1.1);
transform: scale(1.5, 0.5);
/* 回転 */
transform: rotate(45deg);
/* 傾斜 */
transform: skew(10deg);
/* 複数組み合わせ */
transform: translate(20px, 0) scale(1.1) rotate(5deg);
| 関数 | 説明 | 例 |
|---|---|---|
translate() |
移動 | translate(10px, 20px) |
scale() |
拡大縮小 | scale(1.2) |
rotate() |
回転 | rotate(45deg) |
skew() |
傾斜 | skew(10deg) |
transform-origin
変形の基点を変更します。
.card {
transform-origin: top left;
transform: rotate(5deg);
}
よくあるトランジションパターン
ホバーエフェクト
.card {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}
ボタンエフェクト
.btn {
transition: all 0.2s ease;
}
.btn:hover {
background-color: #1d4ed8;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
}
.btn:active {
transform: translateY(0);
box-shadow: 0 2px 4px rgba(59, 130, 246, 0.3);
}
フェードイン
.fade {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.5s ease, transform 0.5s ease;
}
.fade.visible {
opacity: 1;
transform: translateY(0);
}
CSSアニメーション(@keyframes)
トランジションよりも複雑なアニメーションを定義できます。
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.element {
animation: fadeIn 0.5s ease forwards;
}
複数のキーフレーム
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.pulse {
animation: pulse 2s ease-in-out infinite;
}
animation プロパティ
animation-name: fadeIn;
animation-duration: 0.5s;
animation-timing-function: ease;
animation-delay: 0s;
animation-iteration-count: 1; /* infinite で無限 */
animation-direction: normal; /* alternate で往復 */
animation-fill-mode: forwards; /* 終了状態を維持 */
/* ショートハンド */
animation: fadeIn 0.5s ease 0s 1 normal forwards;
| プロパティ | 値の例 | 説明 |
|---|---|---|
iteration-count |
infinite, 3 |
繰り返し回数 |
direction |
normal, alternate, reverse |
方向 |
fill-mode |
forwards, backwards, both |
終了時の状態 |
よくあるアニメーションパターン
スピナー
@keyframes spin {
to { transform: rotate(360deg); }
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #e2e8f0;
border-top-color: #3b82f6;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
バウンス
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-20px); }
}
.bounce {
animation: bounce 1s ease infinite;
}
スライドイン
@keyframes slideIn {
from {
opacity: 0;
transform: translateX(-100%);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.slide-in {
animation: slideIn 0.5s ease forwards;
}
パフォーマンスの考慮
GPUで高速なプロパティ
/* ✅ 高速(GPUで処理) */
transform: translateX(100px);
opacity: 0.5;
/* ❌ 低速(レイアウト再計算が発生) */
left: 100px;
width: 200px;
margin-left: 100px;
| プロパティ | パフォーマンス |
|---|---|
transform |
✅ 高速 |
opacity |
✅ 高速 |
color, background-color |
⚠️ 中程度 |
width, height, margin |
❌ 低速 |
ルール: アニメーションには**
transformとopacity**を使いましょう。位置の移動にはleft/topではなくtranslate()を使います。
will-change
.animated-element {
will-change: transform, opacity;
}
注意:
will-changeはブラウザにアニメーションの準備を促しますが、多用しないでください。メモリを余分に消費します。
アクセシビリティへの配慮
prefers-reduced-motion
動きの少ない表示を好むユーザー(動きに敏感な方)への配慮です。
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
重要: アニメーションは必ず
prefers-reduced-motionに対応しましょう。これはアクセシビリティの必須事項です。
実践: インタラクティブなカード
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
background: #f8fafc;
padding: 48px 16px;
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
max-width: 900px;
margin: 0 auto;
}
.card {
background: white;
border-radius: 12px;
padding: 32px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card:hover {
transform: translateY(-8px);
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.12);
}
.card h3 {
margin-bottom: 12px;
}
.card p {
color: #64748b;
margin-bottom: 16px;
}
.card .btn {
display: inline-block;
background: #3b82f6;
color: white;
padding: 8px 20px;
border-radius: 6px;
text-decoration: none;
font-weight: 600;
transition: background-color 0.2s ease, transform 0.1s ease;
}
.card .btn:hover {
background: #2563eb;
transform: translateY(-1px);
}
.card .btn:active {
transform: translateY(0);
}
/* アクセシビリティ */
@media (prefers-reduced-motion: reduce) {
.card,
.card .btn {
transition: none;
}
}
まとめ
| 概念 | 説明 |
|---|---|
transition |
プロパティ変化の滑らかな補間 |
transform |
要素の変形(移動、拡大、回転) |
@keyframes |
複雑なアニメーションの定義 |
animation |
キーフレームアニメーションの適用 |
will-change |
アニメーション最適化のヒント |
prefers-reduced-motion |
アクセシビリティ対応 |
重要ポイント
- アニメーションには**
transformとopacity**を使う transitionはシンプルな変化、@keyframesは複雑なアニメーション- **
prefers-reduced-motion**に必ず対応する - パフォーマンスを考慮してGPUで処理されるプロパティを選ぶ
練習問題
問題1: 基本
ホバー時に色が変わり、少し浮き上がるボタンを作成してください。
問題2: 応用
@keyframesを使ったローディングスピナーを作成してください。
チャレンジ問題
カードのフェードインアニメーション(スクロールで画面に入ったら表示)を@keyframesとJavaScriptのIntersectionObserverで実装してください。prefers-reduced-motionにも対応させましょう。
参考リンク
次回予告: Day 10では「総合プロジェクト」に取り組みます。これまで学んだすべてのCSS技術を使って、ポートフォリオサイトをスタイリングしましょう!