CSS transform・transition入門
要素の変形とアニメーション効果
CSSのtransformによる要素の変形と、transitionによるスムーズなアニメーション効果の作り方を解説します。
こんな人向けの記事です
- CSSで要素を回転・拡大・移動させたい
- ホバー時にスムーズなアニメーションをつけたい
- 3D変形の基本を学びたい
Step 1transformの基本(translate, rotate, scale, skew)
transform プロパティは、要素を移動・回転・拡大縮小・傾斜させることができます。要素の配置(レイアウト)には影響せず、見た目だけを変形させるのが特徴です。
| 関数 | 効果 | 例 |
|---|---|---|
translate(x, y) | 移動 | translate(50px, 20px) |
rotate(角度) | 回転 | rotate(45deg) |
scale(x, y) | 拡大縮小 | scale(1.5) |
skew(x, y) | 傾斜 | skew(10deg, 5deg) |
translate — 要素の移動
translate() は要素を水平・垂直方向に移動させます。レイアウト上の位置はそのままで、見た目だけが動きます。
<div class="box">元の位置</div>
<div class="box moved">移動後</div>
.box {
width: 80px;
height: 80px;
background: #3498db;
border-radius: 8px;
}
.moved {
/* 右に30px、上に10px移動 */
transform: translate(30px, -10px);
background: #e74c3c;
}
translateX(50px)、垂直方向だけなら translateY(-20px) と単軸指定もできます。% 指定では要素自身のサイズが基準になるため、translateX(-50%) で要素の幅の半分だけ左に移動できます。
rotate — 要素の回転
rotate() は要素を指定した角度だけ回転させます。正の値で時計回り、負の値で反時計回りです。
<div class="box">0deg</div>
<div class="box rotate-45">45deg</div>
<div class="box rotate-90">90deg</div>
<div class="box rotate-neg">-30deg</div>
.box {
width: 70px;
height: 70px;
background: #3498db;
border-radius: 8px;
}
.rotate-45 {
transform: rotate(45deg); /* 時計回り45度 */
background: #e74c3c;
}
.rotate-90 {
transform: rotate(90deg); /* 時計回り90度 */
background: #2ecc71;
}
.rotate-neg {
transform: rotate(-30deg); /* 反時計回り30度 */
background: #f39c12;
}
scale — 拡大縮小
scale() は要素を拡大・縮小します。1 が元のサイズ、1.5 で1.5倍、0.5 で半分になります。
<div class="box scale-half">0.5</div>
<div class="box">1.0</div>
<div class="box scale-up">1.5</div>
<div class="box scale-xy">1.5, 0.8</div>
.box {
width: 60px;
height: 60px;
background: #3498db;
border-radius: 8px;
}
.scale-half {
transform: scale(0.5); /* 半分に縮小 */
background: #e74c3c;
}
.scale-up {
transform: scale(1.5); /* 1.5倍に拡大 */
background: #2ecc71;
}
.scale-xy {
transform: scale(1.5, 0.8); /* 横1.5倍、縦0.8倍 */
background: #9b59b6;
}
skew — 傾斜
skew() は要素を傾斜(ゆがみ)させます。平行四辺形のような形を作るのに使います。
<div class="box">なし</div>
<div class="box skew-x">skewX(15deg)</div>
<div class="box skew-y">skewY(10deg)</div>
<div class="box skew-xy">skew(10,5)</div>
.box {
width: 80px;
height: 60px;
background: #3498db;
}
.skew-x {
transform: skewX(15deg); /* X軸方向に傾斜 */
background: #e74c3c;
}
.skew-y {
transform: skewY(10deg); /* Y軸方向に傾斜 */
background: #2ecc71;
}
.skew-xy {
transform: skew(10deg, 5deg); /* 両方向に傾斜 */
background: #f39c12;
}
Step 2transformの合成とtransform-origin
transform プロパティには複数の変形関数をスペース区切りで指定できます。記述順に変形が適用されるため、順序によって結果が変わります。
複数のtransformを合成する
<div class="box pattern-a">移動→回転</div>
<div class="box pattern-b">回転→移動</div>
/* パターンA: 移動してから回転 */
.pattern-a {
transform: translate(20px, 0) rotate(30deg);
background: #3498db;
}
/* パターンB: 回転してから移動 */
.pattern-b {
transform: rotate(30deg) translate(20px, 0);
background: #e74c3c;
}
/* 回転後のtranslateは回転した座標系で移動するため
結果が異なる! */
transform の変形関数は右から左に適用されます(数学的な行列の乗算と同じ)。rotate() の後の translate() は回転した座標系で移動するため、意図しない位置に要素が移動することがあります。
transform-origin — 変形の基準点
transform-origin は変形の基準点を指定します。デフォルトは要素の中心(center center = 50% 50%)です。
<div class="box origin-center">center</div>
<div class="box origin-topleft">top left</div>
<div class="box origin-bottom">bottom</div>
.box {
width: 70px;
height: 70px;
border-radius: 8px;
transform: rotate(45deg);
}
/* 中心基準(デフォルト) */
.origin-center {
transform-origin: center center;
background: #3498db;
}
/* 左上基準 */
.origin-topleft {
transform-origin: top left;
background: #e74c3c;
}
/* 下端中央基準 */
.origin-bottom {
transform-origin: bottom center;
background: #2ecc71;
}
| 値 | 基準点 |
|---|---|
center center(デフォルト) | 要素の中心 |
top left | 左上 |
top right | 右上 |
bottom left | 左下 |
bottom right | 右下 |
50% 0% | 上端中央(数値指定も可) |
Step 3transitionの基本
transition は、CSSプロパティの値が変わるときにスムーズなアニメーションを適用します。ホバー時の色変化やサイズ変化をなめらかにするのに最もよく使われます。
| プロパティ | 説明 | 例 |
|---|---|---|
transition-property | アニメーションさせるプロパティ | background, transform |
transition-duration | アニメーションの時間 | 0.3s |
transition-timing-function | アニメーションの加速曲線 | ease |
transition-delay | アニメーション開始までの遅延 | 0.1s |
/* 個別指定 */
.box {
transition-property: background, transform;
transition-duration: 0.3s;
transition-timing-function: ease;
transition-delay: 0s;
}
/* ショートハンド(推奨) */
.box {
transition: background 0.3s ease, transform 0.3s ease;
}
/* 全プロパティを対象にする */
.box {
transition: all 0.3s ease;
}
基本的なtransitionの使い方
ホバーしてください:
<div class="box">ホバー</div>
.box {
width: 120px;
padding: 16px;
background: #3498db;
color: #fff;
text-align: center;
border-radius: 8px;
font-weight: bold;
cursor: pointer;
/* ここでtransitionを定義 */
transition: background 0.3s ease,
transform 0.3s ease,
border-radius 0.3s ease;
}
.box:hover {
background: #e74c3c;
transform: scale(1.1);
border-radius: 24px;
}
transition は :hover ではなく、元の状態(通常のセレクタ)に記述します。これにより、ホバーを外した時もスムーズに元に戻ります。:hover にだけ書くと、外した時にパッと元に戻ってしまいます。
transition-delayで遅延アニメーション
エリア全体にホバーしてください:
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
.container {
display: flex;
gap: 16px;
}
.item {
width: 60px;
height: 60px;
background: #3498db;
border-radius: 8px;
transition: transform 0.3s ease;
cursor: pointer;
}
/* 順番にdelayを増やして波のような動き */
.item:nth-child(1) { transition-delay: 0s; }
.item:nth-child(2) { transition-delay: 0.1s; }
.item:nth-child(3) { transition-delay: 0.2s; }
.item:nth-child(4) { transition-delay: 0.3s; }
.container:hover .item {
transform: translateY(-12px);
background: #e74c3c;
}
Step 4よく使うtiming-function
transition-timing-function はアニメーションの加速・減速のカーブを制御します。同じ duration でも、timing-function によって動きの印象が大きく変わります。
| 値 | 動き | 特徴 |
|---|---|---|
ease(デフォルト) | ゆっくり始まり、加速し、ゆっくり終わる | 自然な動き。最もよく使う |
linear | 一定速度 | 機械的な動き |
ease-in | ゆっくり始まり、加速して終わる | 画面外へ出る動きに |
ease-out | 速く始まり、ゆっくり終わる | 画面内に入る動きに |
ease-in-out | ゆっくり始まり、ゆっくり終わる | easeより対称的 |
ホバーして速度の違いを比較:
<div class="track">
<div class="ball ease"></div>
</div>
<div class="track">
<div class="ball linear"></div>
</div>
<div class="track">
<div class="ball ease-in"></div>
</div>
<div class="track">
<div class="ball ease-out"></div>
</div>
<div class="track">
<div class="ball ease-in-out"></div>
</div>
.track {
height: 8px;
background: #eee;
border-radius: 4px;
position: relative;
}
.ball {
width: 32px;
height: 32px;
border-radius: 50%;
position: absolute;
top: 50%;
transform: translateY(-50%);
left: 0;
transition: left 1.5s;
}
/* ホバーで右端に移動 */
.track:hover .ball {
left: calc(100% - 32px);
}
.ease { transition-timing-function: ease; }
.linear { transition-timing-function: linear; }
.ease-in { transition-timing-function: ease-in; }
.ease-out { transition-timing-function: ease-out; }
.ease-in-out { transition-timing-function: ease-in-out; }
cubic-bezier — カスタム曲線
cubic-bezier() で独自のアニメーション曲線を定義できます。4つの制御点(0〜1の範囲)で曲線の形を決めます。
/* バウンス風(終点を超えて戻る) */
.bounce {
transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
/* スナップ(急加速して急停止) */
.snap {
transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
}
/* ゆるやかな減速 */
.smooth-out {
transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);
}
scale
rotate
translate
<div class="box bounce">バウンス</div>
<div class="box snap">スナップ</div>
<div class="box smooth">スムーズ</div>
.box {
width: 80px;
height: 80px;
border-radius: 8px;
color: #fff;
cursor: pointer;
}
/* バウンス風:終点を超えて戻る */
.bounce {
background: #e74c3c;
transition: transform 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
.bounce:hover { transform: scale(1.3); }
/* スナップ:急加速→急停止 */
.snap {
background: #3498db;
transition: transform 0.4s cubic-bezier(0.7, 0, 0.3, 1);
}
.snap:hover { transform: rotate(180deg); }
/* スムーズ減速 */
.smooth {
background: #2ecc71;
transition: transform 0.8s cubic-bezier(0.25, 0.1, 0.25, 1);
}
.smooth:hover { transform: translateY(-20px); }
Step 53D変形(perspective, rotateX, rotateY)
CSSでは3D空間での変形も可能です。perspective で奥行きを設定し、rotateX()、rotateY()、translateZ() で3D的な動きを表現します。
| プロパティ / 関数 | 説明 |
|---|---|
perspective | 視点からの距離(奥行き感)。値が小さいほど立体感が強い |
rotateX(角度) | X軸(横方向)を中心に回転 |
rotateY(角度) | Y軸(縦方向)を中心に回転 |
rotateZ(角度) | Z軸を中心に回転(= 2Dのrotateと同じ) |
translateZ(距離) | Z軸方向に移動(手前/奥へ) |
transform-style: preserve-3d | 子要素も3D空間で描画する |
perspectiveの効果
<!-- perspectiveは親要素に設定 -->
<div class="scene-200">
<div class="card">3D</div>
</div>
<div class="scene-500">
<div class="card">3D</div>
</div>
<div class="scene-1000">
<div class="card">3D</div>
</div>
.card {
width: 80px;
height: 80px;
background: #3498db;
border-radius: 8px;
transform: rotateY(40deg);
}
/* perspectiveの値が小さいほど立体感が強い */
.scene-200 { perspective: 200px; }
.scene-500 { perspective: 500px; }
.scene-1000 { perspective: 1000px; }
rotateX / rotateY によるカードフリップ
ホバーでカードが裏返ります:
<div class="scene">
<div class="card">
<div class="front">表面(Front)</div>
<div class="back">裏面(Back)</div>
</div>
</div>
/* 親要素にperspectiveを設定 */
.scene {
perspective: 600px;
width: 160px;
height: 100px;
}
.card {
width: 100%;
height: 100%;
position: relative;
transition: transform 0.6s ease;
transform-style: preserve-3d; /* 子要素を3D空間で描画 */
}
.scene:hover .card {
transform: rotateY(180deg);
}
.front, .back {
position: absolute;
width: 100%;
height: 100%;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-weight: bold;
backface-visibility: hidden; /* 裏面を非表示 */
}
.front { background: #3498db; }
.back {
background: #e74c3c;
transform: rotateY(180deg); /* 裏面を最初から裏返しに */
}
perspectiveは親要素に設定する(子要素の3D表現を制御)transform-style: preserve-3dがないと子要素が平面化されるbackface-visibility: hiddenでカードの裏面を非表示にする
translateZ — 奥行き方向の移動
ホバーで手前・奥に移動:
+60px
-60px
<div class="scene">
<div class="box near">手前へ</div>
<div class="box far">奥へ</div>
</div>
.scene {
perspective: 400px;
display: flex;
gap: 40px;
justify-content: center;
}
.box {
width: 70px;
height: 70px;
border-radius: 8px;
color: #fff;
transition: transform 0.4s ease;
cursor: pointer;
}
/* 手前に近づく(大きく見える) */
.near { background: #3498db; }
.near:hover { transform: translateZ(60px); }
/* 奥に離れる(小さく見える) */
.far { background: #e74c3c; }
.far:hover { transform: translateZ(-60px); }
Step 6実践的なホバーエフェクト集
ここまで学んだ transform と transition を組み合わせた、実務で使えるホバーエフェクトを紹介します。
1. ボタンのリフトアップ
<button class="lift-btn">ホバーで浮き上がる</button>
.lift-btn {
display: inline-block;
padding: 14px 36px;
background: #3498db;
color: #fff;
border: none;
border-radius: 8px;
font-size: 15px;
font-weight: bold;
cursor: pointer;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.lift-btn:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
}
.lift-btn:active {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
2. カードの拡大+影
カード1
ホバーで浮き上がります
カード2
ホバーで浮き上がります
<div class="card-list">
<div class="card">
<h4>カード1</h4>
<p>ホバーで浮き上がります</p>
</div>
<div class="card">
<h4>カード2</h4>
<p>ホバーで浮き上がります</p>
</div>
</div>
.card-list {
display: flex;
gap: 20px;
}
.card {
width: 140px;
padding: 20px;
background: #fff;
border: 1px solid #e0e0e0;
border-radius: 12px;
text-align: center;
cursor: pointer;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-8px) scale(1.02);
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
}
3. 画像のズーム+オーバーレイ
<div class="img-container">
<img src="photo.jpg" alt="写真">
<div class="overlay">
<span>View More</span>
</div>
</div>
.img-container {
width: 200px;
height: 140px;
overflow: hidden; /* はみ出た部分を隠す */
border-radius: 12px;
position: relative;
cursor: pointer;
}
.img-container img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
/* ホバーで画像を拡大 */
.img-container:hover img {
transform: scale(1.15);
}
/* オーバーレイ */
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
}
.img-container:hover .overlay {
opacity: 1;
}
.overlay span {
color: #fff;
font-weight: bold;
transform: translateY(10px);
transition: transform 0.3s ease;
}
.img-container:hover .overlay span {
transform: translateY(0);
}
4. アンダーラインアニメーション
<nav class="nav">
<a href="#" class="nav-link">ホーム</a>
<a href="#" class="nav-link">サービス</a>
<a href="#" class="nav-link">お問い合わせ</a>
</nav>
.nav { display: flex; gap: 24px; }
.nav-link {
text-decoration: none;
color: #333;
font-weight: bold;
position: relative;
padding-bottom: 4px;
}
/* 擬似要素でアンダーライン */
.nav-link::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0; /* 初期は幅0 */
height: 2px;
background: #3498db;
transition: width 0.3s ease;
}
.nav-link:hover::after {
width: 100%; /* ホバーで全幅に伸びる */
}
5. 3Dチルト効果
ホバーで3Dチルト:
<div class="scene">
<div class="tilt-card">3D Tilt</div>
</div>
.scene {
perspective: 600px;
}
.tilt-card {
width: 120px;
height: 160px;
background: linear-gradient(135deg, #667eea, #764ba2);
border-radius: 16px;
color: #fff;
font-weight: bold;
cursor: pointer;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
transition: transform 0.4s ease, box-shadow 0.4s ease;
}
.tilt-card:hover {
transform: rotateX(10deg) rotateY(-10deg) translateZ(20px);
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.2);
}
まとめtransform・transitionのポイント
| トピック | ポイント |
|---|---|
| transform | translate(移動)、rotate(回転)、scale(拡縮)、skew(傾斜)の4種類 |
| transform合成 | スペース区切りで複数指定。順序で結果が変わるので注意 |
| transform-origin | 変形の基準点。デフォルトは center center |
| transition | 元の状態に定義する。property duration timing-function delay のショートハンド |
| timing-function | ease が基本。cubic-bezier() でカスタム曲線も可能 |
| 3D変形 | 親に perspective、子に transform-style: preserve-3d と backface-visibility: hidden |