ビューポートとは何か
ビューポートは「今、ユーザーに見えている画面の領域」です。ページ全体(ドキュメント)の中で、スクロールせずに表示されている矩形がビューポート。ここが重要です:JavaScriptで“画面サイズ”や“画面に対する位置”を扱うときは、常にビューポートを基準にします。スクロールやズーム、モバイルのUI(アドレスバーの出入り)により、ビューポートは変化します。
ビューポートのサイズを読む(基本の数値)
window.innerWidth / innerHeight(外側寄りの見える領域)
<script>
console.log(window.innerWidth, window.innerHeight);
</script>
HTMLここが重要です:innerWidth/innerHeight は“今見えている画面”の幅・高さを返します。モバイルではブラウザUIの表示状態で変わることがあり、動的に値が増減します。
document.documentElement.clientWidth / clientHeight(スクロールバー除外の見える領域)
<script>
const w = document.documentElement.clientWidth;
const h = document.documentElement.clientHeight;
console.log(w, h);
</script>
HTMLここが重要です:clientWidth/Height は内部スクロールバーの厚みを除いた“レイアウト計算に向いた”見える領域です。「収まるか」の判定やグリッド計算で安定します。
画面に対する位置・サイズの取得(rectの基礎)
getBoundingClientRect で画面座標を知る
<div id="box" style="width:160px; height:80px; border:1px solid #333"></div>
<script>
const r = box.getBoundingClientRect();
console.log(r.left, r.top, r.width, r.height); // 画面左上からの位置とサイズ(小数あり)
</script>
HTMLここが重要です:rect は“ビューポート基準”の位置とサイズを返します。スクロールやズームが反映され、交差判定・ポップアップ位置合わせなど“画面目線”の処理で必須です。
モバイルの二種類のビューポート(レイアウト vs ビジュアル)
レイアウトビューポートとビジュアルビューポート
- レイアウトビューポート:CSSレイアウトの基準。ズームやUIの出入りに対して比較的安定。
- ビジュアルビューポート:実際に見えている領域。ピンチズームやアドレスバーの出入りでサイズが変わる。
ここが重要です:見え方に合わせたいなら“ビジュアル”、レイアウトの計算を崩したくないなら“レイアウト”。実装目的に応じて使い分けます。
VisualViewport API(高度な追従が必要な場合)
<script>
if (window.visualViewport) {
visualViewport.addEventListener("resize", () => {
console.log(visualViewport.width, visualViewport.height, visualViewport.scale);
});
visualViewport.addEventListener("scroll", () => {
console.log(visualViewport.offsetLeft, visualViewport.offsetTop);
});
}
</script>
HTMLここが重要です:ピンチズーム時の表示崩れ対策や、HUDを画面の“見えている部分”に追従させたい場合に有効です。
CSSのビューポート単位と設定(vw/vh と meta)
vw / vh 単位(画面に対する割合)
.hero { width: 100vw; height: 100vh; }
CSSここが重要です:vw/vh はビューポートに対する割合。モバイルで“100vhが実際の見える高さとズレる”問題があり、最近は動的な単位(lvh/svh/dvh)が追加されています。対応環境なら dvh(動的高さ)を使うと“アドレスバー出入り”に追従します。
meta viewport(モバイルのレイアウト基準を決める)
<meta name="viewport" content="width=device-width, initial-scale=1">
HTMLここが重要です:これを設定しないと、モバイルで“狭い画面をデスクトップ前提で縮小表示”され、タップやレイアウトが破綻します。必ず指定しましょう。
実践例(中央配置・可視判定・スクロール補正)
画面中央にモーダルを置く(transform補正)
<div id="modal" class="center">モーダル</div>
<style>
.center {
position: fixed; left: 50%; top: 50%;
transform: translate(-50%, -50%);
max-width: min(92vw, 640px);
max-height: 84vh; overflow: auto;
background: #fff; border: 1px solid #ccc; padding: 16px;
}
</style>
HTMLここが重要です:50%は“左上”を中央に運ぶので、translate(-50%, -50%)で“中心”に補正します。max-width/max-heightで画面に収め、コンテンツは内側スクロール。
要素が画面内に見えているかを判定
<script>
function isInViewport(el, margin = 0) {
const r = el.getBoundingClientRect();
return r.bottom > -margin && r.top < window.innerHeight + margin &&
r.right > -margin && r.left < window.innerWidth + margin;
}
console.log("見えている?", isInViewport(document.getElementById("box"), 50));
</script>
HTMLここが重要です:rect と画面サイズ(innerWidth/Height)で“可視/不可視”判定。marginを設けると近接時に先読みできます。
固定ヘッダで隠れないスクロール位置の計算
<header style="position:sticky; top:0; height:64px"></header>
<section id="target" style="margin-top:1200px">目的地</section>
<script>
function scrollToVisibleTop(el, header = 0) {
const rect = el.getBoundingClientRect();
const y = window.scrollY + rect.top - header;
window.scrollTo({ top: Math.max(y, 0), behavior: "smooth" });
}
scrollToVisibleTop(target, 64);
</script>
HTMLここが重要です:rect(画面基準)+現在のスクロール量で“ページ基準の座標”を作り、固定ヘッダ分を差し引くと、ちょうど見える位置に止まります。
よくある落とし穴と回避策
100vh が実際の高さとズレる(モバイル)
アドレスバーの出入りで“見える高さ”が変わります。対策:可能なら dvh を使用、JSで innerHeight を読んで高さを上書き、もしくはコンテンツに余白を残してはみ出しを許容。
スクロールバーの厚みで計算がズレる
内側レイアウトは clientWidth/Height(バー除外)で、外側配置は offsetWidth/Height(バー込み)で扱います。目的に応じた値を選ぶとズレが消えます。
画面基準と親基準の混同
画面の中央や可視判定は“ビューポート基準”(rect/innerWidth/Height)。親内の位置合わせは“offsetParent基準”(offsetLeft/Top、clientWidth/Height)。基準を混ぜないことが計算の安定につながります。
ピンチズームへの非対応でHUDがズレる
視覚に追従するHUDなら VisualViewport を監視。対応が不要なら、過剰な追従を避けて“レイアウト基準”を優先し、要素には適切な余白とレスポンシブを与える。
まとめ
ビューポートは「今見えている画面領域」で、画面サイズは window.innerWidth/innerHeight、レイアウト計算向けには document.documentElement.clientWidth/Height、位置・サイズは getBoundingClientRect で取得します。モバイルではレイアウト/ビジュアルの二種類のビューポートを意識し、必要に応じて VisualViewport を使う。CSSでは vw/vh(可能なら dvh)と meta viewport で基準を整え、固定ヘッダやスクロールの補正は rect と現在のスクロール量の組み合わせで丁寧に対処。基準の選び分けを徹底すれば、初心者でもズレのない“画面目線”のUIレイアウトが安定して作れます。
