CSS3のtransform:skewでナナメに変形した時の表示位置を制御する

ナナメにすると起こる位置ずれ

時々見かけるナナメに配置された画像やボックスの表現をしてみたくてtransform:skewプロパティを触ってみたのですが、表示位置が変わってしまって意図した位置に配置ができません。

この原因はオブジェクトの実際に配置されている位置と、シアーをかけて表示される位置にズレがある為です。

例えば高さ100pxのボックスにY軸にシアーをかけて歪んだ分高さが10px増えても、高さ100pxのボックスと処理されるため見かけ上10px上に上がってしまいます。

このズレを修正すべく自分なりに調べて解決法を探ってみました。

変形した距離を計算する

skewYで変形をかけた場合を図にするとこんな感じです。

変形位置がデフォルト(transform-origin: 50% 50%)skewYでY軸を歪ませた場合、ボックスの中心を軸に指定角度分シアーをかけた平行四辺形になります。

図に描いてみると、緑で囲った直角三角形の高さの半分だけボックス位置がずれるのが分かります。

直角三角形になっているということは、底辺にあたる横幅とskewYで指定した角度が分かれば高さが求められるということです。
ただし、高さを求める三角形の底辺はボックス幅の1/2なるので、計算式は下記のようになります。

高さ=(底辺×tan(角度))÷2

この距離を相殺してあげれば配置上と表示上の位置がビシっと合います。

ちなみにタンジェントとかよく分からないので、こちらのサイトで計算させていただきました。

直角三角形の辺・角度は? – 高精度計算サイト

サンプル

固定幅で表示させたい場合

上記の計算式で高さを割り出し、その数値だけmargin-topなどで下げてあげればOKです。

HTML

<div class="container1"></div>

CSS

css
.container1{
	width: 500px;
	height: 500px;
	background-color: #f00;
	margin-top:44.8px;
	margin-bottom:0;
	-webkit-transform: skewY(-10deg);
	   -moz-transform: skewY(-10deg);
	    -ms-transform: skewY(-10deg);
	     -o-transform: skewY(-10deg);
	        transform: skewY(-10deg);
}

width:100%指定で端を切らずに表示させたい場合

固定表示の場合は上記の数値をcssに指定してあげればいいのですが、width:100%の場合はそうはいきません。
ブラウザサイズが可変すると高さも可変してしまうからです。

ですのでjavascript(jquery)で動的に処理してみます。
尚javascriptにタンジェントを計算する式があるのですが、角度ではなくラジアンを代入するので一文加えます。

HTML

<div class="container2"></div>

CSS

css
.container2{
	width: 100%;
	height: 500px;
	background-color: #f0f;
	position:absolute;
	-webkit-transform: skewY(-10deg);
	   -moz-transform: skewY(-10deg);
	    -ms-transform: skewY(-10deg);
	     -o-transform: skewY(-10deg);
	        transform: skewY(-10deg);
}

jquery

$(window).on('load resize' , function(){
	var windowWidth = $(window).width();
	var deg = 10;	// 指定した角度
	var rad = deg * Math.PI/180;	//ラジアンの計算
	var objectTop = (windowWidth/2)*Math.tan(rad);	//高さ計算
	$('.container2').css({
		'margin-top' :  objectTop ,
		'margin-bottom' : objectTop
	});
});

これでブラウザサイズが変わっても端が切れずに表示されます。

width:100%指定で固定位置に表示させたい場合

こちらはシンプルに5000pxなど余裕を持ったサイズで固定位置に表示してもいいのですが、javascriptで計算したほうがposition:relativeでも使えますし融通が利くのでこちらも計算式を書いておきます。

HTML

<div class="container3"></div>

CSS

.container3{
	width: 100%;
	height: 500px;
	background-color: #f0f;
	position:absolute;
	-webkit-transform: skewY(-10deg);
	   -moz-transform: skewY(-10deg);
	    -ms-transform: skewY(-10deg);
	     -o-transform: skewY(-10deg);
	        transform: skewY(-10deg);
}

jquery

$(window).on('load resize' , function(){
	var windowWidth = $(window).width();
	var deg = 10;	// 指定した角度
	var rad = deg * Math.PI/180;	//ラジアンの計算
	var objectTop = (windowWidth/2)*Math.tan(rad);	//高さ計算
	$('.container3').css({
		'margin-top' : 300 - objectTop,	//300:配置する高さ
		'margin-bottom' : objectTop
	});
});

これでブラウザサイズが変わっても固定位置に配置されます。
ちなみにこの例ではボックス左上のポイントに合わせているのでjqueryの中でmargin-topを300 – objectTopと計算していますが、右上に合わせたい場合は300 + objectTopになります。

まとめ

ということで、transform:skewYを例にボックスにシアーをかけた場合のズレ補正の解決方法を書いてみました。
自己流なんでもっと簡単な解決方法があるのかも知れませんし、そもそも役に立つシチュエーションがどれだけあるのかも分かりませんが、知っておけばデザインに幅が広がるのではないでしょうか。

ちなみにskewを含めtransformプロパティでどんな効果が出るかシミュレートできるサイトが便利でしたので最後にご紹介しておきます。

CSS3 Generator

rotateやskewなどは試行する必要もさほどないと思いますが、matrixは角度ではなくラジアンを指定するのでシミュレートできるととても助かります。

2件のコメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA