Javascript:ページ最下部までスクロールするための最上部は?

Javascript で単純にページの最下部まで移動するには、window.scrollTo(0,document.documentElement.scrollHeight); で一瞬に移動します。ただ、スムーススクロールで最下部まで移動するためにはページの最下部に移動した時のスクロールトップ(ブラウザの左上)を取得する必要があります。ただ、Javascript には要素の幅や高さを表すプロパティがいろいろあってややこしいです。



scrollHeight、offsetHeight、clientHeight

それぞれ同様に width があります。

  • scrollHeight, scrollWidth
  • offsetHeight, offsetWidth
  • clientHeight, clientWidth


scrollHeight

scrollHeight の値は、垂直スクロールバーを使用せずにすべてのコンテンツをビューポート内に収めるために要素に必要な最小の高さに等しくなります。高さは clientHeight と同じ方法で測定されます。要素のパディングは含みますが、境界線、マージン、 (もしあれば) 水平スクロールバーは含みません。これには ::before または ::after のような擬似要素の幅を含むことがあります。要素の内容が垂直スクロールバーを表示することなく収まる場合、その scrollHeight は clientHeight と等しくなります。


MDN Web Docs からの引用ですが太字にしているのは私です。

ページ全体の高さ(長さ)を取得するにはこれですね。要素を document.documentElement にすれば境界線、マージン、スクロールバーはありませんのでページ全体の長さが取得できるはずです。


offsetHeight

MDN の解説を読んでもよくわかりません(笑)。ただ、ページ全体の長さを取得するには適していないんじゃないでしょうか。


clientHeight

clientHeight がルート要素 (<html> 要素) (または文書が後方互換モードである場合は ) に使用された場合、 (スクロールバーを除いた) ビューポートの高さが返されます。


MDN の解説にブラウザの表示高(ビューポートの高さ)を取得するための具体的な解説があります。つまり、document.documentElement.clientHeight とすれば、スクロールバーを除いたビューポートの高さが取得できるということです。

次の項に書きますが、window.innerHeight はスクロールバーがある場合はスクロールバーを含んだ高さになるということです。


ウィンドウサイズ

こちらのサイトがわかりやすいです。


スペースを占めるスクロールバーがある場合、clientWidth/clientHeight はその中の 幅/高さ を提供します。言い換えれば、ドキュメントの可視部分の幅/高さ、コンテンツで利用可能な値を返します。 そして、window.innerWidth/innerHeight はスクロールバーを無視します。


スクロールバーがある場合は document.documentElement.clientHeight を使わないと正しいビューポートの高さは取得できないということです。


実際に水平スクロールバーを出して、

console.log(document.documentElement.clientHeight);
console.log(window.innerHeight);

の値を見てみますと、Chrome, Firefox, Edge 全てで 17px の違いがあります。Windows10 での値です。Chrome のスクロールバーは 15px だと思っていましたが 17px ですね。Linux 版の Chrome のスクロールバーは 15px です。


ページ最下部のスクロールトップ

上で引用した javascript.info の記事では、ドキュメントの高さを取得するコードも紹介されています。


let scrollHeight = Math.max(
  document.body.scrollHeight, document.documentElement.scrollHeight,
  document.body.offsetHeight, document.documentElement.offsetHeight,
  document.body.clientHeight, document.documentElement.clientHeight
);


この6つの値を Window の Chrome, Firefox, Edge で調べてみますと document.documentElement.clientHeight を除いて全て同じ値です。document.documentElement.clientHeight はビューポートの高さになります。


結論

ページ最下部の最上部(ブラウザ左上)を取得するには、

const scrollHeight = Math.max(
  document.body.scrollHeight, document.documentElement.scrollHeight,
  document.body.offsetHeight, document.documentElement.offsetHeight,
  document.body.clientHeight, document.documentElement.clientHeight
);
const bottomScrollTop = scrollHeight - document.documentElement.clientHeight;

で取得できます。


ただ、現実的には、

const scrollHeight = document.documentElement.scrollHeight;
const viewportHeight = document.documentElement.clientHeight;
const bottomScrollTop = scrollHeight - viewportHeight;

これで問題ないんじゃないでしょうか。