CSSだけで回転する立方体を作る

CSSで3D表現する練習として立方体を作成したので、そのメモとして。

#立方体を作る
##①要素の準備
空間（space）の中に立方体（box）を用意して、立方体の中に面（face）を配置するイメージで作成する。
要素のサイズはboxよりもspaceが大きくなるように適当に設定。
分かりやすいようにspaceとfaceには色付けしている。

```html:html
<body>
    <div class="space">
        <div class="box">
            <div class="face top">top</div>
            <div class="face bottom">bottom</div>
            <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>
    </div>
</body>
```

```css:css
.space {
    width:200px;
    height:200px;
    background-color:skyblue;
}

.box {
    width: 100px;
    height: 100px;
}

.face {
    width: 100%;
    height: 100%;
    border: solid 2px black;
    background-color:forestgreen;
}
```

現段階の表示
![3dbox1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401303/6a5f389c-855e-d706-51dc-c65095a0771e.png)

##②面の回転
配置にあたって各面をそれぞれ回転させる。
回転には`transform: rotate**(**deg);`を使用する。
今回は3D表現にしたいためspaceに`perspective: **px;`を適用してZ軸を追加する。
faceを3D空間に配置するためにboxには`transform-style: preserve-3d;`を適用する。
（boxを回転させたのは見やすくするため）

```css:css
/* 追記内容 */
.space {
    perspective: 800px;
}

.box {
    transform-style: preserve-3d;
    transform:
        rotateX(20deg)
        rotateY(20deg)
        rotateZ(-20deg);
}

.face.top {
    transform: rotateX(90deg);
}

.face.bottom {
    transform: rotateX(-90deg);
}

.face.front {

}

.face.back {
    transform: rotateY(180deg);
}

.face.right {
    transform: rotateY(90deg);
}

.face.left {
    transform: rotateY(-90deg);
}
```

現段階の表示
![3dbox2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401303/4ffb6ca0-09db-b905-c86c-5dd50d9c5666.png)

##③配置を整える
`position`と`translate**`を活用してそれぞれの面の配置を整える。
また、boxがspaceの中央に配置されるようにspaceに追記する。
枠線が綺麗に重なるようにfaceに`box-sizing:border-box;`を適用する。

```css:css
/* 追記内容 */
.space {
    display: flex;
    justify-content: center;
    align-items: center;
}

.box {
    position: relative;
}

.face {
    box-sizing: border-box;
    position: absolute;
}

.face.top {
    transform: translateZ(50px);
}

.face.bottom {
    transform: translateZ(50px);
}

.face.front {
    transform: translateZ(50px);
}

.face.back {
    transform: translateZ(50px);
}

.face.right {
    transform: translateZ(50px);
}

.face.left {
    transform: translateZ(50px);
}
```

現段階の表示
![3dbox3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401303/c0c60fef-0148-465f-0ee5-9ba0cc97d1d8.png)

立方体自体はこれで完成。

#立方体を回転させる
boxに`animation`を適用して立方体に動きをつける。
`animation: キーフレーム名 動作時間 イージング 遅延時間 ループ回数 再生方向 プロパティ引継 状態;`で指定する。

```css:css
/* 追記内容 */
.box {
    animation: rotation 5s linear 0s infinite normal none running;
}

@keyframes rotation {
    0% {
        transform:
            rotateX(0deg)
            rotateY(-90deg)
            rotateZ(-180deg);
    }

    25% {
        transform:
            rotateX(90deg)
            rotateY(0deg)
            rotateZ(-90deg);
    }

    50% {
        transform:
            rotateX(180deg)
            rotateY(90deg)
            rotateZ(0deg);
    }

    75% {
        transform:
            rotateX(270deg)
            rotateY(180deg)
            rotateZ(90deg);
    }

    100% {
        transform:
            rotateX(360deg)
            rotateY(270deg)
            rotateZ(180deg);
    }
}
```

表示
![3dbox4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401303/ed83804f-4ab1-5cfd-b8da-a57da62b682e.gif)
これで完成。

#サンプルコード全文
```html:html
<!DOCTYPE html>

<html lang="ja">

<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="css.css">
    <title>3Dbox</title>
</head>

<body>
    <div class="space">
        <div class="box">
            <div class="face top">top</div>
            <div class="face bottom">bottom</div>
            <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>
    </div>
</body>

</html>
```
```css:css
.space {
    width:200px;
    height:200px;
    background-color:skyblue;
    perspective: 800px;
    display: flex;
    justify-content: center;
    align-items: center;
}

.box {
    width: 100px;
    height: 100px;
    transform-style: preserve-3d;
    transform:
        rotateX(20deg)
        rotateY(20deg)
        rotateZ(-20deg);
    position: relative;
    animation: rotation 5s linear 0s infinite normal none running;
}

@keyframes rotation {
    0% {
        transform:
            rotateX(0deg)
            rotateY(-90deg)
            rotateZ(-180deg);
    }

    25% {
        transform:
            rotateX(90deg)
            rotateY(0deg)
            rotateZ(-90deg);
    }

    50% {
        transform:
            rotateX(180deg)
            rotateY(90deg)
            rotateZ(0deg);
    }

    75% {
        transform:
            rotateX(270deg)
            rotateY(180deg)
            rotateZ(90deg);
    }

    100% {
        transform:
            rotateX(360deg)
            rotateY(270deg)
            rotateZ(180deg);
    }
}

.face {
    width: 100%;
    height: 100%;
    border: solid 2px black;
    box-sizing: border-box;
    background-color:forestgreen;
    position: absolute;
}


.face.top {
    transform:
        rotateX(90deg)
        translateZ(50px);
}

.face.bottom {
    transform:
        rotateX(-90deg)
        translateZ(50px);
}

.face.front {
    transform: translateZ(50px);
}

.face.back {
    transform:
        rotateY(180deg)
        translateZ(50px);
}

.face.right {
    transform:
        rotateY(90deg)
        translateZ(50px);
}

.face.left {
    transform:
        rotateY(-90deg)
        translateZ(50px);
}
```