Dalam pembangunan web, tidak dapat dielakkan untuk menghadapi masalah mengira saiz dan kedudukan elemen Cara untuk menyelesaikan masalah tersebut adalah dengan menggunakan beberapa API yang disediakan oleh DOM digabungkan dengan pemprosesan keserasian untuk menjelaskan. Sebagai artikel pertama, artikel ini memperkenalkan atribut DOM yang berkaitan dengan saiz yang disediakan oleh DOM, menyediakan beberapa kaedah pemprosesan keserasian dan menerangkan cara menggunakan atribut ini dengan betul berdasarkan senario biasa.
1 Memahami offsetWidth, clientWidth, scrollWidth dan atribut ketinggian yang sepadan
Dengan mengandaikan bahawa bar skrol mendatar dan menegak bagi elemen tertentu diseret ke penghujung, julat offsetWidth, clientWidth, scrollWidth dan atribut lain yang sepadan adalah seperti yang ditunjukkan dalam rajah di bawah:
1) offsetWidth dan offsetHeight sepadan dengan lebar dan ketinggian model kotak kedua-dua nilai ini konsisten dengan saiz yang kita lihat apabila kita menggunakan krom untuk memeriksa elemen:
2) scrollWidth, yang sepadan dengan scrollHeight, ialah lebar dan ketinggian kawasan skrol, tetapi tidak termasuk lebar bar skrol! Kawasan menatal terdiri daripada padding dan kandungan.
3) clientWidth dan clientHeight sepadan dengan lebar dan ketinggian kawasan model kotak selepas mengalih keluar sempadan, tidak termasuk lebar bar skrol.
4) Mana-mana elemen DOM boleh mendapatkan offsetWidth, clientWidth, scrollWidh dan atribut ketinggian yang berkaitan dengan cepat melalui API berikut:
//domE ialah objek Elemen Html DOM
domE.scrollWidth
domE.scrollHeight
domE.clientWidth
domE.clientHeight
domE.offsetWidth
domE.offsetHeight
//domE ialah objek Elemen Html DOM
domE.scrollWidth
domE.scrollHeight
domE.clientWidth
domE.clientHeight
domE.offsetWidth
domE.offsetHeight
5) Atribut ini hampir tiada isu keserasian pada penyemak imbas moden termasuk PC dan mudah alih, dan boleh digunakan dengan yakin. Jika anda ingin mengetahui peraturan keserasian terperinci, anda boleh merujuk kepada 2 artikel berikut:
Keserasian DOM W3C – Paparan Model Objek CSS
Kompilasi dan pengenalan mod paparan cssom cssom-view-module
Atribut yang berkaitan di atas bagi elemen html biasa, elemen akar html dan elemen badan diuji satu demi satu untuk mengesahkan kesimpulan sebelumnya dan meringkaskan beberapa teknik pengalaman yang boleh digunakan secara langsung dalam proses pengekodan sebenar. Sebab mengapa kita perlu membezakan antara elemen html biasa, elemen akar html dan elemen badan adalah kerana teori sebelumnya akan ada beberapa keanehan dalam elemen akar html dan elemen badan, yang perlu dikendalikan dengan berhati-hati.
Nota:
1. Untuk mengurangkan panjang, kod yang disiarkan untuk ujian bukanlah kod lengkap, tetapi ia tidak menjejaskan rujukan pembelajaran Selain itu, keputusan ujian yang diberikan dalam artikel semuanya diperoleh dengan berjalan di bawah chrome (versi: 45.0) Dalam keputusan ujian Jika terdapat perbezaan, keputusan ujian untuk IE9, IE10, IE11, Firefox (versi: 42.0), dan Opera (versi: 34.0) juga akan diberikan. mereka akan diterangkan dalam keputusan ujian IE8 dan ke bawah tidak akan dipertimbangkan.
2. Safari tidak diuji kerana had peranti Selain itu, ia adalah sama dengan kernel Chrome, dan kebolehpercayaan sokongan standard tidak jauh berbeza.
3. Versi lama chrome, firefox dan opera tidak boleh diuji kerana pengehadan peranti Namun, memandangkan sokongan penyemak imbas untuk standard, ketiga-tiga penyemak imbas ini mula menyokong piawaian W3C agak biasa, dan penyemak imbas ini dikemas kini dengan cepat Versi arus perdana pelayar ini di pasaran juga agak baharu.
4. Memandangkan IE8 dan ke bawah tidak dipertimbangkan, dan html kini menggunakan html5, jadi document.compatMode = ‘BackCompat’ tidak dipertimbangkan. Walau bagaimanapun, walaupun mod BackCompat diperkenalkan oleh pelayar IE6, document.compatMode = 'BackCompat' juga wujud untuk chrome, firefox, dll. Contohnya, halaman web berikut, anda membukanya dengan chrome dan mencetak document.compatMode dalam konsol , anda akan mendapati bahawa nilainya juga adalah BackCompat (sebabnya adalah berkaitan dengan fakta bahawa halaman menggunakan dtd html4.0. Jika anda menukarnya kepada dtd html4.01, keadaan ini tidak akan berlaku dalam chrome dan firefox):
http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/refs/compatModeCompat.htm
Untuk pengetahuan lanjut tentang compatMode, anda boleh belajar daripada sumber berikut:
https://developer.mozilla.org/zh-CN/docs/Web/API/Document/compatMode
https://msdn.microsoft.com/en-us/library/ms533687(VS.85).aspx
http://www.cnblogs.com/uedt/archive/2010/09/21/1832402.html
Ujian 1. Sahkan offsetWidth, clientWidth, scrollWidth dan atribut ketinggian yang berkaitan bagi elemen html biasa (bukan badan dan elemen akar html):
<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>
Dalam contoh ini, elemen kotak mempunyai lebar dan tinggi 400*300, padding 20px dan jidar 10px Model kotak yang sepadan di bawah chrome:
hasil pelaksanaan js:
Daripada model kotak dan hasil pelaksanaan js, kita boleh tahu:
1) offsetWidth dan offsetHeight adalah sama persis dengan saiz yang dilihat semasa memeriksa elemen dalam krom
2) clientWidth dan clientHeight masing-masing sama dengan offsetWidth dan offsetHeight tolak sempadan yang sepadan (jumlah 20px ke atas dan ke bawah, sejumlah 20px kiri dan kanan) dan lebar bar skrol (lebar bar skrol di bawah chrome ialah 17px );
3) Untuk scrollWidth, tiada limpahan mendatar berlaku dan disebabkan limpahan: tatal, scrollWidth adalah sama dengan clientWidth, tetapi tidak termasuk lebar bar skrol, yang turut mengesahkan kesimpulan yang dicadangkan sebelum ini;
4) Untuk scrollHeight, dalam contoh ini, ia sebenarnya sama dengan padding atas dan bawah (jumlah 40px) offsetHeight(1370px) div.box-2, div.box-2:
5) Terdapat satu lagi css yang perlu diperhatikan dalam ujian di atas, iaitu saiz kotak Dalam kod di atas, saiz kotak ditetapkan kepada kotak kandungan Jika anda menukarnya kepada kotak sempadan, hasilnya akan menjadi serupa, kerana offsetWidth dan clientWidth masih Kawasan yang sepadan dengan scrollWidth tidak akan berubah.
6) Keputusan pelayar lain adalah konsisten dengan kesimpulan 1-5.
Ujian 2. Sahkan lebar tatal klien ofset yang berkaitan dan atribut ketinggian elemen akar html dan elemen badan:
<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>
Dans cet exemple, il y a 4 éléments de boîte sous le corps (la hauteur totale est de 360 * 4 = 1440px). La largeur du corps est adaptative et le corps a également une bordure de 10px.
Comme vous pouvez le voir sur ce résultat :
1) En raison de la bordure de 10 pixels de l'élément body, la valeur clientWidth est inférieure de 20 pixels à la valeur offsetWidth. Ceci est cohérent avec la théorie mentionnée ci-dessus, mais ce qui est incroyable, c'est que la valeur scrollWidth/scrollHeight du corps est en réalité égale à. son offsetWidth/offsetHeight, scrollWidth /scrollHeight est la largeur et la hauteur de la zone de défilement de l'élément. Selon le diagramme de plage donné ci-dessus, le scrollWidth/scrollHeight du corps doit être plus petit que son offsetWidth/offsetHeight
.2) Les scrollWidth et scrollHeight de docE doivent être égaux aux offsetWidth et offsetHeight de l'élément body, à en juger par les résultats en cours, cela est cohérent, mais la clientWidth de docE est en fait égale à son offsetWidth selon la plage. diagramme, la valeur clientWidth de docE doit être égale à offsetWidth moins la largeur de la barre de défilement.
Les résultats d'exécution des autres navigateurs sont également très différents de ceux de Chrome :
IE11 :
1) L'élément body sous IE11 n'a pas le problème de l'élément body sous chrome
2) L'élément racine HTML sous IE11 a également un problème similaire à Chrome
IE10, IE9 :
1) L'élément body sous IE10 et 9 n'a pas le problème de l'élément body sous chrome
2) L'élément racine html sous IE10 et 9 n'a pas de problèmes similaires à Chrome
firefox : Les résultats d'exécution sont cohérents avec IE11.
opera : Le résultat d'exécution est cohérent avec celui de chrome. C'est peut-être parce que ma version d'opera utilise le même noyau de webkit que chrome.
Il semble que IE9 et IE10 soient les plus normaux. C'est un peu difficile à comprendre. J'ai longtemps cherché en ligne et n'ai trouvé aucune information pertinente pour expliquer ces différences. Au final, je n'ai pu que faire des hypothèses audacieuses. devinez quelques explications. Raisons de ces problèmes :
1) Tout d'abord, le défilement de la page Web entière est différent du défilement des éléments html ordinaires eux-mêmes sont les objets de défilement, mais pour les pages Web, les objets de défilement ne sont pas nécessairement l'élément racine html. ou élément de corps. Parce que lorsque le contenu du corps est vide, la hauteur du corps est de 0 et la hauteur de l'élément racine html est également de 0. Si vous ajoutez un débordement : faites défiler le CSS jusqu'au html ou au corps à ce moment-là, vous verrez que le défilement La barre apparaît toujours sur le côté droit de la fenêtre du navigateur, donc pour le défilement global de la page Web, en théorie, l'objet de défilement doit être la fenêtre, pas l'élément html ou l'élément body ! Mais ce n'est pas le cas, en ce qui concerne les navigateurs testés :
Pour IE10 et IE9, son objet de défilement est l'élément racine html, donc le décalage de leur élément racine html inclura la largeur de la barre de défilement
;Pour les autres navigateurs, l'objet de défilement est window, donc le décalage de leur élément racine html n'inclut pas la largeur de la barre de défilement.
2) Deuxièmement, lorsqu'un élément normal défile, le contenu défilant = sa zone de contenu et sa zone de remplissage. Lorsque la page Web défile dans son ensemble, le contenu défilant doit être l'élément racine html ! Mais ce n'est pas réellement le cas, d'après les navigateurs testés :
Pour IE9, IE10, IE11 et Firefox, leur zone de défilement est l'élément racine HTML, donc scrollWidth et scrollHeight de leur documentElement représentent toujours la taille globale de la zone de défilement de la page Web !
Pour Chrome et Opera, leur objet de défilement est l'élément body, donc les scrollWidth et scrollHeight de leur corps représentent toujours la taille globale de la zone de défilement de la page Web !
3) Troisièmement, le navigateur décrit toujours documentElement.clientWidth et documentElement.clientHeight comme la taille de la zone visible de la page Web à l'exclusion de la barre de défilement, ce qui n'a rien à voir avec le contenu de la page Web !
Les inférences ci-dessus ne sont pas déraisonnables. Prenons l'exemple de l'objet de défilement et de la zone de défilement : si vous souhaitez utiliser js pour faire défiler la page jusqu'à une certaine position dans Chrome, vous devez utiliser window.scrollTo sans l'utiliser. body.scrollTop = xxx à traiter, et le paramètre document.documentElement.scrollTop n'est pas valide, indiquant que la zone de défilement globale de Chrome est déterminée par la zone de défilement du corps et si vous souhaitez utiliser js pour ; faites défiler la page jusqu'à une certaine position sous IE11 et Firefox. Sans utiliser window.scrollTo, document.documentElement.scrollTop = xxx doit être utilisé. Le paramètre document.body.scrollTop n'est pas valide, indiquant que la zone de défilement globale de IE11 et Firefox. est déterminé par la zone de défilement de l'élément racine HTML.
2. Utilisez JS pour obtenir avec précision la taille de l'objet DOM
Les scénarios courants incluent :
1) Obtenez la taille de la zone visible de toute la page Web, hors barres de défilement
2) Obtenez la taille de la page Web entière, y compris la zone de défilement invisible
3) Obtenez la taille d'un élément HTML ordinaire
4) Déterminer si les barres de défilement apparaissent sur les éléments ou les pages Web
5) Calculer la largeur de la barre de défilement
下面针对这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; }
以上就是本文的全部内容,希望能对您有所帮助:)另外本文第二部分提供的代码,是根据个人思考和经验总结出的一些方法,在兼容性方面可能还有未考虑到的地方, 如果您有遇到其它不兼容的情况或者有更好的代码,还请不吝赐教 ,欢迎您的指导。