この記事の概要
CSS で要素を変形をさせるとき、昔ながらの書き方は次のようなものです。
.element {
transform: translate(30px, 20px) rotate(20deg);
}
最近はそれぞれの指定を分離して、次のようにも書けます。
.element {
translate: 30px 20px;
rotate: 20deg;
}
個別に書いた方がアニメーションの管理などはしやすいですし、diff も見やすいです。
ただ、常に個別に書くのが優れているわけでもないので、その点について記事にしました。
例示するもの
こういった 3D 表現を実施する際、移動や回転を多く使います。
この立方体を例にして説明します。
translate のローカル座標とグローバル座標
例に出した立方体はこのようなコードでできています。
<div class="cube">
<div class="face front">front</div>
<div class="face back">back</div>
<div class="face right">right</div>
<div class="face left">left</div>
<div class="face top">top</div>
<div class="face bottom">bottom</div>
</div>
.cube {
position: relative;
transform-style: preserve-3d;
transform: rotateX(-30deg) rotateY(30deg);
}
.face {
position: absolute;
}
.front {
transform: translateZ(25dvmin);
}
.back {
transform: rotateY(180deg) translateZ(25dvmin);
}
.right {
transform: rotateY(90deg) translateZ(25dvmin);
}
.left {
transform: rotateY(-90deg) translateZ(25dvmin);
}
.top {
transform: rotateX(90deg) translateZ(25dvmin);
}
.bottom {
transform: rotateX(-90deg) translateZ(25dvmin);
}
こちらを、書いてある数値のまま各プロパティに分離してみます。
translate
の場合は 1 つの値だけを指定すると X 軸の移動になってしまうので、3 つの値を指定しています。
.front {
- transform: translateZ(25dvmin);
+ translate: 0 0 25dvmin;
}
.back {
- transform: rotateY(180deg) translateZ(25dvmin);
+ rotate: y 180deg;
+ translate: 0 0 25dvmin;
}
.right {
- transform: rotateY(90deg) translateZ(25dvmin);
+ rotate: y 90deg;
+ translate: 0 0 25dvmin;
}
.left {
- transform: rotateY(-90deg) translateZ(25dvmin);
+ rotate: y -90deg;
+ translate: 0 0 25dvmin;
}
.top {
- transform: rotateX(90deg) translateZ(25dvmin);
+ rotate: x 90deg;
+ translate: 0 0 25dvmin;
}
.bottom {
- transform: rotateX(-90deg) translateZ(25dvmin);
+ rotate: x -90deg;
+ translate: 0 0 25dvmin;
}
このコードの場合、次のような見た目になります。
回転の向きは正しそうですが、すべての面が同じ向き(画面向かって右下)に移動してしまっています。
実は、translate
を使ってもともとの見た目を再現するためには、このように書く必要があります。
.front {
translate: 0 0 25dvmin;
}
.back {
rotate: y 180deg;
- translate: 0 0 25dvmin;
+ translate: 0 0 -25dvmin;
}
.right {
rotate: y 90deg;
- translate: 0 0 25dvmin;
+ translate: 25dvmin 0 0;
}
.left {
rotate: y -90deg;
- translate: 0 0 25dvmin;
+ translate: -25dvmin 0 0;
}
.top {
rotate: x 90deg;
- translate: 0 0 25dvmin;
+ translate: 0 -25dvmin 0;
}
.bottom {
rotate: x -90deg;
- translate: 0 0 25dvmin;
+ translate: 0 25dvmin 0;
}
transform
を使う場合、記載の順番に気を付ける必要はありますがローカル座標で操作できます。
一方でtranslate
の場合はグローバル座標での操作となります。
どちらかが優れているというよりは、操作したい内容にあわせて変えた方が良いものだと言えそうです。
例えば幾何形態を考えるときはローカル座標の方が扱いやすいと思っています。
複数軸での rotate が複雑
例に出した立方体は X 軸に -30 度、Y 軸に 30 度傾いています。
transform
を用いた書き方はこちらです。
.element {
transform: rotateX(-30deg) rotateY(30deg);
}
直感に沿っていますね。
次に、rotate
を使います。
rotate
の書式はrotate: x y z angle;
なので、次のように書けば同じ結果が得られそうに思いませんか?
.cube {
rotate: -1 1 0 30deg;
}
ところが、実際にはこのような見た目になります。
もともとの見た目に近づけようと思うと、次のようになります。
.cube {
rotate: -1 1 -0.3 45deg;
}
XYZ のベクトルを合成して、その軸にあわせて回転するという仕組み上、各軸の回転量を個別に扱うのが難しいです。
今回の例でいえば X 軸と Y 軸の回転させたい角度が同じなのでまだ考えられますが、それぞれの値が違う場合はかなり難しいです。
これも、どちらが優れているというわけではなく、場合によって使い分けた方が良さそうです。
例えばアイソメトリック風のビューにしたい場合transform
での指定は簡単ですがrotate
を使うと複雑です。1
最後に
CSS において、古いプロパティと新しいプロパティがある場合、大抵は新しいプロパティが上位互換です。
ただtransform
においては一概には言えず、実施したいものにあわせて使い分けるのが良さそうだと思ったので記事にしてみました。
細かなアニメーション制御をしたい場合は個別に、静的に綺麗な配置を実現したい場合は一括、みたいな区分はあるのかもしれません。
-
複雑というか、私はどの値ならアイソメトリックっぽい見た目になるか、計算できませんでした……。 ↩