Movatterモバイル変換


[0]ホーム

URL:


  1. 開発者向けのウェブ技術
  2. CSS
  3. ガイド
  4. 座標変換

このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docsコミュニティーについてもっと知り、仲間になるにはこちらから。

View in EnglishAlways switch to English

CSS 座標変換

CSS 座標変換 (CSS transforms) は、CSS でスタイル設定された要素を 2 次元または 3 次元空間に座標変換する方法を定義します。

CSS 座標変換の動作

下の枠内のスライダーを使うと、 3D 空間での立方体の平行移動、回転、変倍、歪めの CSS 座標変換のプロパティを変更できます。立方体を 3D 空間内で移動させながら、 3D 位置(0, 0, 0) にあるz:0px とラベル付けされた要素との相互作用に注目してください。

<article>  <fieldset>    <legend>      座標変換の設定      <button aria-label="Reset">↻</button>    </legend>    <section>      <fieldset>        <legend>          <label>            <span>平行移動</span>          </label>          <button                                  aria-label="Reset">            ↻          </button>        </legend>        <div>          <div>            <label>              <span>X</span>              <input                type="range"                min="-100"                max="100"                value="0"                data-default="0"                               aria-labelledby="translateXLabel" />            </label>            <output for="translateXRange"></output>          </div>          <div>            <label>              <span>Y</span>              <input                type="range"                min="-100"                max="100"                value="0"                data-default="0"                               aria-labelledby="translateYLabel" />            </label>            <output for="translateYRange"></output>          </div>          <div>            <label>              <span>Z</span>              <input                type="range"                min="-100"                max="100"                value="0"                data-default="0"                               aria-labelledby="translateZLabel" />            </label>            <output for="translateZRange"></output>          </div>        </div>      </fieldset>      <fieldset>        <legend>          <label>            <span>回転</span>          </label>          <button                                  aria-label="Reset">            ↻          </button>        </legend>        <div>          <div>            <label>              <span>X</span>              <input                type="range"                min="-360"                max="360"                value="0"                data-default="0"                               aria-labelledby="rotateXLabel" />            </label>            <output for="rotateXRange"></output>          </div>          <div>            <label>              <span>Y</span>              <input                type="range"                min="-360"                max="360"                value="0"                data-default="0"                               aria-labelledby="rotateYLabel" />            </label>            <output for="rotateYRange"></output>          </div>          <div>            <label>              <span>Z</span>              <input                type="range"                min="-360"                max="360"                value="0"                data-default="0"                               aria-labelledby="rotateZLabel" />            </label>            <output for="rotateZRange"></output>          </div>        </div>      </fieldset>      <fieldset>        <legend>          <label>            <span>変倍</span>          </label>          <button                                  aria-label="Reset">            ↻          </button>        </legend>        <div>          <div>            <label>              <span>X</span>              <input                type="range"                min="0.1"                max="2.5"                value="1"                data-default="1"                step="0.1"                               aria-labelledby="scaleXLabel" />            </label>            <output for="scaleXRange"></output>          </div>          <div>            <label>              <span>Y</span>              <input                type="range"                min="0.1"                max="2.5"                value="1"                data-default="1"                step="0.1"                               aria-labelledby="scaleYLabel" />            </label>            <output for="scaleYRange"></output>          </div>          <div>            <label>              <span>Z</span>              <input                type="range"                min="0.1"                max="2.5"                value="1"                data-default="1"                step="0.1"                               aria-labelledby="scaleZLabel" />            </label>            <output for="scaleZRange"></output>          </div>        </div>      </fieldset>      <fieldset>        <legend>          <label>            <span>歪め</span>          </label>          <button                                  aria-label="Reset">            ↻          </button>        </legend>        <div>          <div>            <label>              <span>X</span>              <input                type="range"                min="-90"                max="90"                value="0"                data-default="0"                               aria-labelledby="skewXLabel" />            </label>            <output for="skewXRange"></output>          </div>          <div>            <label>              <span>Y</span>              <input                type="range"                min="-90"                max="90"                value="0"                data-default="0"                               aria-labelledby="skewYLabel" />            </label>            <output for="skewYRange"></output>          </div>        </div>      </fieldset>      <fieldset>        <legend>          <label>            <span>コンテナーの視点</span>          </label>          <button                                  aria-label="Reset">            ↻          </button>        </legend>        <div>          <div>            <label>              <span><code>perspective</code></span>              <input                type="range"                min="75"                max="500"                value="200"                data-default="200"                               aria-labelledby="perspectiveLabel" />            </label>            <output for="perspectiveRange"></output>          </div>          <div>            <label>              <span                ><code>perspective-origin</code> X (%)</span              >              <input                type="range"                min="0"                max="100"                value="50"                data-default="50"                               aria-labelledby="perspectiveOriginXLabel" />            </label>            <output                           for="perspectiveOriginXRange"></output>          </div>          <div>            <label>              <span><code>perspective-origin</code> Y (%)</span>              <input                type="range"                min="0"                max="100"                value="50"                data-default="50"                               aria-labelledby="perspectiveOriginYLabel" />            </label>            <output                           for="perspectiveOriginYRange"></output>          </div>        </div>      </fieldset>      <fieldset>        <legend>          <label>            <span>その他のプロパティ</span>          </label>          <button                                  aria-label="Reset">            ↻          </button>        </legend>        <div>          <div>            <label>              <span><code>backface-visibility</code></span>              <input                type="checkbox"                checked                data-default="checked"                />            </label>          </div>        </div>      </fieldset>    </section>  </fieldset>  <section>    <div>      <div>        <div>1</div>        <div>2</div>        <div>3</div>        <div>4</div>        <div>5</div>        <div>6</div>      </div>      <div><code>z:0px</code></div>    </div>    <div></div>  </section></article>
#allTransformFieldset {  border: none;  padding: 0;  margin-bottom: 4px;  accent-color: blue; /* or any color */  font-family:    "Inter", "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans",    "Droid Sans", "Helvetica Neue", sans-serif;}#allTransformFieldset > legend {  margin-bottom: 4px;}fieldset {  margin: 0;}legend {  font-weight: bold;  padding: 0;}#fieldsetSection {  display: flex;  flex-wrap: wrap;  align-items: start;  gap: 8px;}#outputSection {  width: 100%;  min-height: 400px;  background: linear-gradient(skyblue, khaki);  display: flex;  justify-content: center;  align-items: center;  position: relative;  overflow: clip;}#outputContainer {  position: absolute;  width: 100%;  height: 100%;  perspective: 200px;  display: flex;  justify-content: center;  align-items: center;  transform-style: preserve-3d;  pointer-events: none;}#z0 {  width: 50px;  height: 50px;  background: linear-gradient(    to right bottom,    rgb(223 223 223),    rgb(190 190 190)  );  transform: translateZ(0px);  position: absolute;  display: flex;  align-items: center;  justify-content: center;  font-size: 14px;  color: black;  border-radius: 50%;  outline: 1px solid rgb(0 0 0 / 0.35);  pointer-events: all;}#perspectiveDot {  width: 4px;  height: 4px;  border-radius: 50%;  background-color: rgb(240 0 0 / 0.5);  transform: translate3d(-2px, -2px, 0px);  position: absolute;}#cube {  width: 100px;  height: 100px;  transform-style: preserve-3d;  transition: all 0.075s ease-out;  position: absolute;  pointer-events: all;}.face {  display: flex;  align-items: center;  justify-content: center;  width: 100%;  height: 100%;  position: absolute;  backface-visibility: inherit;  font-size: 60px;  color: white;}.front {  background: rgb(90 90 90 / 0.7);  transform: translateZ(50px);}.back {  background: rgb(0 210 0 / 0.7);  transform: rotateY(180deg) translateZ(50px);}.right {  background: rgb(210 0 0 / 0.7);  transform: rotateY(90deg) translateZ(50px);}.left {  background: rgb(0 0 210 / 0.7);  transform: rotateY(-90deg) translateZ(50px);}.top {  background: rgb(210 210 0 / 0.7);  transform: rotateX(90deg) translateZ(50px);}.bottom {  background: rgb(210 0 210 / 0.7);  transform: rotateX(-90deg) translateZ(50px);}.transformFieldset {  margin: 0;}.controlsContainer {  display: flex;  flex-direction: column;  align-items: start;  gap: 4px;}.controlsContainer {  width: 100%;}.controlsContainer > div {  display: flex;  flex-direction: row;  align-items: center;  gap: 4px;}.controlsContainer > div > label {  display: flex;  flex-direction: row;  align-items: center;  gap: 4px;}button {  font-size: 18px;  border-radius: 50%;  border: #cccccc solid 1px;  padding: 0;  width: 26px;  height: 26px;  margin-left: 4px;}input[type="range"] {  width: 172px;}output {  width: 3em;}
allTransformFieldset  .querySelectorAll("input[type='range']")  .forEach((rangeInput) => {    // 範囲入力が変更された際のイベントリスナー    rangeInput.addEventListener("input", (el) => {      updateTransform();    });    // 範囲入力がダブルクリックされた際に、関連する座標変換設定をリセット    rangeInput.addEventListener("dblclick", (el) => {      resetInput(el.target);      updateTransform();    });  });// チェックボックス入力が変更された際のイベントリスナーallTransformFieldset  .querySelectorAll("input[type='checkbox']")  .forEach((checkboxInput) => {    checkboxInput.addEventListener("input", (el) => {      updateTransform();    });  });// 「すべてリセット」ボタンのイベントリスナーresetAllButton.addEventListener("click", () => {  allTransformFieldset.querySelectorAll("input").forEach((input) => {    resetInput(input);  });  updateTransform();});// セクションのリセットボタンのイベントリスナーallTransformFieldset  .querySelectorAll(".resetSectionButton")  .forEach((resetSectionButton) => {    resetSectionButton.addEventListener("click", (el) => {      let allRanges = el.target.parentElement.parentElement.querySelectorAll(        "input[type='range']",      );      allRanges.forEach((range) => {        resetInput(range);      });      let allCheckboxes =        el.target.parentElement.parentElement.querySelectorAll(          "input[type='checkbox']",        );      allCheckboxes.forEach((check) => {        resetInput(check);      });      updateTransform();    });  });function resetInput(inputEl) {  if (!inputEl) {    console.warn(`inputEl \`${inputEl}\` is falsy!`);    console.trace();    return;  }  const defaultValue = inputEl.getAttribute("data-default");  if (inputEl.getAttribute("type") === "checkbox") {    inputEl.checked = defaultValue === "checked";  } else {    inputEl.value = defaultValue || "0";  }}function updateOutputs() {  translateXOutput.value = `${translateXRange.value}px`;  translateYOutput.value = `${translateYRange.value}px`;  translateZOutput.value = `${translateZRange.value}px`;  rotateXOutput.value = `${rotateXRange.value}°`;  rotateYOutput.value = `${rotateYRange.value}°`;  rotateZOutput.value = `${rotateZRange.value}°`;  scaleXOutput.value = `${scaleXRange.value}x`;  scaleYOutput.value = `${scaleYRange.value}x`;  scaleZOutput.value = `${scaleZRange.value}x`;  skewXOutput.value = `${skewXRange.value}°`;  skewYOutput.value = `${skewYRange.value}°`;  perspectiveOutput.value = `${perspectiveRange.value}px`;  perspectiveOriginXOutput.value = `${perspectiveOriginXRange.value}%`;  perspectiveOriginYOutput.value = `${perspectiveOriginYRange.value}%`;}function updateTransform() {  updateOutputs();  cube.style.transform = `translate3d(${translateXRange.value}px,                ${translateYRange.value}px,                ${translateZRange.value}px)                rotateX(${rotateXRange.value}deg)                rotateY(${rotateYRange.value}deg)                rotateZ(${rotateZRange.value}deg)                scale3d(${scaleXRange.value},                ${scaleYRange.value},                ${scaleZRange.value})                skewX(${skewXRange.value}deg)                skewY(${skewYRange.value}deg)`;  cube.style.backfaceVisibility = `${backfaceVisibilityCheckbox.checked ? "visible" : "hidden"}`;  outputContainer.style.perspective = `${perspectiveRange.value}px`;  outputContainer.style.perspectiveOrigin = `${perspectiveOriginXRange.value}% ${perspectiveOriginYRange.value}%`;  perspectiveDot.style.top = `${perspectiveOriginYRange.value}%`;  perspectiveDot.style.left = `${perspectiveOriginXRange.value}%`;}updateTransform();

また、perspective スライダーを使って、立方体のコンテナーのperspective プロパティを変更できます。これはあなたとz=0 平面の間の距離を決定します。

perspective-origin スライダーは、ビューの消点を決定するために、閲覧者が3D空間のどこを見ているかを決定します。この消点は小さな赤い点で示されます。これらのスライダーを変更することで、立方体自体を動かすことなく、頭を上下左右に動かして立方体のさまざまな部分を見ることができると想像してください。

backface-visibility チェックボックスは、立方体の裏面をvisible (表示)に設定するか、hidden (非表示)に設定するかを決定します。

上の例の立方体は 6 つの<div> 要素で構成されており、すべて CSS でスタイル設定されて立方体の面を構成しています。立方体は 2D や 3D のキャンバスコンテキストを使用して描画されていないので、他の DOM 要素を検査するのと同じように、ブラウザーの開発者ツールで立方体の面を検査することができます。ブラウザー開発者ツールの要素ピッカーを使用して、立方体の位置と回転を変換しながら、立方体のさまざまな面を調べてみてください。

メモ:3D 回転を含む座標変換を適用する場合、順序はが座標変換結果に影響します。上の例では、座標変換は平行移動、変倍、回転、歪めを行います。回転は X → Y → Z の順に適用されます。

リファレンス

プロパティ

関数

データ型

ガイド

CSS 座標変換の使用

CSS でスタイル付けされた要素をどのように座標変換するかについての手順を追ったチュートリアルです。

座標系

CSS オブジェクトモデルでピクセル位置を定義する方法を説明します。

パフォーマンスの基礎: CSS 座標変換の使用

ウェブパフォーマンスの基礎について、 CSS 座標変換がどのようにパフォーマンスを向上させることができるかを含め、概説します。

ウェブの行列演算

オブジェクトの座標変換を行列で表す方法を説明しています。

関連する概念

仕様書

Specification
CSS Transforms Module Level 1
CSS Transforms Module Level 2

関連情報

Help improve MDN

Learn how to contribute

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2026 Movatter.jp