CSSをある程度使えるようになった人が覚えたいtransformプロパティの使い方

##はじめに
CSSアニメーションを使えるようになろうシリーズ
 - [CSSをある程度使えるようになった人が覚えたいtransitionプロパティの使い方](https://qiita.com/fumu238/items/6da8cc5c10659018d057)

こちらの記事の続きのようなものです。

`transition`を使えるようになったら、次は`transform`ですかね。
こちらはよりアニメーション感が出るのでぜひ覚えたいところです（わたしが）。

##目次
[記事の対象](#記事の対象)
[transformとは](#transformとは)
[transitonプロパティとの違い](#transitonプロパティとの違い)
[transformプロパティの使い方](#transformプロパティの使い方)
[transform関数の種類](#transform関数の種類)
[1.translate()](#1translate)
[2.scale()](#2scale)
[3.rotate()](#3rotate)
[4.skew()](#4skew)
[3Dで表示したい時のおまじない](#3Dで表示したい時のおまじない)


##記事の対象
 - CSSでアニメーションさせたい
 - trnsitionは覚えたけど他には？
 - transformって何ができるの？

という方（つまり自分）に向けた記事です。
基礎的な内容になっており、且つ自分の中でのまとめのような記事なので、説明不足な点など多々あるかと思いますがご了承ください。

##transformとは
transformは、CSSアニメーションのひとつであり、動きに変化をつけるためのプロパティです。
具体的には何かアクションが行われたときやプロパティが変化するときなど、例えば

 - マウスカーソルをボタンに乗せたとき
 - クリックしたとき
 
など
つまり、疑似クラスである`:hover`などと組み合わせて使うことが多いでしょう。
transform特有の変化させるプロパティを用いて、例えば図形の形などを変化させることができます。

また`animation`や`transition`という時間をかけて変化するようなプロパティともよく一緒に使われます。

##transitonプロパティとの違い
 - **transition**

**変化にかける時間やその変化速度の度合いを指定することができますが、trnsition自体には形を変化させるプロパティは用意されていません**。
基本的には疑似クラス（hover）や`animation`、`transform`と一緒に使用することで、元のCSSの状態から、プロパティを変更または追加することで変更後のCSSに変化させます。

 - **transform**

**transform自体にCSSを変化させるプロパティが用意されています**。
`transform`は、主にオブジェクトを**移動、回転、拡大縮小**することができます。
さらに**縦(Y軸)と横(X軸)の2D変化だけでなく、3D(Z軸)の変化**を加えることができます。

基本的にはマウスをホバーするなど、元のCSSから変更させる必要はありますが、`transition`と組み合わせることでよりヌルヌルとした動きにすることができます。




##transformプロパティの使い方
`transform`は、基本的には変化後のほうにプロパティを追加します。

```css:CSS

セレクタ{
  background-color: black;
  color: white;
  transition: all 0.3s;
  /** こっちじゃない **/
}
セレクタ:hover {
  background-color: white; 
  color: black;
  transform: translateX(50px);/** こっちに記述 **/
}
```
`transition`は、変化の仕方(時間)を指定するだけなので**元のセレクタに指定する**必要がありましたが
`transform`の場合は変化が起こるプロパティですので、変化させたいセレクタの、**ホバーした状態のほうに指定**します。
元のセレクタにも指定できますが、ホバーをせずとも最初から変化している形になります。

見た方が早いですね。
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="fumu238" data-slug-hash="jOPZgKg" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="transform説明">
  <span>See the Pen <a href="https://codepen.io/fumu238/pen/jOPZgKg">
  transform説明</a> by fumu (<a href="https://codepen.io/fumu238">@fumu238</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

上の「ホバー」と書かれた箱は、ホバーしたほうのセレクタにtranslateを指定してあり、30px右に移動します。
下の「30px右」は、箱そのもののセレクタにtranslateを指定してあるので、最初から30px右の状態になっています。

##transform関数の種類
**transform**にはプロパティ自体の種類はなく、**関数**を使用することで様々な変化を加えることができるようになります。

```css:CSS
セレクタ {
  transform:関数();
}
```
関数なので、()には引数（数値など）を入れます。
基本的には**横(X軸)、縦(Y軸)、3D(Z軸)**それぞれを指定します。

|No|関数名|説明|
|:-:|:-:|:---|
|1|translate()|要素を移動させる。|
|2|scale()|要素を伸縮させる。|
|3|rotate()|要素を回転させる。|
|4|skew()|要素に傾斜をつける。|
|#|matrix()|6つの値を指定し、変形させます。（難しいので今回は割愛します）|

```css:CSS
セレクタ {
  transform: translate(40px,40px) scale(1.2) rotate(90deg,90deg);
}
```

関数の種類は、厳密には上記の他に**X軸だけを指定するものやY軸だけを指定するもの**などがあるので、それぞれで詳しく見ていきます。

##1.translate()
**トランスレイト**は要素を移動させる関数です。
基本的に値はpxで指定します。

|No|関数名|引数の数|説明|
|:-:|:-:|:-:|:---|
|1|translate()|2|第一引数にX軸方向の距離、第二引数にY軸方向の距離を指定。|
|2|translateX()|1|X軸方向の距離を指定。|
|3|translateY()|1|Y軸方向の距離を指定。|
|4|translateZ()|1|Z軸方向の距離を指定。|
|5|translate3d()|3|第一引数にX軸方向、第二引数にY軸方向、第三引数にZ軸方向の距離を指定。|

###translate（**X軸**, **Y軸**）

```css:CSS
セレクタ {
  transform: translate(40px,40px) ;
}
```
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="fumu238" data-slug-hash="xxGzWmm" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="transform()">
  <span>See the Pen <a href="https://codepen.io/fumu238/pen/xxGzWmm">
  transform()</a> by fumu (<a href="https://codepen.io/fumu238">@fumu238</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

X軸(横)方向に40px、Y軸方向に40px移動します。

**translateX**と**translateY**は特に難しいことはないので割愛します。

###translateZ（**Z軸**）

```css:CSS
セレクタ {
  transform: translateZ(100px) ;
}
```
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="fumu238" data-slug-hash="OJVoboE" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="translateX">
  <span>See the Pen <a href="https://codepen.io/fumu238/pen/OJVoboE">
  translateX</a> by fumu (<a href="https://codepen.io/fumu238">@fumu238</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


3Dの動きなので、近づいてくるような動きをしているのがわかると思います。

###translate3d（**X軸**, **Y軸**, **Z軸**）

```css:CSS
セレクタ {
  transform: translate3d(50px, 50px, 100px) ;
}
```

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="fumu238" data-slug-hash="BaNOQvO" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="BaNOQvO">
  <span>See the Pen <a href="https://codepen.io/fumu238/pen/BaNOQvO">
  BaNOQvO</a> by fumu (<a href="https://codepen.io/fumu238">@fumu238</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

右斜め下方向に移動しつつ、眼前に近づいてくるような動きになります。
ちなみに、値は**マイナス(-)**も指定することができ、下のBOX2のほうは３方向にマイナスを設定しているので、BOX1とは対称的な動きになります。Z方向だと画面奥に移動するので、小さくなっていくのがわかります。


##2.scale()
**スケール**は要素を伸縮させる関数です。
値は、1を基準とした比率の数字を指定します。

|No|関数名|引数の数|説明|
|:-:|:-:|:-:|:---|
|1|scale()|2|第一引数にX軸方向の距離、第二引数にY軸方向の倍率を指定。|
|2|scaleX()|1|X軸方向の倍率を指定。|
|3|scaleY()|1|Y軸方向の倍率を指定。|
|4|scaleZ()|1|Z軸方向の倍率を指定。|
|5|scale3d()|3|第一引数にX軸方向、第二引数にY軸方向、第三引数にZ軸方向の倍率を指定。|

###scale（**X軸**, **Y軸**）

```css:CSS
セレクタ {
  transform: scale(1.2, 0.8) ;
}
```
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="fumu238" data-slug-hash="PoqdKPw" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="scale()">
  <span>See the Pen <a href="https://codepen.io/fumu238/pen/PoqdKPw">
  scale()</a> by fumu (<a href="https://codepen.io/fumu238">@fumu238</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

X軸方向に1.2、Y軸方向に0.8を指定しているので、横に1.2倍、縦に0.8倍の大きさに変化します。

スケールの3Dの変化はかなりややこしくまだ理解に乏しいので、ここでは省きます。

##3.rotate()
ローテートは、要素を回転させることができます。
値の単位は**deg**(degree:角度)を使います。何度回転させるかを指定するということですね。

|No|関数名|引数の数|説明|
|:-:|:-:|:-:|:---|
|1|rotate()|1|角度を指定。(rotateZと同じ扱い？)|
|2|rotateX()|1|X軸方向の角度を指定。|
|3|rotateY()|1|Y軸方向の角度を指定。|
|4|rotateZ()|1|Z軸方向の角度を指定。|
|5|rotate3d()|４|第一、二、三引数で回転軸を指定し、第四引数で角度を指定。|

###rotate(Z軸)

```css:CSS
セレクタ {
  transform: rotate(90deg) ;
}
```
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="fumu238" data-slug-hash="RwPYEVb" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="RwPYEVb">
  <span>See the Pen <a href="https://codepen.io/fumu238/pen/RwPYEVb">
  RwPYEVb</a> by fumu (<a href="https://codepen.io/fumu238">@fumu238</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
rotateで角度を指定すると、オブジェクトを上から見下ろした形で回転します。rotateZと同じ扱いかと思われます。
ちなみにマイナスも指定することができ、その場合は**反時計回り**になります。

###rotateX(X軸)

```css:CSS
セレクタ {
  transform: rotateX(180deg) ;
}
```
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="fumu238" data-slug-hash="oNXPJoO" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="rotateX()">
  <span>See the Pen <a href="https://codepen.io/fumu238/pen/oNXPJoO">
  rotateX()</a> by fumu (<a href="https://codepen.io/fumu238">@fumu238</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

rotateXは、X軸を軸に回転するので、オブジェクトは縦回転することになります。

###rotateY(Y軸)

```css:CSS
セレクタ {
  transform: rotateY(-180deg) ;
}
```

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="fumu238" data-slug-hash="JjdawBz" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="rotateY()">
  <span>See the Pen <a href="https://codepen.io/fumu238/pen/JjdawBz">
  rotateY()</a> by fumu (<a href="https://codepen.io/fumu238">@fumu238</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

rotateY()はY軸が軸なので、横回転です。
マイナスで指定しているので、Y軸方向のマイナス、つまり左に向かって回転します。

ちなみに例ではどちらも同じ値を指定(-180deg)していますが、**回転の基準となる位置が違っている**ので、違った挙動をとっています。
これは``transform-origin``というプロパティを指定することで、物体の変化の基準位置を決めることができるようになります。詳しい説明は割愛します。

##4.skew()
**スキュー**は、オブジェクトに傾斜をつけることができます。
平行四辺形をイメージするとわかりやすいですかね。

こちらも単位はrotateと同じく**deg**を使用します。

|No|関数名|引数の数|説明|
|:-:|:-:|:-:|:---|
|1|skew()|2|第一引数にX軸方向の距離、第二引数にY軸方向の角度を指定。|
|2|skewX()|1|X軸方向の角度を指定。|
|3|skewY()|1|Y軸方向の角度を指定。|


###skewX(X軸)
```css:CSS
セレクタ {
  transform: skewX(20deg) ;
}
```

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="fumu238" data-slug-hash="MWwqZxX" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="skewX()">
  <span>See the Pen <a href="https://codepen.io/fumu238/pen/MWwqZxX">
  skewX()</a> by fumu (<a href="https://codepen.io/fumu238">@fumu238</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

X軸方向、つまり横に伸びるように傾斜がつき、平行四辺形の形になります。


###skew(X軸, Y軸)

```css:CSS
セレクタ {
  transform: skew(20deg, 20deg) ;
}
```

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="fumu238" data-slug-hash="ZEGMVVj" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="skew()">
  <span>See the Pen <a href="https://codepen.io/fumu238/pen/ZEGMVVj">
  skew()</a> by fumu (<a href="https://codepen.io/fumu238">@fumu238</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

X軸とY軸をいっぺんに指定すると、単純にそれぞれひとつだけ指定した場合とではかなり結果が異なります。

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="fumu238" data-slug-hash="rNVZoEQ" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="skew違い">
  <span>See the Pen <a href="https://codepen.io/fumu238/pen/rNVZoEQ">
  skew違い</a> by fumu (<a href="https://codepen.io/fumu238">@fumu238</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
こちらの例では
box1はskewX(30deg) skewY(30deg);
box2はskewY(30deg) skewX(30deg);
box3はskew(30deg, 30deg);

という、どれも同じような指定をしてますが、全て見た目の結果は異なります。
正直skewの使い所はあまり思い浮かばないので、もし使いどきがきたら「あーそういえばそうだったな」と思い出せればいいかなと思います。

##3Dで表示したい時のおまじない

transformには3D(Z軸)方向の変化を加えることができる関数がありますが、ただそれを指定するだけでは、ブラウザによってはうまく動いてくれません。

3Dでの変化を加える時は、**変化を加えたい要素の親要素**にあるプロパティを指定してあげる必要があります。

```css:CSS
セレクタ {
  transform-style: preserve-3d;
}
```
これです。
transform-styleに指定できる値は``flat``か``preserve-3d``のどちらか。子要素を２Dで見るか、3Dで見るかという指定をします。
おまじないなので、細かいことは考えずに3Dにするときは親要素につけてあげましょう。

###perspective

また、``transform-style``と同じく**親要素**のほうに``perspective``を指定してあげることで、子要素を見る視点の高さをpxで指定することができます。

```css:CSS
セレクタ {
  perspective: 1000px;
}
```
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="fumu238" data-slug-hash="XWbPONw" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="XWbPONw">
  <span>See the Pen <a href="https://codepen.io/fumu238/pen/XWbPONw">
  XWbPONw</a> by fumu (<a href="https://codepen.io/fumu238">@fumu238</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

上のbox1は``perspective:1000px``を指定してあり、視点が高い状態です。
下のbox2は``perspective:100px``を指定してあり、オブジェクトの大きさに対してかなり目線が低い状態、つまり近い状態なので、回転する動きも大きく見えます。

##おわりに
まだまだtransformに関するプロパティの種類だったり、細かい指定の仕方や考え方がたくさんありますが、一旦はこれでだいたいの変化を行うことができるようになるかと思います。
特にtranslate、rotate、scaleあたりは使う頻度も高そうなのでしっかりと頭に入れておきたいところ。

雑なまとめになってしまいましたが、最後まで読んでくれた方はありがとうございます。