[CSS] スマホの横画面に固定する方法とrotate 90degのズレ解消法

2023年10月24日

CSS

eyecatch 先日、Podcastラジオで開発状況を公開している、清重影織ちゃんペパの冒険という絵本ゲーム。 この開発の基盤をほぼほぼ作らせてもらって楽しませてもらっていて、開発作業ももうほぼ終盤で、思いついたブラッシュアップなどをやっている時に、スマートフォンでこのゲームを実行してみると、縦表示(Landscape)モードの時に、まるでゲームにならないので、横画面(Horizontal)にする必要が出てきました。 このゲームはインターネットブラウザで手軽に表示できる仕様にしていて、内容もHTML,CSS,Javascriptだけで動かしています。 スマートフォンでは、横画面固定の設定もあるが、ゲームをプレイするヒトが、わざわざそんな設定をするなんてめんどくさい事をやらせるわけにはいきません。 そして、横画面固定モードは、JavascriptにもCSSにも存在しないため、独自の方法で構築するしかありません。 今回はそんな横画面固定をする方法と、その時に生じるズレに解消方法について、解説したいと思います。

Javascriptで対応

スマホだけに、orientationchangeというイベントがあります。 これは、画面が回転したときのイベントを取得でき、この時に、スマホの表示画面(画面サイズ)が、縦サイズと横サイズを判定して、どちらが長いかで、Vertical(縦)とHorizontal(横)を判別する方式で、次のように掛けば簡単に判定できます。 window.addEventListener('orientationchange' , check_orientation) function check_orientation(){ const rect = document.body.getBoundingClientRect() const orientation = rect.width > rect.height ? "horizontal" : "vertical" alert(orientation) reutrn orientation } このプログラムはブラウザで実行しながら、端末を縦横回転させると、画面が切り替わったタイミングでアラートが表示されるプログラムなのですが、これを利用して、画面構成を切り替えることができます。 もちろん、縦横を切り替えると、x軸、y軸が入れ替わるため、ゴリゴリに書き込んだプログラムを修正していくのは、なかなかの作業ボリュームになるでしょう。 このイベントのリファレンスサイトは、こちら。 https://developer.mozilla.org/ja/docs/Web/API/Window/orientationchange_event

CSSで対応

実は、Javascriptよりも、CSSで対応すると、すんなりできてしまうことがわかりました。 それは、メディアクエリのorientation判別する機能を使い、次の様に書くだけで対応できます。 @media (orientation:landscape){ body{ width:100%; height:100%; transform: rotate(0deg); } } @media (orientation:portrait){ body{ width:100vh; height:100vw; transform: rotate(90deg); } } ポイントは、widthとheightをスマホの縦横表示でそれぞれ入れ替える必要があるということです。 縦表示(vertical)の場合は、じつは何もしなくてもいいのですが、念のため、widthとheightに100%をセットして、rotateを0degでセットしています。 横表示(horizontal)になった場合に、widthに100vh(縦サイズの100%)、heightに100wh(横サイズの100%)をセットするようにしたら、サイズのズレは無くなりました。

位置ズレが発生する場合の対処法

今回のゲームでは、次のようなフレーム構成でDOM構造を作っていました。 <body> <div id='box'></div> </body> id="box"は、縦横の上限を設けており、常に画面の中心に表示させるために、次のようなcssでセットされていました。 body{ background-color:red; margin:0; } #box{ background-color:blue; width:100%; height:100%; position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); } これに先程のorientationメディアクエリを適用させると、次のような表示不具合が発生しました。 横画面 縦画面 box(青)が画面いっぱいに表示されているハズなのに、左側と下側に、bodyの赤色が見えてしまっています。 boxの表示サイズは画面サイズと同じだったので、どうやら、右上にズレてしまっているようです。 解決方法 次のコードを追加するだけで、上記のズレが解消されました。 body{ transform-origin: 50vw; } これは、センタリング指定しているtransformでの-50%という指定が、縦横解釈がうまくできない状態らしく、強制的にそのズレを補正するために、横幅の50%を差し引いて上げることで、右上にずれていたboxが適正な表示がされるようになりました。

あとがき

transformを使ったセンタリング設定をしていない場合は、こんなめんどくさい設定を追加する必要はないのですが、ゲームフレームの場合は、意外とセット去れているケースが多いかもしれないと思って、ブログに残しておくことにしました。 この記事が参考になったヒトが一人でもいるといいな。