CSS REFERENCE

レイアウト・構造

transform 要素

ー 要素を移動・回転・拡縮・歪める、レイアウトを壊さない変形プロパティ

POINT !

transform 要素のポイント!

  • transform による変形はレイアウトに影響しない。translateX(100px) で要素を動かしても、他の要素の配置は一切変わらない。left / margin などでの移動とは根本的に異なる挙動で、これが transition / animation と組み合わせる際の最大の利点。
  • 複数の変換関数を組み合わせる際、記述順序が結果に影響する。transform: rotate(45deg) translateX(100px) と transform: translateX(100px) rotate(45deg) は異なる結果になる。変換は右から左の順に適用される(行列演算)。
  • transform を持つ要素は新しい重ね合わせコンテキスト(stacking context)を形成する。position: fixed の子要素を持つ場合、祖先に transform があると fixed が意図どおりに機能しなくなるため注意が必要。
  • transform: translateZ(0) や will-change: transform はブラウザに「この要素はGPUレイヤーに分離して処理せよ」というヒントになる。ただし多用するとVRAMを消費するため、アニメーションを行う要素にのみ使う。

概要

transform プロパティは、要素の視覚的な「形状」と「位置」を、ドキュメントのレイアウトフローに影響を与えることなく変換するためのプロパティです。

2D変換と3D変換の両方をサポートし、以下の変換関数を組み合わせて使います。

【2D変換関数】
・translate(x, y) / translateX() / translateY():移動
・scale(x, y) / scaleX() / scaleY():拡縮
・rotate(angle):回転
・skew(x, y) / skewX() / skewY():傾斜
・matrix(a,b,c,d,e,f):上記すべてを1つの行列で表現

【3D変換関数】
・translate3d(x,y,z) / translateZ():3D移動
・scale3d() / scaleZ():3D拡縮
・rotate3d(x,y,z,angle) / rotateX() / rotateY() / rotateZ():3D回転
・perspective():遠近感の設定

transform が CSS の中でも特別な存在である理由は「GPU アクセラレーション」にあります。transform と opacity による変化は、ブラウザのコンポジットレイヤーで処理されるため、CPUによるレイアウト再計算(reflow / repaint)が発生しません。これが、transform を animation / transition と組み合わせることで60fps の滑らかなアニメーションが実現できる根拠です。

具体的な役割

要素の中央揃え(translate(-50%,-50%))、ホバー時の浮き上がり演出(translateY)、回転アニメーション(rotate)、ローディングスピナー、カードのフリップ演出(rotateY)、スクロール連動パララックスなど幅広く使う。

アクセシビリティ

♿ transform による視覚的な変形は DOM の構造・読み上げ順序・フォーカス順序に影響しません。スクリーンリーダーは transform で移動した要素を、元の DOM 位置で読み上げます。

視覚的に隠す目的で transform: scale(0) や translate(-9999px) を使う手法がありますが、これらの要素はフォーカス可能なまま残るため、キーボードユーザーが見えない要素にフォーカスする問題が起きます。視覚的に隠す場合は visibility: hidden または display: none を使ってください。

また、rotation・scale などのアニメーションは前庭障害のあるユーザーに影響を与えるため、prefers-reduced-motion への対応は必須です。

セットで使うプロパティ

📦 transform は対象要素自体の描画を変換しますが、その子要素も含めてすべて変換されます。

【重ね合わせコンテキストの生成】
transform(none 以外)が設定された要素は、新たな重ね合わせコンテキストを作ります。これにより:
・z-index の効果がこの要素の内部に閉じる
・子要素の position: fixed がビューポートでなくこの要素を基準にする

【transform-origin】
変換の基準点(原点)を指定します。デフォルトは要素の中心(50% 50%)。
rotate の回転中心や scale の拡大基点を変えたい場合に使います。

【perspective プロパティとの違い】
transform: perspective() は transform 関数のひとつで、要素自体に遠近感を設定します。
perspective プロパティ(親要素に設定)は、その子要素群に共通の消失点を設けます。3Dカードフリップなどでは親に perspective を設定するアプローチが一般的です。

技術の変遷:昔の常識 vs 今の常識

TRADITION (昔)
位置の変更には position: relative + top / left を使い、アニメーションも JavaScript で left 値を書き換えていた。この方法はレイアウトの再計算(reflow)を毎フレーム引き起こし、カクついた動きの原因になっていた。要素の中央揃えも position: absolute + margin: -50px などの負のマージン計算が必要だった。
MODERN (今)
移動は transform: translate() で完全にレイアウト外の操作。中央揃えは transform: translate(-50%, -50%) または Flexbox / Grid の justify-content / align-items で解決。アニメーションはすべて transform + opacity に集約し、GPU アクセラレーションを最大活用するのが現代のベストプラクティス。

関連する値

値 / 関連 説明
translate(x, y) X・Y方向に移動。% はその要素自身のサイズに対する割合。translate(-50%, -50%) で中央揃えのテクニックに使われる
scale(x, y) 拡大・縮小。1が原寸、2で2倍、0.5で半分。scale(-1) で鏡像反転が可能
rotate(angle) 回転。deg(度)/ rad(ラジアン)/ turn(回転数)で指定。正の値で時計回り
skew(x, y) 傾斜・歪め。X軸・Y軸方向にシアー変換。デザインのアクセントとして使われることが多い
rotateY(angle) Y軸(縦軸)を中心に3D回転。perspectiveと組み合わせてカードフリップ演出を作る
初期値 none
継承 なし
transform-origin 変換の基準点。デフォルトは「50% 50%」(要素中心)。「top left」や「0 0」に変えると変換の起点が変わる

利用例

position:absolute の完全中央揃え

translate(-50%, -50%) を使った古典的かつ確実な中央揃え。要素のサイズが不明な場合でも使える万能パターン。

HTML Structure
<div style="position:relative;width:100%;height:180px;background:#f1f5f9;border-radius:12px;border:2px dashed #cbd5e1"><div style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background:#1a56db;color:white;padding:14px 24px;border-radius:8px;font-weight:700;font-size:14px;white-space:nowrap;font-family:sans-serif">完全中央に配置</div></div>
CSS Style
.container {
  position: relative;
  width: 300px;
  height: 200px;
}

.centered {
  position: absolute;
  top: 50%;
  left: 50%;

  /* 自身のサイズの半分だけ戻す */
  transform: translate(-50%, -50%);
}

3D カードフリップ

rotateY を使ったカードの裏表フリップ。perspective・backface-visibility との組み合わせが肝。

HTML Structure
<style>.card-scene{perspective:800px;width:180px;height:120px;margin:30px auto}.card-3d{width:100%;height:100%;position:relative;transform-style:preserve-3d;transition:transform 0.6s ease;cursor:pointer}.card-scene:hover .card-3d{transform:rotateY(180deg)}.card-front,.card-back{position:absolute;inset:0;backface-visibility:hidden;border-radius:12px;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:14px;font-family:sans-serif}.card-front{background:linear-gradient(135deg,#1a56db,#7c3aed);color:white}.card-back{background:linear-gradient(135deg,#059669,#0891b2);color:white;transform:rotateY(180deg)}</style><div style="padding:20px;background:#f8fafc;border-radius:12px"><div class="card-scene"><div class="card-3d"><div class="card-front">ホバーして</div><div class="card-back">🎉 裏面!</div></div></div><p style="text-align:center;font-size:12px;color:#64748b;margin-top:8px;font-family:sans-serif">カードにホバーするとフリップします</p></div>
CSS Style
.card-scene {
  perspective: 800px; /* 親に遠近感を設定 */
  width: 200px;
  height: 130px;
}

.card-3d {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d; /* 子の3D空間を保持 */
  transition: transform 0.6s ease;
}

.card-scene:hover .card-3d {
  transform: rotateY(180deg);
}

.card-front,
.card-back {
  position: absolute;
  inset: 0;
  backface-visibility: hidden; /* 裏面を隠す */
  border-radius: 12px;
}

.card-back {
  transform: rotateY(180deg); /* 裏面はあらかじめ反転 */
}

よくある誤用・注意点

transform: translateX() で要素を移動しても、その要素が元々占めていたスペースは消えない。これを理解せず「移動したのに隙間が残る」と混乱するケースが多い。また複数transform関数の記述順を無視すると意図しない変形になる。

HTML Structure
CSS (Incorrect)
/* ❌ 誤解されやすい例:translateX しても元のスペースは残る */
.item {
  transform: translateX(200px);
  /* 視覚的には200px右に移動するが、
     他の要素から見たこの要素の「居場所」は変わらない */
}

/* ❌ 記述順による違いを無視した例 */
.box-a {
  /* まず回転してから移動 → 移動方向が回転後の軸に */
  transform: rotate(45deg) translateX(100px);
}
.box-b {
  /* まず移動してから回転 → 結果がまったく異なる */
  transform: translateX(100px) rotate(45deg);
}