CSS
CSS3
transform

【CSS3】Transform(変形)関連のまとめ

はじめに

この記事は、HTMLとCSSの基礎知識がある方向けの内容です。
CSS3から要素の変形が指定できる、transform(トランスフォーム)プロパティが追加されました。
transformプロパティを使うことで、要素に対して移動、回転、伸縮、傾斜の変形を加えることができます。
ボタンにマウスカーソルを乗せたときに、移動したり、大きさを変えたりするのに使われるプロパティです。
jQueryやJavaScriptを使って似たようなことができますが、CSSを使う方がヌルヌル動きます。

transform(変形)には、2D(XY方向)と3D(XYZ方向)があり、3D表示するには複数のプロパティを指定する必要があります。
解説の都合上、プロパティは順番に説明しているため、記事の途中で3D表示を試しても意図した3D表示がされません。
検証する場合は、一読して全てのプロパティを確認してから試してみてください。
また、一部のプロパティは、GoogleChromeなどのモダンブラウザしか対応しておりません。
最後にブラウザの対応状況を記載しておりますので、確認してください。
説明内でベンダープレフィックスの記述はしておりません。
検証して動作しないときは、ベンダープレフィックスの要否を確認してください。

transform プロパティは、よく transition (トランジション)プロパティ や @keyframes と一緒に使うことがあります。
transition プロパティとは変化するまでの時間を設定するプロパティです。
この transition についてもまとめたので、詳しく知りたい方は下記をご覧ください。

@keyframesanimation についてもまとめたので、詳しく知りたい方は下記をご覧ください。

誤りがあれば、ご指摘頂けると嬉しいです((_ _ (´ω` )ペコ

transformプロパティについて

transform(トランスフォーム)は、直訳すると変形という意味です。
変形には移動、回転、伸縮、傾斜の4つがあります。
transformプロパティの値に関数を指定することで、移動、回転、伸縮、傾斜の設定ができます。
移動、回転、伸縮は、3D(XYZ方向)による指定ができます。
transformプロパティの値に指定できる関数は下記になります。

transformプロパティの値に指定できる関数

No 関数 読み方 変形効果 2D(XY方向) 3D(XYZ方向)
01 translate トランスレイト 移動
02 rotate ローテート 回転
03 scale スケール 伸縮
04 skew スキュー 傾斜

上述している通り、transformプロパティの値に関数を指定することで、変形の設定ができます。
移動や回転など複数指定するときは、記述の仕方に注意する必要があります。
最初にtransformの記述の仕方について確認した後に各関数について見ていきましょう。

記述の仕方について

transformはプロパティですので、複数記述すると最後のtransformプロパティのみ反映されます。
例えば、移動と回転を指定するときは、transformプロパティを複数記述せずに、値に続けて記述してください。
値に複数記述するときは、半角スペースを空けて続けて記述してください。

正しい記述

セレクタ名 {
    transform:translateX(20px) translateY(20px) rotate(40deg);
}

誤った記述

セレクタ名 {
    transform:translateX(20px);
    transform:translateY(20px);
    transform:rotate(40deg);
}

同じプロパティを複数記述したときは、上書きされるため、最後に記載した rotate(40deg) のみ反映されます。

また、値に記述する順番も重要で、記述順に変形します。

例えば、値に「移動・回転・伸縮・傾斜」の順番に指定したときと、逆に「傾斜・伸縮・回転・移動」の順番で指定したときは実行結果が異なる場合があります。
意図した結果にならないときは、順番も確認してください。

No.01 translate関連(移動)

translateで、移動の指定ができます。
2D(XY方向)または3D(XYZ方向)の指定が可能です。
translate()関数でX軸とY軸の移動をまとめて指定できます。
translateX()関数、translateY()関数、translateZ()関数を使って個別に移動距離を指定することもできます。
それぞれを続けて記述することで2D(XY方向)または3D(XYZ方向)の指定が可能ですが、3D(XYZ方向)をまとめて指定できるtranslate3d()関数があります。
単位はpxで指定します。

translate()関数の記述

セレクタ名 {
    transform:translate(X軸方向の移動距離,Y軸方向の移動距離);
}

CodePen の結果は、カーソルをマウスオーバーすると動作します。

See the Pen bmZpWK by 7968 (@b7968) on CodePen.

translateX()関数の記述

セレクタ名 {
    transform:translateX(X軸方向の移動距離);
}

See the Pen Redarp by 7968 (@b7968) on CodePen.

translateY()関数の記述

セレクタ名 {
    transform:translateY(Y軸方向の移動距離);
}

See the Pen pxYygQ by 7968 (@b7968) on CodePen.

translateZ()関数の記述

セレクタ名 {
    transform:translateZ(Z軸方向の移動距離);
}

See the Pen aRMNNb by 7968 (@b7968) on CodePen.

translate3d()関数の記述

セレクタ名 {
    transform:translate3d(X軸方向の移動距離,Y軸方向の移動距離,Z軸方向の移動距離);
}

translateとpositionの違いと描画速度について

X軸とY軸の移動だけなら、positionプロパティを使っても同じことが可能です。
translateを使う場合とpositionプロパティを使う場合では、描画するパフォーマンスが異なります。
基本的にtranslateを使う方がヌルヌル動きます。
この描画速度に関しては、GPUも関係してきます。
私自身全然詳しくないので、ここではざっくり説明します。
画像処理をするGPUという機器があります。
アニメーションをするときにCPUではなく、画像処理が得意なGPUに任せる方が効率的です。
transformプロパティにtranslateの3D関連の値を指定するとブラウザはGPUを利用して描画します。
そのため、translateの3D関連の値を指定する方が描画速度が速くなります。
例えば、headerにtranslateの3D関連の値を指定した場合、そのページ全てがGPUで処理するわけはなく、値が指定されているheaderのみGPUで処理するみたいです。
描画速度を速くするために、関係のない箇所にtranslateの3D関連の値を指定するという方法はしない方が良いみたいです。
GPUを使いすぎると逆にパフォーマンスが低下することがあるみたいですので、本当に必要な箇所のみ使うことをお勧めします。
GPUと描画速度に関しては、下記の記事を見ていただくとわかりやすいと思います。

GoogleChromeのデベロッパーツールを使うことで、GPUで処理されているところを確認できます。
デベロッパーツールの使い方は下記がわかりやすいですので、気になる方はご一読ください。

No.02 rotate関連(回転)

rotate()関数で、回転の指定ができます。
rotate()関数は、要素の回転を指定します。
rotateX()関数、rotateY()関数、rotateZ()関数を使ってそれぞれの方向に対して回転を指定することもできます。
それぞれを続けて記述することで2D(XY方向)または3D(XYZ方向)の指定が可能です。
回転軸を3D(XYZ方向)で指定し、回転角度を指定できるrotate3d()関数があります。

値には、回転角度を指定します。
回転させる角度は、degで表します。
deg は degree(ディグリー)の略で、円周を360分とした角度を表す単位です。
例えば、90度回転させたいときは90degと指定します。
正数だと時計回りで回転し、負数だと反時計回りに回転します。

rotate()関数の記述

セレクタ名 {
    transform:rotate(回転角度);
}

See the Pen GYeZZE by 7968 (@b7968) on CodePen.

rotateX()関数の記述

セレクタ名 {
    transform:rotateX(X軸の回転角度);
}

See the Pen yRwOOG by 7968 (@b7968) on CodePen.

rotateY()関数の記述

セレクタ名 {
    transform:rotateY(Y軸の回転角度);
}

See the Pen rqReeE by 7968 (@b7968) on CodePen.

rotateZ()関数の記述

セレクタ名 {
    transform:rotateZ(Z軸の回転角度);
}

See the Pen oaVxLL by 7968 (@b7968) on CodePen.

rotate3d()で記述

rotate3d()関数を使うことで、回転軸をXYZ方向で指定し、回転を指定できます。
rotate3d()関数は、3つの数値(X,Y,Zの順)で回転軸を指定し、最後の回転角度で指定した角度に回転します。

セレクタ名 {
    transform:rotate3d(数値,数値,数値,回転角度);
}

rotate3d()関数は、どのように回転軸を決めているのか理解できませんでした。
参考サイトを記載しますので、詳しく知りたい方はご覧ください。
W3C - CSS Transforms Module Level 1」に記載されている内容が最新の仕様です。
W3Cのサイトを確認するのがベストですが、英語のため他の参考サイトも記載しておきます。

No.03 scale関連(伸縮)

scale()関数で、伸縮の指定ができます。
2D(XY方向)または3D(XYZ方向)の指定が可能です。
scale()関数でX軸とY軸の伸縮率をまとめて指定できます。
scaleX()関数、scaleY()関数、scaleZ()関数を使って個別に伸縮率を指定することもできます。
それぞれを続けて記述することで2D(XY方向)または3D(XYZ方向)の指定が可能ですが、3D(XYZ方向)をまとめて指定できるscale3d()関数があります。

値は数値のみで指定します。
数値は、1を基準に伸縮する比率を整数または少数で指定します。

scale()関数の記述

セレクタ名 {
    transform:scale(数値,数値);
}

See the Pen PyLNzO by 7968 (@b7968) on CodePen.

scaleX()関数の記述

セレクタ名 {
    transform:scaleX(数値);
}

See the Pen qJvZab by 7968 (@b7968) on CodePen.

scaleY()関数の記述

セレクタ名 {
    transform:scaleY(数値);
}

See the Pen OBqNRz by 7968 (@b7968) on CodePen.

scaleZ()関数の記述

セレクタ名 {
    transform:scaleZ(数値);
}

Z軸方向の伸縮は少し分かり難いです。
例えば何の変形もしていない、width:100px × height:100px の面に対してscaleZ()関数を指定しても面に奥行きが出るわけではありません。
面に対して回転などの変形をかけ、Z軸方向にも面が存在すときに面がZ軸方向に伸縮します。

実際に結果を見ると理解しやすいかと思います。

See the Pen XxGdjv by 7968 (@b7968) on CodePen.

マウスオーバーするとZ軸方向に伸縮します。
Z軸方向の伸縮がわかりやすいようにY軸方向に回転をかけています。
左側はZ軸だけの伸縮で、右側はXYZの全ての方向に伸縮の設定をしております。
紺色の面は何の変化も加えていない基の形の面になります。
わかりやすくするために、まだ説明していないプロパティを設定しております。
どのようなコードを記述しているか理解しなくても大丈夫ですので、ここではZ軸方向の伸縮がどのような感じか確認してください。

scale3d()関数の記述

セレクタ名 {
    transform:scale3d(数値,数値,数値);
}

See the Pen VERamm by 7968 (@b7968) on CodePen.

No.04 skew関連(傾斜)

skew()関数で、傾斜の指定ができます。
2D(XY方向)のみ指定できます。
skew()関数でX軸とY軸の傾斜角度をまとめて指定できます。
skewX()関数、skewY()関数を使って個別に傾斜角度を指定することもできます。

傾斜角度の単位はdegで指定します。

skew()関数の記述

セレクタ名 {
    transform:skew(X軸の傾斜角度,Y軸の傾斜角度);
}

See the Pen OBqNbz by 7968 (@b7968) on CodePen.

skewX()関数の記述

セレクタ名 {
    transform:skewX(X軸の傾斜角度);
}

See the Pen ePXZBw by 7968 (@b7968) on CodePen.

skewY()関数の記述

セレクタ名 {
    transform:skewY(Y軸の傾斜角度);
}

See the Pen wYOGgj by 7968 (@b7968) on CodePen.

skew関連は組み合わせると結果が異なるので注意

普通に考えると skew(30deg)skewX(30deg) skewY(30deg)skewY(30deg) skewX(30deg) は同じ結果になると思いますが、実際にはそれぞれ異なる結果になります。

See the Pen EdMKWa by 7968 (@b7968) on CodePen.

計算方法が異なるため、同じ結果になりません。
指定するときは注意してください。

skew()関数の仕様について

上記のように実行結果が異なるため、skew()関数の仕様については検討中のようです。

2015年9月現在、「transform - CSS | MDN」のWebサイトには下記のようにskew()関数が取り除かれたとの記述があります。

注記: skew() 関数は初期の草案に存在しました。この関数は取り除かれましたが、一部の実装にはまだ残されています。これは使わないでください。

同じ効果を得るために、skew() に1 つの引数を与えて使っていたのなら skewX() を、汎用的には matrix(1, tan(ay), tan(ax), 1, 0, 0) を使ってください。ここで tan() は CSS 関数ではなく、自分で計算する必要がある点に注意してください。

2015年9月現在、W3Cの「CSS Transforms Module Level 1」には、下記のように従来のコンテンツとの互換性のため、skew()関数をサポートする必要があると記述されています。

Note that the behavior of skew() is different from multiplying skewX() with skewY(). Implementations must support this function for compatibility with legacy content.

今後、skew()関数は仕様が変わる可能性もありますが、現時点では互換性のためにskew()関数を残す方向のようです。

変形する基点を設定するプロパティ

今まで変形について見てきましたが、変形する基点を設定したいときがあります。
変形する基点を設定するには、transform-originプロパティを使って設定します。

transform-originプロパティについて

transform-origin(トランスフォーム・オリジン)プロパティは、要素の基点を指定するプロパティです。
初期値は2Dの場合は50% 50%で、3Dの場合は50% 50% 0で要素の中心になります。
transform-originプロパティを指定しないと、初期値が基点になります。

transform-originプロパティの値には基点となるX軸とY軸の位置を指定します。
値には、単位付き数値またはワード(left center right top center bottom)で指定してください。

セレクタ名 {
    transform-origin:X軸の位置 Y軸の位置;
}

2Dまたは3Dの表示を設定するプロパティ

今まで3Dと言ってきましたが、デフォルトでは3D表示されません。
3Dで表示するには、transform-styleプロパティで3D表示に設定する必要があります。

transform-styleプロパティについて

transform-styleプロパティで子要素を2Dで表示するか、3Dで表示するかを指定できます。
transform-styleプロパティの値にflatpreserve-3dを指定できます。
初期値はflatのため、設定しないと2D表示になります。
preserve-3dを指定することで、要素の基点を中心に3D表示されます。

読み方 用途
flat(初期値) フラット 子要素を2Dで表示
preserve-3d プレサーブ・スリーディ 子要素を3Dで表示

下記のように記述することで、子要素は3Dで表示されるようになります。
3D表示させたい要素の親要素にtransform-styleプロパティを指定してください。

セレクタ名 {
    transform-style:preserve-3d;
}
このプロパティは継承されないため、すべての子孫要素でセットする必要があります。

divなどを入れ子にして幾つかの要素を3D表示させるときは、3D表示させたい全ての親要素に設定してください。
このプロパティを設定し忘れると、Firefoxでは3D表示がされず、GoogleChromeでは3D表示されるが透過で表示される意味不明な状況になるので注意してください。

3D表示になると言われても、実行結果がないと理解できないかと思います。
この後に遠近感を設定するプロパティが出てきます。
紛らわしいので、後から2つの実行結果を見比べながらそれぞれの違いを確認します。
現時点では、3D表示するプロパティがあるということを覚えておいてください。

遠近感を設定するプロパティ

先ほどは、子要素を3Dで表示するかの設定でした。
3Dの表示に設定しても、遠近感の設定はされません。
遠近感を設定すると、近く(閲覧者側)に配置されている物体が大きく表示され、遠くに配置されている物体は小さく表示されます。
遠近感を設定するプロパティは2つあります。
2つある理由は、プロパティを設定した要素のみに遠近感を設定するのか、プロパティを設定した要素の子要素のみに遠近感を設定するのかの違いがあります。
必要に応じて使い分けてください。

perspectiveプロパティについて

perspective(パースペクティブ)プロパティは、要素に対して遠近感を設定できます。
perspectiveプロパティは、指定した要素には遠近感は適用されず、子要素(transformプロパティで変化を指定している要素)のみに適用されます。
子要素に適用されるので、遠近感を設定要素の親要素にperspectiveプロパティを指定してください。
値は整数で単位はpxで指定してください。

セレクタ名 {
    perspective:px;
}

perspective-originプロパティについて

perspective-origin(パースペクティブ・オリジン)プロパティは、perspectiveプロパティの視点(子要素を俯瞰する視点)を指定するプロパティです。
初期値はperspectiveプロパティを設定した要素の中心に設定されています。
perspective-originプロパティを指定しないと、初期値が基点になります。

perspective-originプロパティの値には基点となるX軸とY軸の位置を指定します。
値には、単位付き数値またはワード(left center right top center bottom)で指定してください。

セレクタ名 {
    perspective-origin:X軸の位置 Y軸の位置;
}

transform:perspective()について

transformプロパティにperspective()関数を指定することで遠近感の設定ができます。
効果はperspectiveプロパティと同じですが、適用される範囲が異なります。
perspective()関数は指定した要素しか適用されません。
値は整数で単位はpxで指定してください。

セレクタ名 {
    transform:perspective(px);
}

3D表示と遠近の設定を確認

3D表示と遠近の設定について図にまとめました。
それぞれ設定すると、どのように表示されるのか図を見ながら確認しましょう。

css3-transform-3d.jpg.png

最初にCSSの設定を確認します。
紺色の面は変形をかけていないので、変形前の形です。
橙色の面にはrotateY(40deg)を指定しています。
緑色の面にはrotateY(-40deg)を指定しています。

3D表示と遠近の設定をすることで、それぞれどのような表示になるのか確認してみましょう。

No.01の表示について

遠近の設定も3Dの設定もしていません。
橙色の面にはY軸を基点した回転がかかっているため、面の左側は手前に面の右側は奥にあります。
ただ、遠近の設定をしていないため、手間にあっても奥にあっても同じ大きさで表示されています。
その上、3Dの設定もしていないため、上面図を見ると分かりますが、2Dで表示されています。

No.02の表示について

遠近の設定のみしております。
橙色の面の左側は手前にあるため、大きく表示され、奥にある右側の面は小さく表示されています。
こちらも3Dの設定をしていないため、上面図を見ると分かりますが、2Dで表示されています。

No.03の表示について

3Dの表示設定のみしております。
そのため、基点を中心に面がZ軸方向にも表示されています。
上面図を見るとわかりますが、橙色の面は回転がかかっており、左側の面が手間に右側の面が奥に表示されています。
緑の色の面は逆の回転がかかっておりますので、橙色の面とは対称的な表示になります。
ただ、遠近の設定をしていないため、橙色と緑色の面は同じ大きさで表示されています。

No.04の表示について

遠近の設定と3Dの表示設定をしております。
遠近の設定をしているため、回転がかかっている橙色の面の左側は大きく表示され、右側は小さく表示されます。
また、3D表示もしているため、基点を中心に面がZ軸方向にも表示されています。
橙色の面の右側は紺色の面より奥にありますので、正面から見ると途中で切れたように表示されます。

transform関連チートシート

transform関連のプロパティや関数は、複数あるためチートシートを作成しました。

css3-transform-sheet.jpg

ブラウザの対応状況

最後にブラウザの対応状況を確認しましょう。
私は、GoogleChromeで動作の確認をしております。
上記のプロパティに関しては、対応状況は各自で調べてください。
transform3D関連のプロパティは、主要ブラウザであるIE10・IE11でも部分サポートしかしておりませんので、実務で使うときは注意してください。

プロパティ名 IE8 IE9 IE10 IE11
transform 2D ×
transform 3D × ×
transform-origin × × ×
perspective × ×

2015年9月現在、transform-styleプロパティとperspective-originプロパティは「Can I use」に登録されていません。
私の環境(Windows7)で検証した結果は下記になります。
検証結果に誤りがある場合もございますので、念のため各自で確認してください。

プロパティ名 IE8 IE9 IE10 IE11
transform-style × × × ×
perspective-origin × ×

最後に

CSSのTransformに関する仕様は、W3Cの「CSS Transforms Module Level 1」に記載があります。
2015年9月現在、草案段階であり、仕様が変更になる可能性があります。
最新の情報は、上記のW3Cの仕様書(英語版)を確認してください。