
CSSしか書けないけどウェブ上で3D表現してみたい
-
2023年3月24日
こんにちは。ココネウェブ開発室のHです。
webページを作るときにちょっとした3D表現をしてみたいなぁと思うと思うのですが、
webGLとかThree.jsとか使ったことないしわからんなぁと思うと思うのです。
CSSだけで3D表現できないかなぁという人向けに簡単な立方体の実装方法をご紹介します。
まず立方体を作る箱を作成し (class=”cube”)、箱の中に面を6つ作成します (class=”panel”)。
各面ごとにstyle設定が必要なので、個別にclassを付与します。
わかりやすいように各パネルに文字列とclassで透過色を指定しておきます。
サイズは200px × 200pxでボーダーも付けておきます。
<div class="cube">
<div class="panel front"><p>Front</p></div>
<div class="panel back"><p>Back</p></div>
<div class="panel left"><p>Left</p></div>
<div class="panel right"><p>Right</p></div>
<div class="panel top"><p>Top</p></div>
<div class="panel bottom"><p>Bottom</p></div>
</div>
<style>
.panel {
width: 200px;
height: 200px;
border: 4px solid #999;
box-sizing: border-box;
font-family: Impact;
font-size: 62px;
color: #fff;
text-align: center;
}
.front {
background-color: hsl(90deg 90% 70%/60%);
}
.back {
background-color: hsl(180deg 90% 70%/60%);
}
.left {
background-color: hsl(0deg 90% 70%/60%);
}
.right {
background-color: hsl(320deg 90% 70%/60%);
}
.top {
background-color: hsl(30deg 90% 70%/60%);
}
.bottom {
background-color: hsl(240deg 90% 70%/60%);
}
</style>
div要素が縦に並んでるだけの状態なので、箱(class=”cube”)の transform-style プロパティに preserve-3d を設定します。
transform-style: preserve-3d は子要素を3D空間に配置するという設定をするものです。
面(class=”panel”)にdefaultの位置設定しておきます。
.cube { /* 新しく追加 */
position: relative;
width: 200px;
height: 200px;
transform-style: preserve-3d;
}
.panel { /* .panel に下記を追加 */
position: absolute;
top: 0;
left: 0;
}
3D空間に配置してますが、同じ位置に配置してるので、まだ平面として重なっているだけの見え方になっています。
ここから各面(class=”panel”)を3D空間に配置していきます。
front を手前に100px、back を奥に100px動かします。
.front { /* .front に追加 */
transform: translateZ(100px);
}
.back { /* .back に追加 */
transform: translateZ(-100px) rotateX(180deg); /* 裏返す必要があるので rotateX を指定 */
}
手前から見ると見た目は変わらないのですが、斜め上から見るとこのように配置されていることがわかります。
続いて側面を配置していきます。
left を縦軸で-90度回転させて左に100px、right を縦軸で90度回転させて右に100px動かします。
.left { /* .left に追加 */
left: -100px;
transform: rotateY(-90deg);
}
.right { /* .right に追加 */
left: auto; /* .panel で left: 0 になっているので auto でオーバーライドする */
right: -100px;
transform: rotateY(-90deg);
}
最後は上下面を配置します。
top を横軸で90度回転させて上に100px、bottom を横軸で-90度回転させて下に100px動かします。
.top {
top: -100px;
transform: rotateX(90deg);
}
.bottom {
top: auto; /* .panel で top: 0 になっているので auto でオーバーライドする */
bottom: -100px;
transform: rotateX(-90deg);
}
これで立方体が完成しました。
が、なんか違和感がありますよね、、、?
現在の状態を手前から見ると、
このように平面にしか見えません。
ここで立方体の仕上げです。perspective を設定します。
箱(class=”cube”)を囲う空間(class=”stage”)を作ります。
<div class="stage"<!-- この div で囲う -->
<div class="cube">...</div>
</div>
<style>
.stage { /* 追加 */
margin: 100px auto;
width: 200px;
perspective: 500px;
}
</style>
立体感が出ました。perspective は視点の設定です。立体的な座標変換ができます。
わかりやすく言うと遠近法の設定ができます。遠くのものは小さく、近くのものは大きく見えるというアレです。
基本値は none で値として渡す length が0や負数と同じく、立体的な座標変換をしない、という設定です。
length の値はz軸のどの位置から見たように表示するか、という距離を設定します。
最後にアニメーションを付けて動かしてみます。
<style>
.cube { /* .cube に追加 */
animation: mixedRotation 8s linear infinite;
}
@keyframes mixedRotation { /* 追加 */
0% {
transform: rotateX(0deg) rotateY(0deg);
}
100% {
transform: rotateX(360deg) rotateY(360deg);
}
}
</style>
See the Pen
Cube made with only css by shortrange (@shortrange)
on CodePen.
css animation で回転させています。
箱にカーソルを乗せると箱の前面と背面が開き、回転が速くなります。
ボタンを設置してJSでclassを付与してアニメーションを変化させても良いと思います。
各面がdivエレメントなので、6面に遷移を付けてみても面白いかもです。
今回のソースです。
https://codepen.io/shortrange/pen/mdLwrLX
vueバージョンもあります。こちらはボタンで動きを制御しています。
backをクリックすると箱が開きます。
https://codepen.io/shortrange/pen/MWGavyx
ココネでは一緒に働く仲間を募集中です。
ご興味のある方は、ぜひこちらの採用特設サイトをご覧ください。