テスト 1. 通常の HTML 要素 (非 body および HTML ルート要素) の offsetWidth、clientWidth、scrollWidth および関連する高さの属性を確認します:
<style type="text/css">
html,
body {
margin: 0;
}
body {
padding: 100px;
}
.box {
overflow: scroll;
width: 400px;
height: 300px;
padding: 20px;
border: 10px solid #000;
margin: 0 auto;
box-sizing: content-box;
}
.box-2 {
border: 1px solid #000;
}
</style>
<body>
<div class="box">
<div class="box-2">...</div>
</div>
</body>
<script type="text/javascript">
var boxE = document.querySelectorAll('.box')[0];
console.log('scrollWidth:' + boxE.scrollWidth);
console.log('scrollHeight:' + boxE.scrollHeight);
console.log('clientWidth:' + boxE.clientWidth);
console.log('clientHeight:' + boxE.clientHeight);
console.log('offsetWidth :' + boxE.offsetWidth);
console.log('offsetHeight:' + boxE.offsetHeight);
</script>
<styletype="text/css">
html,
body{
margin: 0;
}
body{
padding: 100px;
}
.box{
overflow: scroll;
width: 400px;
height: 300px;
padding: 20px;
border: 10px solid #000;
margin: 0 auto;
box-sizing: content-box;
}
.box-2{
border: 1px solid #000;
}
</style>
<body>
<divclass="box">
<divclass="box-2">...</div>
</div>
</body>
<scripttype="text/javascript">
var boxE = document.querySelectorAll('.box')[0];
console.log('scrollWidth:' + boxE.scrollWidth);
console.log('scrollHeight:' + boxE.scrollHeight);
console.log('clientWidth:' + boxE.clientWidth);
console.log('clientHeight:' + boxE.clientHeight);
console.log('offsetWidth :' + boxE.offsetWidth);
console.log('offsetHeight:' + boxE.offsetHeight);
</script>
この例では、ボックス要素の幅と高さは 400*300、パディングは 20 ピクセル、境界線は 10 ピクセルです。クロム上の対応するボックス モデルは次のとおりです。
js の実行結果:
ボックスモデルと js の実行結果から、次のことがわかります。
1) offsetWidth と offsetHeight は、Chrome で要素を検査するときに表示されるサイズとまったく同じです。
2) clientWidth と clientHeight は、それぞれ offsetWidth と offsetHeight から対応する境界線 (上下合計 20 ピクセル、左右合計 20 ピクセル) とスクロール バーの幅 (クロム下のスクロール バーの幅は 17 ピクセル) を引いたものと等しくなります。 );
3)scrollWidth の場合、水平方向のオーバーフローは発生しません。オーバーフローのため、scrollWidth は clientWidth と同じですが、スクロール バーの幅は含まれません。これは、以前に提案された結論も検証します。
4) この例では、scrollHeight は、実際には div.box-2、div.box-2 の上下のパディング (合計 40 ピクセル) + offsetHeight(1370 ピクセル) に等しくなります。
5) 上記のテストでは、box-sizing というもう 1 つの CSS に注目してください。上記のコードでは、box-sizing を content-box に変更すると、結果は次のようになります。 offsetWidth と clientWidth は同じなので、scrollWidth に対応する領域は変更されません。
6) 他のブラウザの結果は、結論 1 ~ 5 と一致しています。
テスト 2. HTML ルート要素と body 要素の関連するオフセット クライアント スクロール幅と高さの属性を確認します:
<style type="text/css">
html,
body {
margin: 0;
}
body {
border: 10px solid #D4D2D2;
}
.box {
overflow: scroll;
width: 400px;
height: 300px;
padding: 20px;
border: 10px solid #000;
margin: 0 auto;
box-sizing: content-box;
}
.box-2 {
border: 1px solid #000;
}
</style>
<body>
<div class="box">
<div class="box-2">...</div>
</div>
<div class="box">
<div class="box-2">...</div>
</div>
<div class="box">
<div class="box-2">...</div>
</div>
<div class="box">
<div class="box-2">...</div>
</div>
</body>
<script>
console.log('docE.scrollWidth:' + document.documentElement.scrollWidth);
console.log('scrollHeight:' + document.documentElement.scrollHeight);
console.log('docE.clientWidth:' + document.documentElement.clientWidth);
console.log('docE.clientHeight:' + document.documentElement.clientHeight);
console.log('docE.offsetWidth :' + document.documentElement.offsetWidth);
console.log('docE.offsetHeight:' + document.documentElement.offsetHeight);
console.log('');
console.log('body.scrollWidth:' + document.body.scrollWidth);
console.log('body.scrollHeight:' + document.body.scrollHeight);
console.log('body.clientWidth:' + document.body.clientWidth);
console.log('body.clientHeight:' + document.body.clientHeight);
console.log('body.offsetWidth :' + document.body.offsetWidth);
console.log('body.offsetHeight:' + document.body.offsetHeight);
</script>
<styletype="text/css">
html,
body{
margin: 0;
}
body{
border: 10px solid #D4D2D2;
}
.box{
overflow: scroll;
width: 400px;
height: 300px;
padding: 20px;
border: 10px solid #000;
margin: 0 auto;
box-sizing: content-box;
}
.box-2{
border: 1px solid #000;
}
</style>
<body>
<divclass="box">
<divclass="box-2">...</div>
</div>
<divclass="box">
<divclass="box-2">...</div>
</div>
<divclass="box">
<divclass="box-2">...</div>
</div>
<divclass="box">
<divclass="box-2">...</div>
</div>
</body>
<script>
console.log('docE.scrollWidth:' + document.documentElement.scrollWidth);
console.log('scrollHeight:' + document.documentElement.scrollHeight);
console.log('docE.clientWidth:' + document.documentElement.clientWidth);
console.log('docE.clientHeight:' + document.documentElement.clientHeight);
console.log('docE.offsetWidth :' + document.documentElement.offsetWidth);
console.log('docE.offsetHeight:' + document.documentElement.offsetHeight);
console.log('');
console.log('body.scrollWidth:' + document.body.scrollWidth);
console.log('body.scrollHeight:' + document.body.scrollHeight);
console.log('body.clientWidth:' + document.body.clientWidth);
console.log('body.clientHeight:' + document.body.clientHeight);
console.log('body.offsetWidth :' + document.body.offsetWidth);
console.log('body.offsetHeight:' + document.body.offsetHeight);
</script>
この例では、本文の下に 4 つのボックス要素があります (合計の高さは 360 * 4 = 1440px)。本文の幅は調整可能で、本文にも 10 ピクセルの境界線があります。実行結果は次のとおりです。
この結果からわかるように:
1) body 要素の境界線が 10 ピクセルであるため、clientWidth は offsetWidth より 20 ピクセル小さくなります。これは上記の理論と一致しますが、驚くべきことに、body のスクロール幅/スクロール高さは実際には等しいということです。 offsetWidth/offsetHeight、scrollWidth /scrollHeight は、要素のスクロール領域の幅と高さです。上記の範囲図によれば、本文のスクロール幅/スクロール高さは、そのオフセット幅/オフセット高さよりも小さい必要があります。
2) docEのscrollWidthとscrollHeightはbody要素のoffsetWidthとoffsetHeightに等しいはずですが、これは一貫していますが、範囲によればdocEのclientWidthは実際にはそのoffsetWidthに等しいです。図では、docE の clientWidth は、offsetWidth からスクロール バーの幅を引いたものとなります。
他のブラウザの実行結果も Chrome とはかなり異なります:
IE11:
1) IE11 での body 要素には chrome での body 要素の問題はありません
2) IE11 の HTML ルート要素にも、Chrome と同様の問題があります
IE10、IE9:
1) IE10 および 9 の body 要素には、chrome の body 要素の問題はありません
2) IE10 および 9 の HTML ルート要素には、Chrome と同様の問題はありません
firefox: 実行結果は IE11 と一致します。
opera: 実行結果は chrome の結果と一致しています。これは、私のバージョンの opera が chrome と同じ Webkit カーネルを使用しているためかもしれません。
IE9 と IE10 が最も標準的なようです。ネットで長時間検索しても、これらの違いを説明する関連情報は見つかりませんでした。これらの問題の理由をいくつか考えてみましょう:
1) まず、Web ページ全体のスクロールは、通常の HTML 要素のスクロールとは異なります。通常の HTML 要素自体がスクロール オブジェクトですが、Web ページの場合、スクロール オブジェクトは HTML のルート要素である必要はありません。またはボディ要素。本文のコンテンツが空の場合、本文の高さは 0 になり、HTML のルート要素の高さも 0 になるためです。このとき、HTML または本文に overflow:scroll CSS を追加すると、スクロールが表示されることがわかります。バーは依然としてブラウザ ウィンドウの右側に表示されるため、Web ページ全体のスクロールでは、理論上、スクロール オブジェクトは HTML 要素や body 要素ではなくウィンドウである必要があります。しかし、テストしたブラウザの限りではそうではありません:
IE10 および IE9 の場合、スクロール オブジェクトは HTML ルート要素であるため、HTML ルート要素のオフセットにはスクロール バーの幅が含まれます。
他のブラウザの場合、スクロール オブジェクトはウィンドウであるため、HTML ルート要素のオフセットにはスクロール バーの幅は含まれません。
2) 次に、通常の要素がスクロールするとき、スクロールするコンテンツ = そのコンテンツ領域 + そのパディング領域になります。Web ページ全体がスクロールする場合、スクロールするコンテンツは HTML ルート要素である必要があります。しかし、テストしたブラウザの限りでは、これは実際には当てはまりません:
IE9、IE10、IE11、Firefox の場合、スクロール領域は HTML ルート要素であるため、documentElement のスクロール幅とスクロール高さは常に Web ページのスクロール領域全体のサイズを表します。
chrome と opera の場合、スクロール オブジェクトは body 要素であるため、body のスクロール幅とスクロール高さは常に Web ページのスクロール領域全体のサイズを表します。
3) 第三に、ブラウザは常に documentElement.clientWidth と documentElement.clientHeight を、スクロール バーを除いた Web ページの表示領域のサイズとして記述します。これは Web ページのコンテンツとは何の関係もありません。
上記の推論は不合理ではありません。スクロール オブジェクトとスクロール領域を例にとります。Chrome でページを特定の位置までスクロールするために js を使用したい場合は、ドキュメントを使用せずに window.scrollTo を使用する必要があります。 body.scrollTop = xxx を処理し、documentElement.scrollTop の設定が無効であることを示します。これは、Chrome の全体のスクロール領域が本文のスクロール領域によって決定されることを示し、js を使用して処理を実行する場合。 IE11 および Firefox でページを特定の位置までスクロールするには、window.scrollTo を使用せずに document.documentElement.scrollTop = xxx を使用する必要があります。これは、IE11 および Firefox のスクロール領域全体が無効であることを示します。 HTML ルート要素のスクロール領域によって決まります。
2. JS を使用して DOM オブジェクトのサイズを正確に取得します
一般的なシナリオは次のとおりです:
1) スクロールバーを除く、Web ページ全体の表示領域のサイズを取得します
2) 非表示のスクロール領域を含む Web ページ全体のサイズを取得します
3) 通常の HTML 要素のサイズを取得します
4) スクロール バーが要素または Web ページに表示されるかどうかを決定します
5) スクロールバーの幅を計算します
下面针对这5个场景一一说明,以下代码均 不考虑IE8及以下,不考虑html4 ,另外请注意viewport的设置,要保证在移动设备上visual viewport与layout viewport重合。
1)如何获取整个网页的可视区域的大小,不包括滚动条
document.documentElement.clientWidth;
document.documentElement.clientHeight;
document.documentElement.clientWidth;
document.documentElement.clientHeight;
2)如何获取整个网页的大小,包括不可见的滚动区域
function pageWidth() {
var doc = document.documentElement,
body = document.body;
if (doc.clientWidth == window.innerWidth) {
return doc["clientWidth"];
}
return Math.max(
body["scrollWidth"], doc["scrollWidth"],
body["offsetWidth"], doc["clientWidth"]
);
}
function pageHeight() {
var doc = document.documentElement,
body = document.body;
if (doc.clientHeight == window.innerHeight) {
return doc["clientHeight"];
}
return Math.max(
body["scrollHeight"], doc["scrollHeight"],
body["offsetHeight"], doc["clientHeight"]
);
}
function pageWidth() {
var doc = document.documentElement,
body = document.body;
if (doc.clientWidth == window.innerWidth) {
return doc["clientWidth"];
}
return Math.max(
body["scrollWidth"], doc["scrollWidth"],
body["offsetWidth"], doc["clientWidth"]
);
}
function pageHeight() {
var doc = document.documentElement,
body = document.body;
if (doc.clientHeight == window.innerHeight) {
return doc["clientHeight"];
}
return Math.max(
body["scrollHeight"], doc["scrollHeight"],
body["offsetHeight"], doc["clientHeight"]
);
}
以上出现的window.innerWidth和window.innerHeight分别用来获取网页包括滚动条的可视区域的宽高,这也是一个兼容性不错的方法,不过从实际开发情况来看,我们需要不包括滚动条的可视区域更多一些,所以在前面没有单独介绍。另外在之前给出的PPK的博客中也有关于这两个属性的兼容性测试,可以去了解。
3)如何获取一个普通html元素的大小
简单方法:
docE.offsetWidth;
docE.offsetHeight;
docE.offsetWidth;
docE.offsetHeight;
利用getBoundingClientRect:
var obj = docE.getBoundingClientRect(),
elemWidth,
elemHeight;
if(obj) {
if(obj.width) {
elemWidth = obj.width;
elemHeight = obj.height;
} else {
elemWidth = obj.right - obj.left;
elemHeight = obj.bottom - obj.top;
}
} else {
elemWidth = docE.offsetWidth;
elemHeight = docE.offsetHeight;
}
var obj = docE.getBoundingClientRect(),
elemWidth,
elemHeight;
if(obj) {
if(obj.width) {
elemWidth = obj.width;
elemHeight = obj.height;
} else {
elemWidth = obj.right - obj.left;
elemHeight = obj.bottom - obj.top;
}
} else {
elemWidth = docE.offsetWidth;
elemHeight = docE.offsetHeight;
}
getBoundingClientRect将在下篇文章中跟其它与位置有关的DOM属性一起再详细介绍。
4 )判断元素或网页有无出现滚动条
function scrollbarState(elem) {
var docE = document.documentElement,
body = document.body;
if (!elem || elem === document || elem === docE || elem === body) {
return {
scrollbarX: docE.clientHeight window.innerHeight,
scrollbarY: docE.clientWidth window.innerWidth
}
}
if (typeof(Element) == 'function' & !(elem instanceof(Element) || !body.contains(elem))) {
return {
scrollbarX: false,
scrollbarY: false
};
}
var elemStyle = elem.style,
overflowStyle = {
hidden: elemStyle.overflow == 'hidden',
hiddenX: elemStyle.overflowX == 'hidden',
hiddenY: elemStyle.overflowY == 'hidden',
scroll: elemStyle.overflow == 'scroll',
scrollX: elemStyle.overflowX == 'scroll',
scrollY: elemStyle.overflowY == 'scroll'
};
return {
scrollbarX: overflowStyle.scroll || overflowStyle.scrollX || (!overflowStyle.hidden & !overflowStyle.hiddenX && elem.clientWidth elem.scrollWidth),
scrollbarY: overflowStyle.scroll || overflowStyle.scrollY || (!overflowStyle.hidden && !overflowStyle.hiddenY && elem.clientHeight elem.scrollHeight)
};
}
function scrollbarState(elem) {
var docE = document.documentElement,
body = document.body;
if (!elem || elem === document || elem === docE || elem === body) {
return {
scrollbarX: docE.clientHeight window.innerHeight,
scrollbarY: docE.clientWidth window.innerWidth
}
}
if (typeof(Element) == 'function' & !(eleminstanceof(Element) || !body.contains(elem))) {
return {
scrollbarX: false,
scrollbarY: false
};
}
var elemStyle = elem.style,
overflowStyle = {
hidden: elemStyle.overflow == 'hidden',
hiddenX: elemStyle.overflowX == 'hidden',
hiddenY: elemStyle.overflowY == 'hidden',
scroll: elemStyle.overflow == 'scroll',
scrollX: elemStyle.overflowX == 'scroll',
scrollY: elemStyle.overflowY == 'scroll'
};
return {
scrollbarX: overflowStyle.scroll || overflowStyle.scrollX || (!overflowStyle.hidden & !overflowStyle.hiddenX && elem.clientWidth elem.scrollWidth),
scrollbarY: overflowStyle.scroll || overflowStyle.scrollY || (!overflowStyle.hidden && !overflowStyle.hiddenY && elem.clientHeight elem.scrollHeight)
};
}
当x或y方向的overflow为scroll的时候,该方向的scrollbarX为true,表示出现滚动条。
5)计算滚动条的宽度
function scrollbarWidth() {
var docE = document.documentElement,
body = document.body,
e = document.createElement('div');
e.style.cssText = 'position: absolute; top: -9999px; width: 50px; height: 50px; overflow: scroll;';
body.appendChild(e);
var _scrollbarWidth = e.offsetWidth - e.clientWidth
body.removeChild(e);
return _scrollbarWidth;
}
function scrollbarWidth() {
var docE = document.documentElement,
body = document.body,
e = document.createElement('div');
e.style.cssText = 'position: absolute; top: -9999px; width: 50px; height: 50px; overflow: scroll;';
body.appendChild(e);
var _scrollbarWidth = e.offsetWidth - e.clientWidth
body.removeChild(e);
return _scrollbarWidth;
}
以上就是本文的全部内容,希望能对您有所帮助:)另外本文第二部分提供的代码,是根据个人思考和经验总结出的一些方法,在兼容性方面可能还有未考虑到的地方, 如果您有遇到其它不兼容的情况或者有更好的代码,还请不吝赐教 ,欢迎您的指导。