1、偏移量---offsetjavascript
一、定位父級css
在理解偏移大小以前,首先要理解offsetParent。人們並無把offsetParent翻譯爲偏移父級,而是翻譯成定位父級,很大緣由是offsetParent與定位有關html
定位父級offsetParent的定義------》與當前元素最近的通過定位(position不等於static)的父級元素,主要分爲下列幾種狀況 :java
【1】元素自身有fixed定位,offsetParent的結果爲nullchrome
當元素自身有fixed固定定位時,咱們知道固定定位的元素相對於視口進行定位,此時沒有定位父級,offsetParent的結果爲null瀏覽器
[注意]firefox瀏覽器有兼容性問題佈局
<div id="test" style="position:fixed"></div> <script> //firefox並無考慮固定定位的問題,返回<body>,其餘瀏覽器都返回null console.log(test.offsetParent); </script>
【2】元素自身無fixed定位,且父級元素都未通過定位,offsetParent的結果爲<body>性能
<div id="test"></div>
<script>
console.log(test.offsetParent);//<body>
</script>
【3】元素自身無fixed定位,且父級元素存在通過定位的元素,offsetParent的結果爲離自身元素最近的通過定位的父級元素字體
<div id="div0" style="position:absolute;">
<div id="div1" style="position:absolute;">
<div id='test'></div>
</div>
</div>
<script>
console.log(test.offsetParent); //<div id="div1">
</script>
【4】<body>元素的parentNode是null網站
console.log(document.body.offsetParent);//null
補充:對於定位父級offsetParent來講,IE7-瀏覽器存在如下Bug
【bug1】當元素自己通過絕對定位或相對定位,且父級元素無通過定位的元素時,IE7-瀏覽器下,offsetParent是<html>
<div id="test" style="position:absolute;"></div> <script> //IE7-瀏覽器返回<html>,其餘瀏覽器返回<body> console.log(test.offsetParent); </script><div id="test" style="position:relative;"></div> <script> //IE7-瀏覽器返回<html>,其餘瀏覽器返回<body> console.log(test.offsetParent); </script><div id="test" style="position:fixed;"></div> <script> //firefox並無考慮固定定位的問題,返回<body>,其餘瀏覽器都返回null console.log(test.offsetParent); </script>【bug2】若是父級元素存在觸發 haslayout 的元素或通過定位的元素,即offsetParent的結果爲離自身元素最近的通過定位或觸發haslayout的父級元素
<div id="div0" style="display:inline-block;"> <div id='test'></div> </div> <script> //IE7-瀏覽器返回<div id="div0">,其餘瀏覽器返回<body> console.log(test.offsetParent); </script>
<div id="div0" style="position:absolute;"> <div id="div1" style="display:inline-block;"> <div id='test'></div> </div> </div> <script> //IE7-瀏覽器返回<div id="div1">,其餘瀏覽器返回<div id="div0"> console.log(test.offsetParent); </script>
<div id="div0" style="display:inline-block;"> <div id="div1" style="position:absolute;"> <div id='test'></div> </div> </div> <script> //全部瀏覽器都返回<div id="div1"> console.log(test.offsetParent); </script>
二、4個偏移量【元素 的可見大小由其高度、寬度決定,包括全部內邊距、滾動條和邊框大小(注意,不包括外邊距)】
【1】offsetHeight------元素在垂直方向上佔用的空間大小,以像素計。
offsetHeight = border-top-width + padding-top + height + padding-bottom + border-bottom-width
【2】offsetWidth------元素在水平方向上佔用的空間大小,以像素計。
offsetWidth = border-left-width + padding-left + width + padding-right + border-right-width;
補充:若是存在垂直滾動條,offsetWidth也包括垂直滾動條的寬度;若是存在水平滾動條,offsetHeight也包括水平滾動條的高度
<div id="test" style="width:100px; height:100px; padding:10px; margin:10px; border:1px solid black; overflow: scroll;"></div> <script> //IE8-瀏覽器將垂直滾動條的寬度計算在width寬度和height高度中,width和height的值仍然是100px; //而其餘瀏覽器則把垂直滾動條的寬度從width寬度中移出,把水平滾動條的高度從height高度中移出,則滾動條寬度爲17px,width寬度和height高度爲剩下的83px if(window.getComputedStyle){ console.log(getComputedStyle(test).width,getComputedStyle(test).height)//83px }else{ console.log(test.currentStyle.width,test.currentStyle.height);//100px } console.log(test.offsetWidth,test.offsetHeight);//122=1+10+100+10+1</script>
【3】offsetTop------元素的上外邊框(border-top)至包含元素的上內邊框之間的像素距離
【4】offsetLeft------元素的左外邊框(border-left)至包含元素的左內邊框之間的像素距離
補充:IE7-瀏覽器在offsetTop屬性的處理上存在bug
【1】若父級設置position: relative,則在IE7-瀏覽器下,offsetTop值爲offsetParent元素的paddingBottom值
<div id="out" style="padding: 5px;position: relative;"> <div id="test" style="width:100px; height:100px; margin:10px;"></div> </div> <script> //其餘瀏覽器返回15(5+10),而IE7-瀏覽器返回5 console.log(test.offsetTop); </script>
【2】若父級設置position: aboslute(或其餘觸發haslayout的條件),offsetTop值爲offsetParent元素的paddingBottom值和當前元素的marginTop值的較大值
<div id="out" style="padding: 5px;position:absolute;"> <div id="test" style="width:100px; height:100px; margin:10px;"></div> </div> <script> //其餘瀏覽器返回15(5+10),而IE7-瀏覽器返回10(10和5的較大值) console.log(test.offsetTop); </script>
三、頁面偏移
要知道某個元素在頁面上的偏移量,將這個元素的offsetLeft和offsetTop與其offsetParent的相同屬性相加,並加上offsetParent的相應方向的邊框,如此循環直到根元素,就能夠獲得元素到頁面的偏移量
【注意】在默認狀況下,IE8-瀏覽器下若是使用currentStyle()方法獲取<html>和<body>(甚至普通div元素)的邊框寬度都是medium,而若是使用clientLeft(或clientTop)獲取邊框寬度,則是實際的數值
html,body{border: 0;} body{margin:0;}
function getElementLeft(element){ var actualLeft = element.offsetLeft; var current = element.offsetParent; while(current != null){ actualLeft += current.offsetLeft + current.clientLeft; current = current.offsetParent; } return actualLeft + 'px'; } function getElementTop(element){ var actualTop = element.offsetTop; var current = element.offsetParent; while(current != null){ actualTop += current.offsetTop + current.clientTop; current = current.offsetParent; } return actualTop + 'px'; }
<div style="padding: 20px;border:1px solid black;position:absolute;"> <div id="test" style="width:100px; height:100px; margin:10px;"></div> </div> <script> //其餘瀏覽器返回31(10+20+1),而IE7-瀏覽器返回21((20和10的較大值)+1) console.log(getElementTop(test)); //全部瀏覽器返回31(10+20+1) console.log(getElementLeft(test)); </script>
注意:
一、全部這些偏移量屬性都是只讀的,並且每次訪問它們都須要從新計算。
二、應該儘可能避免重複訪問這些屬性;若是須要重複使用其中某些屬性的值,能夠將它們保存在局部變量中,以提升性能。
三、若是給元素設置了display:none,則它的偏移量屬性都爲0
2、客戶區大小---client
定義:元素內容及其內邊距所佔據的空間大小【即:元素內部的空間大小】
/*滾動條佔用的空間不計算在內*/
<div id="test" style="width: 100px;height: 100px;padding: 10px;margin: 10px;border: 1px solid black;overflow:scroll"></div> <script> //103(120-17),滾動條寬度爲17px console.log(test.clientHeight); console.log(test.clientWidth); </script>
一、4個客戶區大小
【1】clientHeight
clientHeight = padding-top + height + padding-bottom
【2】clientWidth
clientWidth = padding-left + height + padding-right
補充:當height和縱向padding的和爲0(以及小於17px的狀況)時,若是仍然存在滾動條,各瀏覽器表現不同
<div id="test" style="width: 100px;height:0;margin: 10px;border: 1px solid black;overflow:scroll"></div> <script> //chrome/safari:-17(0-17) //firefox/IE:0 console.log(test.clientHeight); </script>
bug:若是設置overflow:scroll,使得滾動條始終存在,當不設置高度height值時,各個瀏覽器表現不同。
一、firefox存在一個最小高度爲34px的垂直滾動條
二、IE7-瀏覽器存在一個最小高度爲19px的垂直滾動條,
三、而其餘瀏覽器的垂直滾動條無最小高度
總結:當clientHeight的值小於34px時,firefox會返回34;當clientHeight的值小於19px時,IE7-會返回19
/*無高度*/
<div id="test" style="width: 100px;margin: 10px;border: 1px solid black;overflow:scroll"></div> <script> //chrome/IE8+/safari:0(由於height和padding都是0) //firefox:34(設置overflow:scroll以後,默認存在一個高34px的垂直滾動條) //IE7-:19(默認存在一個高19px的垂直滾動條) console.log(test.clientHeight); </script>
/*字體大小爲20px*/
<div id="test" style="width: 100px;margin: 10px;border: 1px solid black;font-size:20px;line-height:1;overflow:scroll">內容</div> <script> //chrome/IE8+/safari:20(20*1) //firefox:34(20<34) //IE7-:20(20>19) console.log(test.clientHeight); </script>
/*有padding-top和字體大小*/
<div id="test" style="width: 100px;padding-top:20px;margin: 10px;border: 1px solid black;font-size:20px;line-height:1;overflow:scroll">內容</div> <script> //chrome/IE8+/safari:40(20*1+20) //firefox:40(40>34) //IE7-:40(40>19) console.log(test.clientHeight); </script>
【3】clientLeft-----------返回左邊框的寬度
【4】clientHeight------------返回上邊框的寬度
<div id="test" style="width: 100px;height: 100px;padding: 10px;margin: 10px;border: 1px solid black;"></div> <script> //1 1 console.log(test.clientLeft); console.log(test.clientTop); </script>
【注意】若是display爲inline時,clientLeft屬性和clientTop屬性都返回0
<div id="test" style="display:inline;width: 100px;height: 100px;padding: 10px;margin: 10px;border: 1px solid black;"></div> <script> //0 0 console.log(test.clientLeft); console.log(test.clientTop); </script>
二、頁面大小---肯定瀏覽器 視口大小
【1】document.documentElement的client屬性來表示頁面大小(不包含滾動條寬度)
【注意】在IE7-瀏覽器中,<html>元素默認存在垂直滾動條
<body style="overflow:scroll"> <script> //1903(1920-17) console.log(document.documentElement.clientWidth); //930(947-17) console.log(document.documentElement.clientHeight); </script>
【2】表示頁面大小的屬性是window.innerHeight和innerWidth屬性(包含滾動條寬度)
innerHeight和innerWidth表示的是瀏覽器窗口大小減去菜單欄、地址欄等剩餘的頁面尺寸,因爲滾動條是屬於頁面的,因此包含滾動條
【注意】IE8-瀏覽器不支持innerHeight和innerWidth屬性
<body style="overflow:scroll"> <script> //1920 console.log(window.innerWidth); //947 console.log(window.innerHeight); </script>
【注意】
一、若是沒有滾動條,這兩類屬性在電腦端表示一樣的值,可是卻表示不一樣的含義。在移動端,innerWidth和innerHeight表示的是視覺視口,即用戶正在看到的網站的區域;而document.documentElement.clientWidth和clientHeight表示的是佈局視口,指CSS佈局的尺寸。
二、頁面的客戶區大小和頁面的實際大小是不一樣的,頁面的實際大小將scroll滾動大小來表示
三、全部客戶區client屬性都是隻讀的【IE8-瀏覽器會報錯,其餘瀏覽器則靜默失敗】
四、每次訪問客戶區client屬性都須要從新計算,重複訪問須要耗費大量的性能,因此要儘可能避免重複訪問這些屬性。若是須要重複訪問,則把它們的值保存在變量中,以提升性能
五、若是給元素設置了display:none,則客戶區client屬性都爲0
六、,要肯定瀏覽器視口大小,可使用 document.documentElement 或 document.body(在 IE7 以前的版本中)的 clientWidth 和 clientHeight【肯定瀏覽器是否運行在混雜模式】
function getViewport(){ if (document.compatMode == "BackCompat"){ return { width: document.body.clientWidth, height: document.body.clientHeight }; } else { return { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight }; } }
3、滾動大小----scroll
定義:包含滾動內容的元素的大小
一、4個滾動大小
【1】scrollHeight----在沒有滾動條的狀況下,元素內容的總高度,包括因爲溢出而沒法展現在網頁的不可見部分
【2】scrollWidth-----在沒有滾動條的狀況下,元素內容的總寬度,包括因爲溢出而沒法展現在網頁的不可見部分
【注意】
一、scrollHeight和scrollWidth只可讀
二、scrollWidth 和 scrollHeight 主要用於肯定元素內容的實際大小。
例如,一般認爲元素是在 Web 瀏覽器的視口中滾動的元素(IE6 以前版本運行在混雜模式下時是元素)。所以,帶有 垂直滾動條的頁面總高度就是
document.documentElement.scrollHeight。
三、IE7-瀏覽器返回值是不許確的
【1】沒有滾動條時,scrollHeight與clientHeight屬性結果相等,scrollWidth與clientWidth屬性結果相等
<div id="test" style="width: 100px;height: 100px;padding: 10px;margin: 10px;border: 1px solid black;"></div> <script> //120 120 console.log(test.scrollHeight,test.scrollWidth); //120 120 console.log(test.clientHeight,test.clientWidth); </script>【2】存在滾動條時,但元素設置寬高大於等於元素內容寬高時,scroll和client屬性的結果相等
<div id="test"style="width: 100px;height: 100px;padding:10px;margin:10px;border:1px solid black;overflow:scroll;font-size:20px;line-height:1;"> 內容<br>內容<br> </div> <script> //103(120-17) 103(120-17) console.log(test.scrollHeight,test.scrollWidth); //103(120-17) 103(120-17) console.log(test.clientHeight,test.clientWidth); </script>
【3】存在滾動條,但元素設置寬高小於元素內容寬高,即存在內容溢出的狀況時,scroll屬性大於client屬性
[注意]scrollHeight屬性存在兼容性問題,chrome和safari瀏覽器中,scrollHeight包含padding-bottom;而IE和firefox不包含padding-bottom
<div id="test" style="width:100px;height:100px;padding:10px;margin:10px;border:1px solid black;overflow:scroll;font-size:20px;line-height:200px;"> 內容 </div> <script> //chrome/safari:220(200+10+10) //firefox/IE:210(200+10) console.log(test.scrollHeight); //103(120-17) console.log(test.clientHeight); </script>******************************************************************************************************
對於不包含滾動條的頁面而言, scrollWidth 和 scrollHeight 與 clientWidth 和 clientHeight 之間的關係並不十分清晰。
在這種狀況下,基於document.documentElement 查看 這些屬性會在不一樣瀏覽器間發現一些不一致性問題,以下所述。
一、Firefox 中這兩組屬性始終都是相等的,但大小表明的是文檔內容區域的實際尺寸,而非視口的 尺寸。
二、Opera、Safari 3.1 及更高版本、Chrome 中的這兩組屬性是有差異的,其中 scrollWidth 和 scrollHeight 等於視口大小,而 clientWidth 和 clientHeight 等於文檔內容區域的大小。
三、IE(在標準模式)中的這兩組屬性不相等,其中 scrollWidth 和 scrollHeight 等於文檔內 容區域的大小,而 clientWidth 和 clientHeight 等於視口大小。
總結:在肯定文檔的總高度時(包括基於視口的最小高度時),必須取得 scrollWidth/clientWidth 和 scrollHeight/clientHeight 中的最大值,才能保證在跨瀏覽器的環境下獲得精確的結果。【對於運行在混雜模式下的 IE,則須要用 document.body 代替 document.documentElement。】
var docHeight = Math.max(document.documentElement.scrollHeight,document.documentElement.clientHeight); var docWidth = Math.max(document.documentElement.scrollWidth,document.documentElement.clientWidth);
【3】scrollLeft-----被隱藏在內容區域左側的像素數。元素未滾動時,scrollLeft的值爲0,若是元素被水平滾動了,scrollLeft的值大於0
【4】scrollTop-----被隱藏在內容區域上方的像素數。元素未滾動時,scrollTop的值爲0,若是元素被垂直滾動了,scrollTop的值大於0
一、當滾動條滾動到內容底部時,符合如下等式
scrollHeight == scrollTop + clientHeight
<div id="test" style="width: 100px;height: 100px;padding: 10px;margin: 10px;border: 1px solid black;overflow:scroll;font-size:20px;line-height:200px;"> 內容</div> <button id='btn1'>點擊</button> <div id="result"></div> <script> btn1.onclick = function(){
//scrollTop:0;clientHeight:103;scrollHeight:220 result.innerHTML = 'scrollTop:' + test.scrollTop+';clientHeight:' + test.clientHeight + ';scrollHeight:' + test.scrollHeight } </script>二、scrollLeft和scrollTop是可寫的,scrollLeft和scrollTop賦值爲負值時,並不會報錯,而是靜默失敗
二、頁面尺寸
document.documentElement.clientHeight表示頁面的可視區域的尺寸,而document.documentElement.scrollHeight表示html元素內容的實際尺寸。可是因爲各個瀏覽器表現不同,分爲如下幾種狀況
【1】html元素沒有滾動條時,IE和firefox的client和scroll屬性始終相同,且返回可視區的尺寸大小;而safari和chrome表現正常,clientHeight返回可視區域大小,而scrollHeight返回元素內容大小
//firefox: 755 755 //chrome: 947 8(body元素的margin) //safari: 744 8(body元素的margin) //IE: 768 768 console.log(document.documentElement.clientHeight,document.documentElement.scrollHeight)
【2】html元素存在滾動條時,各個瀏覽器都表現正常。clientHeight返回可視區域大小,而scrollHeight返回元素內容大小
<body style="height:1000px"> <script> //firefox: 755 1016(1000+8*2) //chrome: 947 1016(1000+8*2) //safari: 744 1016(1000+8*2) //IE: 768 1016(1000+8*2) console.log(document.documentElement.clientHeight,document.documentElement.scrollHeight) </script>
兼容
所以要取得文檔實際高度時,要取得<html>元素的scrollHeight和clientHeight的最大值
var docHeight = Math.max(document.documentElement.scrollHeight,document.documentElement.clientHeight); var docWidth = Math.max(document.documentElement.scrollWidth,document.documentElement.clientWidth);
三、頁面滾動
理論上,經過document.documentElement.scrollTop和scrollLeft能夠反映和控制頁面的滾動;可是chrome和safari瀏覽器是經過document.body.scrollTop和scrollLeft來控制的
<body style="height:1000px"> <button id='btn1' style="position:fixed;top:0;">點擊</button> <div id="result" style="position:fixed;top:30px;"></div> <script> btn1.onclick = function(){ result.innerHTML = 'html的scrollTop:' + document.documentElement.scrollTop +';body的scrollTop:' + document.body.scrollTop; } </script> </body>
//頁面的滾動高度兼容寫法是
var docScrollTop = document.documentElement.scrollTop || document.body.scrollTop;
四、回到頂部
function scrollTop(){
if((document.body.scrollTop || document.documentElement.scrollTop) != 0){
document.body.scrollTop = document.documentElement.scrollTop = 0;
}
}
<body style="height:1000px">
<button id='btn' style="position:fixed">回到頂部</button>
<script>
function scrollTop(){
if((document.body.scrollTop || document.documentElement.scrollTop) != 0){
document.body.scrollTop = document.documentElement.scrollTop = 0;
}
}
btn.onclick = scrollTop;
</script>
</body>
4、獲取整個頁面滾動的像素值
【1】pageXOffset-----表示水平方向上頁面滾動的像素值
【2】pageYOffset-----表示垂直方向上頁面滾動的像素值
[注意]IE8-瀏覽器不支持
<body style="height:1000px"> <button id='btn1' style="position:fixed;top:0;">點擊</button> <div id="result" style="position:fixed;top:30px;"></div> <script> btn1.onclick = function(){ result.innerHTML = 'pageYOffset:' + window.pageYOffset; } </script> </body>
5、滾動方法
【1】scrollTo(x,y)----滾動當前window中顯示的文檔,讓文檔中由座標x和y指定的點位於顯示區域的左上角
<body style="height:1000px"> <button id='btn' style="position:fixed">滾動</button> <script> btn.onclick = function(){scrollTo(0,0);} </script>
【2】scrollBy(x,y)-----滾動當前window中顯示的文檔,x和y指定滾動的相對量
<body style="height:1000px"> <button id='btn1' style="position:fixed">向下滾動</button> <button id='btn2' style="position:fixed;top:40px">向上滾動</button> <script> btn1.onclick = function(){scrollBy(0,100);} btn2.onclick = function(){scrollBy(0,-100);} </script>
【小應用】利用scrollBy()加setInterval計時器實現簡單的快速滾動功能
<body style="height:1000px"> <button id='btn1' style="position:fixed">開始滾動</button> <button id='btn2' style="position:fixed;top:40px">中止滾動</button> <script> var timer = 0; btn1.onclick = function(){ timer = setInterval(function(){ scrollBy(0,10); },100)} btn2.onclick = function(){ clearInterval(timer); timer = 0; } </script>
【3】scrollIntoView()滾動當前元素,進入瀏覽器的可見區域
該方法能夠接受一個布爾值做爲參數。若是爲true,表示元素的頂部與當前區域的可見部分的頂部對齊(前提是當前區域可滾動);若是爲false,表示元素的底部與當前區域的可見部分的尾部對齊(前提是當前區域可滾動)。若是沒有提供該參數,默認爲true
<body style="height:1000px"> <div id="test" style="height:100px;width:100px;position:absolute;left:0;top:500px; line-height: 1.5 !important;">></div> <button id='btn1' style="position:fixed">滾動到頁面開頭</button> <button id='btn2' style="position:fixed;top:40px">滾動到頁面結尾</button> <script> btn1.onclick = function(){ test.scrollIntoView(); }; btn2.onclick = function(){ test.scrollIntoView(false); } </script>
【4】scrollIntoViewIfNeeded()
scrollIntoViewIfNeeded(true)方法只在當前元素在視口中不可見的狀況下,才滾動瀏覽器窗口或容器元素,最終讓它可見。若是當前元素在視口中可見,這個方法什麼也不作
若是將可選的alignCenter參數設置爲true,則表示儘可能將元素顯示在視口中部(垂直方向)
[注意]該方法只有chrome和safari支持
<body style="height:1000px"> <div id="test" style="height:100px;width:100px;position:absolute;left:0;top:500px; line-height: 1.5 !important;">></div> <button id='btn' style="position:fixed">滾動到頁面中間</button> <script> btn.onclick = function(){ test.scrollIntoViewIfNeeded(true) }; </script>
【5】scrollByLines(lineCount)
scrollByLines(lineCount)方法將元素的內容滾動指定的行髙,lineCount值能夠是正值, 也能夠是負值
[注意]該方法只有safari支持
<div id="test" style="width:100px;height: 100px;padding:10px;margin: 10px;border: 1px solid black;overflow:scroll;font-size:20px;line-height:200px;"> 內容</div> <button id='btn1'>向下滾動</button> <button id='btn2'>向上滾動</button> <script> btn1.onclick = function(){test.scrollByLines(1);} btn2.onclick = function(){test.scrollByLines(-1);} </script>
【6】scrollByPages(pageCount)
scrollByPages(pageCount)方法將元素的內容滾動指定的頁面高度,具體高度由元素的高度決定
[注意]該方法只有safari支持
<div id="test" style="width:100px;height:100px;padding:10px;margin:10px;border:1px solid black;overflow:scroll;font-size:20px;line-height:200px;"> 內容</div> <button id='btn1'>向下滾動</button> <button id='btn2'>向上滾動</button> <script> btn1.onclick = function(){test.scrollByPages(1);} btn2.onclick = function(){test.scrollByPages(-1);} </script>
6、滾動事件
scroll事件是在window對象上發生的,它表示的是頁面中相應元素的變化。固然,scroll事件也能夠用在有滾動條的元素上
<body style="height:1000px"> <div id="result" style="position:fixed;top:10px;"></div> <script> window.onscroll = function(){ result.innerHTML = '頁面的scrollTop:' + (document.documentElement.scrollTop||document.body.scrollTop); } </script> </body>