気になっていたページの背景指定の途切れが解決か?

ウインドウの縦サイズより小さい表示のウェブページは、bodyタグの領域がページの内容合わせになってしまうので、bodyタグの背景色など、背景指定がウインドウ内で途切れてしまいますよね?(よね?)
ウェブブラウザは、CSSで「height:100%」にしてもウインドウの縦サイズに合わせてくれませんから、htmlに背景指定したり、いろいろと工夫をして結局ダメだった経験があります。CSS3が当たり前になった今も、CSSの指定だけでは解決できないものと認識してました。

最近になって再び気になったのでJavaScriptでの解決を試みました。

結果、ウインドウのリサイズイベントを受けてbodyタグの縦サイズを現下のウインドウ縦サイズに指定するという方法で概ね成功しました。
でも話は単純ではありません。ウインドウ縦サイズをままで指定してしまうと、ウインドウ縦サイズよりbodyタグ縦サイズが大きい場合は、上にスクロールした時にページ内表示がbodyダグからはみ出てしまって更に見苦しいことになってしまいます。捲し上げた着物の裾から足が覗いてる感じ(時代劇で岡っ引きが走ってる時のアレです。)の事態です。
かといってbodyタグに「overfrow:hidden」を指定したら元も子もないし、「overfrow:scroll」は指定してみなかったけど「当て次の上に当て次ってどうよ」と思いながら、「いやいやここはまっすぐとJavaScriptでクリアしよう」と気を取り直した次第です。
話も実際も横道には逸れたのですが、JavaScriptでページエレメント群のclientHeightとgetComputedStyle()を参照してページ表示サイズを算出する方法で、まあ、だいたいのところ解決できたようです。(すみません。きっちりできたと確証がないのです。)

なんか、やたら前置きが長くなったのですが解決のための考え方を掲載します。ご参考になれば幸いです。実際のコーディングは、対象となるページによって異なるので自前でお願いします。

まず、hustlemouse仕様にて、ページHTMLの基本構成です。

<html>
<head> … </head>
<body>
<header class='page'> … </header>
<section class='page'> … </header>
<footer class='page'> … </header>
<div id='workingAnim' style='position:absolute;display:none;left:-200%; opacity:65%;'></div>
</body>
</html>

最後のdivタグは’position:absolute’なので無視してbodyタグ直下の「class=’page’」指定のエレメント対象にしてサイズを拾って行くことになります。hustlemouse仕様ではbodyタグ直下だけに「class=’page’」指定をしますので、getElementsByClassName()を使ってエレメントへの参照を取得しています。つづくターミナル表示は、macOS上でSafariでのコンソール出力の表記です。また、「>」がコンソールへ私が打ち込んだ入力テキストで、「<」がリターンキーを押すと現れる出力情報です。

> ns = document.getElementsByClassName('page')

< HTMLCollection (3) = $2
 0 <header class="page">…</header>
 1 <section class="page">…</section>
 2 <footer class="page">…</footer>

nsにはHTMLCollectionが代入されます。ちなみにquerySelectorAll()を使って取得るすことも可能ですが、気持ち処理が遅い?ということです。紹介だけしておきます。こちはNodeListが代入されます。

> ns = document.querySelectorAll('body > *.page')

< NodeList (3) = $1
 0 <header class="page">…</header>
 1 <section class="page">…</section>
 2 <footer class="page">…</footer>

このあと、それぞれのエレメントオブジェクトを参照して表示中の縦サイズ(clientHeight)の情報を取得して加算していけば良いのですが、それぞれのエレメントには当然と言えるぐらいマージンとかボーダーとかの指定をしますよね。残念ながら、clientWidthやclientHeightはマージンやボーダーの幅を含んだ数値ではありません。
そりゃあ、マージンなんて自分でCSSに設定しているから判っちゃいますが、必ずしもピクセル単位で指定していないというよりも、相対的に表示したいから’rem’とか’vh’を使っているのが普通だと思います。CSS指定から算出する方も考えましたが、まっすぐJavascriptの道を歩いて、動的に’px’の値を取得したいですよね。というわけでgetComputedStyle()の出番が巡ってまいりました。いやあ、初めて使いました。

getComputedStyle()は、エレメントのスタイル情報を全て取得できます。全てというより重要なのは「解決値」、現在の表示情報であるということです。ほとんどのプロパティでは「計算値」がそのまま「解決値」になるそうですが、widthとheightは「使用値」が「解決値」になるそうです。(開発者向けのウェブ技術>Web API>Window>Window.getComputedStyle()に感謝。)ちょっとクラッ?としますが、少々不安な気分になったのでwidthとheightは、clientWidthとclientHeightで取得して、ほかはgetComputedStyle()で「解決値」を取得としました。

たとえば、取得したnsの先頭エレメントのマージントップを取得するには、次のように記述します。

value = window.getComputedStyle(ns[0])['margin-top']

まずここで確認したいことは、CSSプロパティの記述です。’margin’という具合にて一括で参照はできません。’margin-top’、’margin-bottom’、’border-top-width’、’border-bottom-width’と各々別々に参照する必要があります。つぎにvalueに入ってくる値はたとえば’20px’とテキストになりますので気をつけましょう。それでも、単位は希求するピクセルです。正規表現(単位に変更があっても事故らないように予防線を張ります。)を使って数値を取り出してから数値化して処理すると良いでしょう。

これで、ページ表示の縦サイズがウインドウ縦サイズより小さい場合だけ、bodyタグのエレメントのheigtに「ウインドウ縦サイズ値 + ‘px’」を指定すれば、すっきりと背景がウインドウを埋めつくすようになります。おっと、大きい場合は’auto’を指定しましょう。

と、これで一応の解決はしたのですが、少々不安が残ります。ページ表示の縦サイズの算出はできたのですが、どうも?ブラウザの開発ツールでモニターできる数値と比較すると近似値ではあるのですが少々差異があります。双方の値が同じぐらいの時に1ピクセルぐらい背景が欠けるかはみ出すかするかもしれません。まあ、大勢に問題ないのでよいのですが、きっちりしてないのは気になるところでした。そかさ。