このウェブサイトはご利用の端末での閲覧に対応していません。
This website does not support your device.

CSSで立体的な要素を作る

記事Aug.26th, 2021
CSSの“transform”プロパティと三次元変形関数を使用して立体的に見える要素を作る方法について解説。

CSSの変形

CSSではtransform”プロパティと各種定義されている変形関数を使用することで通常は矩形である要素の形状を変更することができます。

変形関数の中でも三次元変形関数を使用することで要素を立体的に見えるように変形させることができます。

この記事では複数の要素に変形を加えることで立体的に見える立方体をCSSで作る方法について解説していきます。

Step~1 下準備

要素は曲げたりすることはできないので立体の1個ずつの面は別の要素として配置する必要があります。

まずは立方体の面となる6個の要素を用意し、それらを立方体を配置する三次元空間となる1個の親要素で囲みます。必ずしも二重に囲む必要はありませんが、立方体とは別の要素も同じ三次元空間に配置する場合は下の例のように二重に囲むと後々変形を加えるのが簡単になります。

<!-- 三次元空間を表す要素 -->
<div class="canvas">
<!-- 立方体の全体を表す要素 -->
<div class="cube">
<!-- 立方体の面を表す要素 -->
<div class="cube-face-1"></div>
<div class="cube-face-2"></div>
<div class="cube-face-3"></div>
<div class="cube-face-4"></div>
<div class="cube-face-5"></div>
<div class="cube-face-6"></div>
</div>
</div>

この例ではdiv”要素を使用していますが、img”要素などの他の要素でも変形させることができます。

次にスタイルシートを用意します。

/* 三次元空間を表す要素 */
.canvas {

}

/* 立方体の全体を表す要素 */
.cube {
margin: 0 auto;
width: 100px;
}

/* 立方体の面を表す要素 */
.cube-face-1, .cube-face-2, .cube-face-3, .cube-face-4, .cube-face-5, .cube-face-6 {
box-sizing: border-box;
}

.cube-face-1 {
width: 100px;
height: 100px;
background-color: rgba(71,209,209,0.8); /* */
}

.cube-face-2 {
width: 100px;
height: 100px;
background-color: rgba(170,207,83,0.8); /* */
}

.cube-face-3 {
width: 100px;
height: 100px;
background-color: rgba(248,184,98,0.8); /* */
}

.cube-face-4 {
width: 100px;
height: 100px;
background-color: rgba(211,56,28,0.8); /* */
}

.cube-face-5 {
width: 100px;
height: 100px;
background-color: rgba(233,84,107,0.8); /* */
}

.cube-face-6 {
width: 100px;
height: 100px;
background-color: rgba(180,76,151,0.8); /* */
}

ここで、要素は変形された後も変形前にあった場所を占有し続けるので、position”プロパティを使用して全部の面を重ね合わせます。

また、position: absolute;を適用するともともと要素が占有していた空間は完全になくなり、親要素の高さが“0”になります。そのため、このままでは周りに他のコンテンツが配置された場合に重なってしまいます。height”プロパティで立方体を表す要素(“<div class="cube">”)に高さを持たせても良いですが、他の要素を同じ三次元空間に配置する場合に邪魔になることもあるのでここでは三次元空間(“<div class="canvas">”)の高さを設定してこれを防ぎます。

/* 三次元空間を表す要素 */
.canvas {
height: 100px;
}

/* 立方体の全体を表す要素 */
.cube {
margin: 0 auto;
width: 100px;
}

/* 立方体の面を表す要素 */
.cube-face-1, .cube-face-2, .cube-face-3, .cube-face-4, .cube-face-5, .cube-face-6 {
box-sizing: border-box;
position: absolute;
}

.cube-face-1 {
width: 100px;
height: 100px;
background-color: rgba(71,209,209,0.8); /* */
}

.cube-face-2 {
width: 100px;
height: 100px;
background-color: rgba(170,207,83,0.8); /* */
}

.cube-face-3 {
width: 100px;
height: 100px;
background-color: rgba(248,184,98,0.8); /* */
}

.cube-face-4 {
width: 100px;
height: 100px;
background-color: rgba(211,56,28,0.8); /* */
}

.cube-face-5 {
width: 100px;
height: 100px;
background-color: rgba(233,84,107,0.8); /* */
}

.cube-face-6 {
width: 100px;
height: 100px;
background-color: rgba(180,76,151,0.8); /* */
}

position: absolute;で重ねられた要素は単純に後にHTMLコードに記述された要素が上になるように重ねられます。

Step~2 要素を立体的に再配置する

次に、それぞれの面が立方体の面となるように再配置します。要素を変形させるtransform”プロパティとその値として要素の変形方法を指定する変形関数translateZ()”関数rotateX()”関数rotateY()”関数を使用し、それぞれの要素を移動、回転します。

回転などの変形は既定では要素の中心を原点(transform-origin: 50% 50%;)として行われるのでこれを考慮しながら要素を変形させます。

/* 三次元空間を表す要素 */
.canvas {
height: 100px;
}

/* 立方体の全体を表す要素 */
.cube {
margin: 0 auto;
width: 100px;
}

/* 立方体の面を表す要素 */
.cube-face-1, .cube-face-2, .cube-face-3, .cube-face-4, .cube-face-5, .cube-face-6 {
box-sizing: border-box;
position: absolute;
}

.cube-face-1 {
width: 100px;
height: 100px;
background-color: rgba(71,209,209,0.8); /* */
transform: translateZ(50px);
}

.cube-face-2 {
width: 100px;
height: 100px;
background-color: rgba(170,207,83,0.8); /* */
transform: rotateY(180deg) translateZ(50px);
}

.cube-face-3 {
width: 100px;
height: 100px;
background-color: rgba(248,184,98,0.8); /* */
transform: rotateY(-90deg) translateZ(50px);
}

.cube-face-4 {
width: 100px;
height: 100px;
background-color: rgba(211,56,28,0.8); /* */
transform: rotateY(90deg) translateZ(50px);
}

.cube-face-5 {
width: 100px;
height: 100px;
background-color: rgba(233,84,107,0.8); /* */
transform: rotateX(90deg) translateZ(50px);
}

.cube-face-6 {
width: 100px;
height: 100px;
background-color: rgba(180,76,151,0.8); /* */
transform: rotateX(-90deg) translateZ(50px);
}

上の例を見てわかる通り、transform”プロパティによって要素を変形させただけでは三次元空間に要素が配置されていることにはならず、要素が重なる順番は変わりません。なので、上下と左右の面は90度回転されて見えなくなりましたが、前後の面は重なる順番が変わっていません。

Step~3 要素を三次元空間に配置する

三次元空間を表す親要素のtransform-style”プロパティの値を“preserve-3d”に指定し、子要素が三次元に配置されるように設定します。transform-style”プロパティは子孫要素には継承されないので、立方体の面も三次元に配置されるように立方体の全体を表す要素も同様に設定します。

/* 三次元空間を表す要素 */
.canvas {
height: 100px;
transform-style: preserve-3d;
}

/* 立方体の全体を表す要素 */
.cube {
margin: 0 auto;
width: 100px;
transform-style: preserve-3d;
}

/* 立方体の面を表す要素 */
.cube-face-1, .cube-face-2, .cube-face-3, .cube-face-4, .cube-face-5, .cube-face-6 {
box-sizing: border-box;
position: absolute;
}

.cube-face-1 {
width: 100px;
height: 100px;
background-color: rgba(71,209,209,0.8); /* */
transform: translateZ(50px);
}

.cube-face-2 {
width: 100px;
height: 100px;
background-color: rgba(170,207,83,0.8); /* */
transform: rotateY(180deg) translateZ(50px);
}

.cube-face-3 {
width: 100px;
height: 100px;
background-color: rgba(248,184,98,0.8); /* */
transform: rotateY(-90deg) translateZ(50px);
}

.cube-face-4 {
width: 100px;
height: 100px;
background-color: rgba(211,56,28,0.8); /* */
transform: rotateY(90deg) translateZ(50px);
}

.cube-face-5 {
width: 100px;
height: 100px;
background-color: rgba(233,84,107,0.8); /* */
transform: rotateX(90deg) translateZ(50px);
}

.cube-face-6 {
width: 100px;
height: 100px;
background-color: rgba(180,76,151,0.8); /* */
transform: rotateX(-90deg) translateZ(50px);
}

上の例を見ると、面がtransform”プロパティで再配置した順番に重なるようになったのがわかります。

Step~4 遠近感を設定する

transform-style: preserve-3d;によって要素は三次元に配置されるようになりましたが、このままでは遠近感がないので手前にある要素も奥にある要素も同じ大きさで表示されます。ここで、perspective”プロパティを使用して視点から三次元空間の描画面までの距離を指定し、遠近感を加えます。

perspective”プロパティの値は<length>”値で座標空間のZ座標が“Z=0”となる面までの距離を指定し、pxcmなどで指定できます。

perspective”プロパティで距離を指定するとその距離に合わせてZ座標が“Z=0”よりも大きい(視点から近い)要素は大きく、Z座標が“Z=0”よりも小さい(視点から遠い)要素は小さく表示されるようになります。

/* 三次元空間を表す要素 */
.canvas {
height: 100px;
transform-style: preserve-3d;
perspective: 30cm;
}

/* 立方体の全体を表す要素 */
.cube {
margin: 0 auto;
width: 100px;
transform-style: preserve-3d;
}

/* 立方体の面を表す要素 */
.cube-face-1, .cube-face-2, .cube-face-3, .cube-face-4, .cube-face-5, .cube-face-6 {
box-sizing: border-box;
position: absolute;
}

.cube-face-1 {
width: 100px;
height: 100px;
background-color: rgba(71,209,209,0.8); /* */
transform: translateZ(50px);
}

.cube-face-2 {
width: 100px;
height: 100px;
background-color: rgba(170,207,83,0.8); /* */
transform: rotateY(180deg) translateZ(50px);
}

.cube-face-3 {
width: 100px;
height: 100px;
background-color: rgba(248,184,98,0.8); /* */
transform: rotateY(-90deg) translateZ(50px);
}

.cube-face-4 {
width: 100px;
height: 100px;
background-color: rgba(211,56,28,0.8); /* */
transform: rotateY(90deg) translateZ(50px);
}

.cube-face-5 {
width: 100px;
height: 100px;
background-color: rgba(233,84,107,0.8); /* */
transform: rotateX(90deg) translateZ(50px);
}

.cube-face-6 {
width: 100px;
height: 100px;
background-color: rgba(180,76,151,0.8); /* */
transform: rotateX(-90deg) translateZ(50px);
}

また、視点は既定では三次元空間の描画面の中心ですが、perspective-origin”プロパティによって上下左右へ動かすことができます。

/* 三次元空間を表す要素 */
.canvas {
height: 100px;
transform-style: preserve-3d;
perspective:30cm;
perspective-origin: 10cm -10cm;
}

/* 立方体の全体を表す要素 */
.cube {
margin: 0 auto;
width: 100px;
transform-style: preserve-3d;
}

/* 立方体の面を表す要素 */
.cube-face-1, .cube-face-2, .cube-face-3, .cube-face-4, .cube-face-5, .cube-face-6 {
box-sizing: border-box;
position: absolute;
}

.cube-face-1 {
width: 100px;
height: 100px;
background-color: rgba(71,209,209,0.8); /* */
transform: translateZ(50px);
}

.cube-face-2 {
width: 100px;
height: 100px;
background-color: rgba(170,207,83,0.8); /* */
transform: rotateY(180deg) translateZ(50px);
}

.cube-face-3 {
width: 100px;
height: 100px;
background-color: rgba(248,184,98,0.8); /* */
transform: rotateY(-90deg) translateZ(50px);
}

.cube-face-4 {
width: 100px;
height: 100px;
background-color: rgba(211,56,28,0.8); /* */
transform: rotateY(90deg) translateZ(50px);
}

.cube-face-5 {
width: 100px;
height: 100px;
background-color: rgba(233,84,107,0.8); /* */
transform: rotateX(90deg) translateZ(50px);
}

.cube-face-6 {
width: 100px;
height: 100px;
background-color: rgba(180,76,151,0.8); /* */
transform: rotateX(-90deg) translateZ(50px);
}

なお、視点を移動しても描画面と平行な要素は変化しないため、変更した視点の位置によっては変形された要素が歪んで見えることがあります。

Step~5 立方体を変形する

transform”プロパティによって立方体の全体を表す要素を変形させることで立方体全体を変形させることができます。次の例ではrotate3d()”関数によって立方体全体を回転させています。

変形は立方体の全体を表す要素(“<div class="cube">”)の変形の原点を中心にして行われます。既定では要素の中心(transform-origin: 50% 50%;)が原点ですが、ここではすべての子要素にposition: absolute;を適用したことで、高さが“0”になっているので、原点は立方体の上の面の中心と一致します。下の例ではtransform-origin:”プロパティで原点を立方体の中心に移動させることで立方体の中心点を中心に回転するようにしています。

/* 三次元空間を表す要素 */
.canvas {
height: 100px;
transform-style: preserve-3d;
perspective:30cm;
perspective-origin: 10cm -10cm;
}

/* 立方体の全体を表す要素 */
.cube {
margin: 0 auto;
width: 100px;
transform-style: preserve-3d;
transform-origin: 50px 50px;
transform: rotate3d(1,1,1,45deg);
}

/* 立方体の面を表す要素 */
.cube-face-1, .cube-face-2, .cube-face-3, .cube-face-4, .cube-face-5, .cube-face-6 {
box-sizing: border-box;
position: absolute;
}

.cube-face-1 {
width: 100px;
height: 100px;
background-color: rgba(71,209,209,0.8); /* */
transform: translateZ(50px);
}

.cube-face-2 {
width: 100px;
height: 100px;
background-color: rgba(170,207,83,0.8); /* */
transform: rotateY(180deg) translateZ(50px);
}

.cube-face-3 {
width: 100px;
height: 100px;
background-color: rgba(248,184,98,0.8); /* */
transform: rotateY(-90deg) translateZ(50px);
}

.cube-face-4 {
width: 100px;
height: 100px;
background-color: rgba(211,56,28,0.8); /* */
transform: rotateY(90deg) translateZ(50px);
}

.cube-face-5 {
width: 100px;
height: 100px;
background-color: rgba(233,84,107,0.8); /* */
transform: rotateX(90deg) translateZ(50px);
}

.cube-face-6 {
width: 100px;
height: 100px;
background-color: rgba(180,76,151,0.8); /* */
transform: rotateX(-90deg) translateZ(50px);
}

また、次の例ではanimation”プロパティを使用して立方体を回転させ続けるアニメーションを適用しています。

/* 三次元空間を表す要素 */
.canvas {
height: 100px;
transform-style: preserve-3d;
perspective:30cm;
perspective-origin: 10cm -10cm;
}

/* 立方体の全体を表す要素 */
.cube {
margin: 0 auto;
width: 100px;
transform-style: preserve-3d;
transform-origin: 50px 50px;
animation: 5s linear infinite CubeRotation;
}

@keyframes CubeRotation {
0% { transform: rotate3d(1,1,1,0deg); }
100% { transform: rotate3d(1,1,1,360deg); }
}

/* 立方体の面を表す要素 */
.cube-face-1, .cube-face-2, .cube-face-3, .cube-face-4, .cube-face-5, .cube-face-6 {
box-sizing: border-box;
position: absolute;
}

.cube-face-1 {
width: 100px;
height: 100px;
background-color: rgba(71,209,209,0.8); /* */
transform: translateZ(50px);
}

.cube-face-2 {
width: 100px;
height: 100px;
background-color: rgba(170,207,83,0.8); /* */
transform: rotateY(180deg) translateZ(50px);
}

.cube-face-3 {
width: 100px;
height: 100px;
background-color: rgba(248,184,98,0.8); /* */
transform: rotateY(-90deg) translateZ(50px);
}

.cube-face-4 {
width: 100px;
height: 100px;
background-color: rgba(211,56,28,0.8); /* */
transform: rotateY(90deg) translateZ(50px);
}

.cube-face-5 {
width: 100px;
height: 100px;
background-color: rgba(233,84,107,0.8); /* */
transform: rotateX(90deg) translateZ(50px);
}

.cube-face-6 {
width: 100px;
height: 100px;
background-color: rgba(180,76,151,0.8); /* */
transform: rotateX(-90deg) translateZ(50px);
}

要素の裏面は既定では表面と同じ内容が鏡像のように表示されます。ここまでの例では構造が分かりやすいように面の裏側を表示していますが、非表示にしたい場合はbackface-visibility”プロパティによって設定できます。

Step~6 複数の要素を三次元に配置する

transform-style: preserve-3d;が適用された要素の中に配置された兄弟要素は、これまでの立方体のそれぞれの面と同じように、同じ三次元空間を共有します。

三次元空間を表す要素(“<div class="canvas">”)の中にこれまでの例と同じ立方体を2個配置しています。

<!-- 三次元空間を表す要素 -->
<div class="canvas">
<!-- 1個目の立方体の全体を表す要素 -->
<div class="cube1">
<!-- 1個目の立方体の面を表す要素 -->
<div class="cube-face-1"></div>
<div class="cube-face-2"></div>
<div class="cube-face-3"></div>
<div class="cube-face-4"></div>
<div class="cube-face-5"></div>
<div class="cube-face-6"></div>
</div>

<!-- 2個目の立方体の全体を表す要素 -->
<div class="cube2">
<!-- 2個目の立方体の面を表す要素 -->
<div class="cube-face-1"></div>
<div class="cube-face-2"></div>
<div class="cube-face-3"></div>
<div class="cube-face-4"></div>
<div class="cube-face-5"></div>
<div class="cube-face-6"></div>
</div>
</div>
/* 三次元空間を表す要素 */
.canvas {
height: 100px;
transform-style: preserve-3d;
perspective:30cm;
perspective-origin: 10cm -10cm;
}

.cube1, cube2 {
margin: 0 auto;
width: 100px;
transform-style: preserve-3d;
transform-origin: 50px 50px;
}

/* 1個目の立方体の全体を表す要素 */
.cube1 {
animation: 5s linear infinite CubeRotation1;
}

@keyframes CubeRotation1 {
0% { transform: rotateZ(0deg); }
100% { transform: rotateZ(360deg); }
}

/* 2個目の立方体の全体を表す要素 */
.cube2 {
animation: 5s linear infinite CubeRotation2;
}


@keyframes CubeRotation2 {
0% { transform: rotateY(0deg); }
100% { transform: rotateY(360deg); }
}

/* 立方体の面を表す要素 */
.cube-face-1, .cube-face-2, .cube-face-3, .cube-face-4, .cube-face-5, .cube-face-6 {
box-sizing: border-box;
position: absolute;
}

.cube-face-1 {
width: 100px;
height: 100px;
background-color: rgba(71,209,209,0.8); /* */
transform: translateZ(50px);
}

.cube-face-2 {
width: 100px;
height: 100px;
background-color: rgba(170,207,83,0.8); /* */
transform: rotateY(180deg) translateZ(50px);
}

.cube-face-3 {
width: 100px;
height: 100px;
background-color: rgba(248,184,98,0.8); /* */
transform: rotateY(-90deg) translateZ(50px);
}

.cube-face-4 {
width: 100px;
height: 100px;
background-color: rgba(211,56,28,0.8); /* */
transform: rotateY(90deg) translateZ(50px);
}

.cube-face-5 {
width: 100px;
height: 100px;
background-color: rgba(233,84,107,0.8); /* */
transform: rotateX(90deg) translateZ(50px);
}

.cube-face-6 {
width: 100px;
height: 100px;
background-color: rgba(180,76,151,0.8); /* */
transform: rotateX(-90deg) translateZ(50px);
}

通常は要素は重なったとしても交わることはありませんが、同じ三次元空間に配置された要素は交わることができます。

一番上へ
トップにもどる
シェアする
シェアする
Facebookでシェアする
ツイート
Google+でシェア
Pocket
はてなブックマーク