perspective-originプロパティの説明
CSSのperspective-origin
プロパティは、三次元的に配置された要素に対する視点の位置を定めます。この機能は、perspective
プロパティと合わせて使うことによって効果を発揮します。
本プロパティは、transform
で変形を加えた子要素を持つ親要素に対して適用します。概念としてはZ軸に奥行きを持つ箱を用意して、その中を覗く視点が存在するという捉え方ができます。
perspective-originに指定できる値
x-position
- 消失点の水平方向の座標を表す値です。
<length>
値、<percentage>
値、キーワードが使用できます。 y-position
- 消失点の垂直方向の座標を表す値です。
<length>
値、<percentage>
値、キーワードが使用できます。
perspective-originの使い方とサンプルコード
perspective-origin
プロパティの構文は以下の通りです。
/* 水平方向 */
perspective-origin: x-position;
/* 記述例 */
perspective-origin: left;
perspective-origin: center;
perspective-origin: right;
/* 水平方向 | 垂直方向 */
perspective-origin: x-position y-position;
/* 記述例 */
perspective-origin: left top;
perspective-origin: left 50%;
perspective-origin: 0 bottom;
perspective-origin: center 0;
perspective-origin: center 50%;
perspective-origin: 50% bottom;
perspective-origin: right top;
perspective-origin: right 50%;
perspective-origin: 100% bottom;
perspective-origin: -100% -50%;
/* 水平方向 | 垂直方向(キーワード値の場合のみ有効) */
perspective-origin: y-position x-position;
/* グローバル値 */
perspective-origin: inherit;
perspective-origin: initial;
perspective-origin: revert;
perspective-origin: unset;
perspective-originの実例
それでは実際にperspective-origin
プロパティの書き方を見ていきましょう。以下の例は、transform-style
の値にpreserve-3d
を与えて三次元空間のコンテナを作成し、子要素で立方体を組み立てて設置した時の比較です。
perspective
の値によって視点の深度が変わりますが、今回は500px
に固定した上で視点の位置を変えています。キーワード値では、各辺の0
地点が基準となりますが、それを超えた角度から眺める表現は、<length>
値や<percentage>
値によって実現できます。
<section class="samp_box">
<div class="grid_item">
<h2>top left</h2>
<div class="cube_wrapper" id="po_1">
<ul>
<li class="face_1">1</li>
<li class="face_2">2</li>
<li class="face_3">3</li>
<li class="face_4">4</li>
<li class="face_5">5</li>
<li class="face_6">6</li>
</ul>
</div>
</div>
<div class="grid_item">
<h2>top center</h2>
<div class="cube_wrapper" id="po_2">
<ul>
<li class="face_1">1</li>
<li class="face_2">2</li>
<li class="face_3">3</li>
<li class="face_4">4</li>
<li class="face_5">5</li>
<li class="face_6">6</li>
</ul>
</div>
</div>
<div class="grid_item">
<h2>top right</h2>
<div class="cube_wrapper" id="po_3">
<ul>
<li class="face_1">1</li>
<li class="face_2">2</li>
<li class="face_3">3</li>
<li class="face_4">4</li>
<li class="face_5">5</li>
<li class="face_6">6</li>
</ul>
</div>
</div>
<div class="grid_item">
<h2>200% 200%</h2>
<div class="cube_wrapper" id="po_4">
<ul>
<li class="face_1">1</li>
<li class="face_2">2</li>
<li class="face_3">3</li>
<li class="face_4">4</li>
<li class="face_5">5</li>
<li class="face_6">6</li>
</ul>
</div>
</div>
<div class="grid_item">
<h2>200% -100%</h2>
<div class="cube_wrapper" id="po_5">
<ul>
<li class="face_1">1</li>
<li class="face_2">2</li>
<li class="face_3">3</li>
<li class="face_4">4</li>
<li class="face_5">5</li>
<li class="face_6">6</li>
</ul>
</div>
</div>
<div class="grid_item">
<h2>-100% 200%</h2>
<div class="cube_wrapper" id="po_6">
<ul>
<li class="face_1">1</li>
<li class="face_2">2</li>
<li class="face_3">3</li>
<li class="face_4">4</li>
<li class="face_5">5</li>
<li class="face_6">6</li>
</ul>
</div>
</div>
</section>
.samp_box {
overflow: auto;
padding: 1rem;
background-color: #eee;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 1rem;
}
.samp_box > div {
position: relative;
background-color: #fff;
text-align: center;
}
div > h2 {
position: absolute;
width: 100%;
margin: .3rem 0 0;
font-size: 0.875rem;
font-weight: normal;
}
/* 立方体のコンテナを作成 */
.cube_wrapper {
width: 100px;
height: 100px;
margin: 50px auto;
perspective: 500px;
}
.cube_wrapper > ul {
width: 100%;
height: 100%;
padding: 0;
color: #fff;
font-size: 3rem;
font-weight: bold;
line-height: 100px;
list-style: none;
transform-style: preserve-3d;
}
.cube_wrapper li {
position: absolute;
width: 100%;
height: 100%;
}
.face_1 {
transform: translateZ(50px);
background-color: rgba(0, 0, 0, 0.1);
}
.face_2 {
transform: translateY(-50px) rotateX(90deg);
background-color: rgba(255, 0, 153, 0.7);
}
.face_3 {
transform: translateX(-50px) rotateY(-90deg);
background-color: rgba(255, 153, 0, 0.7);
}
.face_4 {
transform: translateY(50px) rotateX(-90deg);
background-color: rgba(250, 59, 59, 0.7);
}
.face_5 {
transform: translateX(50px) rotateY(90deg);
background-color: rgba(0, 153, 255, 0.7);
}
.face_6 {
transform: translateZ(-50px) rotateX(180deg);
background-color: rgba(0, 191, 115, 1);
}
/* コンテナの視点を変更 */
#po_1 {
perspective-origin: top left;
}
#po_2 {
perspective-origin: top center;
}
#po_3 {
perspective-origin: top right;
}
#po_4 {
perspective-origin: 200% 200%;
}
#po_5 {
perspective-origin: 200% -100%;
}
#po_6 {
perspective-origin: -100% 200%;
}
アニメーションを指定した時の歪み
立体的な要素にアニメーションを適用する祭に、視点の位置によっては歪んで見えることがあります。以下の例は、先ほどのサンプルをアレンジして極端な数値に変えたものの比較です。
/* アニメーションのCSSは以下の部分に追加します */
.cube_wrapper > ul {
/* 他のプロパティは変更なし */
animation: 30s linear 0s infinite normal none running TurnCube;
}
@keyframes TurnCube {
0%{
transform:rotateX(0deg) rotateY(0deg);
}
100%{
transform:rotateX(360deg) rotateY(360deg);
}
}