perspective-origin:三次元的に配置された要素に対する視点の位置を定める

初期値 50% 50%
適用対象 変形可能要素
継承 しない
アニメーション <length>値、<percentage>値
対応ブラウザ caniuseで確認

perspective-originプロパティの説明

perspective-originは、三次元的に配置された要素に対する視点の位置を定めます。この機能は、perspectiveプロパティと合わせて使うことによって効果を発揮します。

本プロパティは、transformで変形を加えた子要素を持つ親要素に対して適用します。概念としてはZ軸に奥行きを持つ箱を用意して、その中を覗く視点が存在するという捉え方ができます。

perspective-originに指定できる値

x-position
消失点の水平方向の座標を表す値です。<length>値、<percentage>値、キーワードが使用できます。
y-position
消失点の垂直方向の座標を表す値です。<length>値、<percentage>値、キーワードが使用できます。

perspective-originの使い方とサンプル

perspective-originプロパティの構文は以下の通りです。

CSS
/* 水平方向 */
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>値によって実現できます。

表示確認
CSS
.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%;
}
HTML
<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>

アニメーションを指定した時の歪み

立体的な要素にアニメーションを適用する祭に、視点の位置によっては歪んで見えることがあります。以下の例は、先ほどのサンプルをアレンジして極端な数値に変えたものの比較です。

表示確認
CSS
/* アニメーションの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);
	}
}

perspective-originに関連するCSSプロパティ

変形・トランスフォーム
backface-visibility 要素が裏面を向いた時に可視化するかどうかを指定する
perspective 三次元的に配置された要素の遠近感を指定する
perspective-origin 三次元的に配置された要素に対する視点の位置を定める
transform 要素に座標変換を適用して移動、回転、拡大縮小、歪みなどを行う
transform-origin 要素を座標変換させる時の原点を指定する
transform-style 変形可能要素が配置される空間の次元を切り替える