DOM盒模型 – 小火柴的蓝色理想

 

偏移量offset

  偏移量包括元素在屏幕上占用的所有可见的空间。元素的可见大小由其高度、宽度决定,包括所有内边距、滚动条和边框大小(注意,不包括外边距)。
    [注意1]所有偏移量属性都是只读的,而且每次访问他们都需要重新计算
    [注意2]若给元素设置了display:none,则它的四个offset属性都为0
【offsetParent】元素的定位父级,(标准浏览器包括IE8下)
  【1】若元素自身是fixed定位,则offsetParent是null
  【2】若元素有进行过CSS定位(relativeabsolutefixed)的父级,则offsetParent就是在DOM结构中离其最近的进行过CSS定位的父级
  【3】若元素没有进行过CSS定位的父级,则offsetParent是<body>元素
  【4】<body>的offsetParent是null

<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Document</title>
<style>
body
{
margin
: 0;
}
ul
{
margin
: 0;
padding
: 0;
list-style
: none;
}
.box
{
width
: 500px;
height
: 500px;
background-color
: gray;
}
.list
{
height
: 300px;
width
: 300px;
background-color
: #ccc;
border
: 10px solid black;
}
.in
{
height
: 100px;
width
: 100px;
background-color
: red;
margin
: 10px;
padding
: 10px;
border
: 1px solid black;
}
</style>
</head>
<body>
<div class=”box” id=”box”>
<ul class=”list” id=”list”>
<li class=”in” id=”test”>test</li>
</ul>
</div>
<body>
<script>
var oBox = document.getElementById(box);
var oList = document.getElementById(list);
var oTest = document.getElementById(test);
//<body>的定位父级是null
console.log(document.body.nodeName);
//没有进行CSS定位的父级,所以定位父级是<body>
console.log(oList.offsetParent.nodeName);
//没有进行CSS定位的父级,所以定位父级是<body>
console.log(oTest.offsetParent.nodeName);
document.onclick
= function(){
oList.style.position
= relative;
//自身有定位,但父级中没有进行CSS定位的,所以定位父级是<body>
console.log(oList.offsetParent.nodeName);
//oList是oText的进行过CSS定位的父级,所以其定位父级是oList
console.log(oTest.offsetParent.nodeName);
}
</script>
</body>
</html>

 

  【IE7-浏览器bug】
    【1】自身有定位元素(relativeabsolute)
      【1.1】若无进行过定位的父级元素,则offsetParent是<html>
      【1.2】若有进行过定位的父级元素,则offsetParent是进行过定位的父级元素
    【2】自身无定位元素(触发haslayout的父元素也具有进行过定位的父级的特征)[与标准相同]
      【1.1】若无进行过定位的父级元素,则offsetParent是<body>
      【1.2】若有进行过定位的父级元素,则offsetParent是进行过定位的父级元素

 

【offsetHeight】元素在垂直方向上占用的空间大小,以像素计。包括元素的高度、(可见的)水平滚动条的高度、上边框高度和下边框高度。
【offsetWidth】元素在水平方向上占用的空间大小,以像素计。包括元素的宽度、(可见的)垂直滚动条的宽度、左边框宽度和右边框宽度。
  [注意]即使元素加上水平或垂直滚动条,offsetWidth跟offsetHeight的值是不会更改的,因为浏览器渲染时把滚动条的宽度(或高度)算在了元素本身的宽度(或高度)中了
【offsetLeft】元素的左外边框至包含元素的左内边框之间的像素距离
【offsetTop】元素的上外边框至包含元素的上内边框之间的像素距离
  其中offsetLeft和offsetTop属性与包含元素有关,包含元素的引用保存在offsetParent属性中。offsetParent属性不一定与parentNode的值相等。例如<td>元素的offsetParent是作为其祖先元素的<table>元素,因为<table>是在DOM层次中距<td>最近的一个具有大小的元素

<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Document</title>
<style>
body
{
margin
: 0;
}
ul
{
margin
: 0;
padding
: 0;
list-style
: none;
}
.list
{
height
: 500px;
width
: 500px;
background-color
: #ccc;
border
: 10px solid black;
}
.in
{
height
: 100px;
width
: 100px;
background-color
: red;
margin
: 100px;
padding
: 100px;
border
: 1px solid black;
}
</style>
</head>
<body>
<ul class=”list” id=”list”>
<li class=”in” id=”test”>test</li>
</ul>
<script>
var oList = document.getElementById(list);
var oTest = document.getElementById(test);
//302px 302px
console.log(oTest.offsetWidth,oTest.offsetHeight);
//110px 110px,而IE7-浏览器输出100px
console.log(oTest.offsetTop,oTest.offsetLeft);
document.onclick
= function(){
oTest.style.overflow
= scroll;
//加入滚动条后,值依然不发生改变
console.log(oTest.offsetWidth,oTest.offsetHeight);
console.log(oTest.offsetTop,oTest.offsetLeft);
}
</script>
</body>
</html>

 

  【firefox的bug】
    当自身有定位元素,有定位父级,且定位父级设置overflow:hidden时,火狐的offsetLeft会减去定位父级相应方向的边框的宽度。

<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Document</title>
<style>
body
{
margin
: 0;
}
ul
{
margin
: 0;
padding
: 0;
list-style
: none;
}
.list
{
height
: 500px;
width
: 500px;
background-color
: #ccc;
border
: 10px solid black;
border-left-width
: 5px;
}
.in
{
height
: 100px;
width
: 100px;
background-color
: red;
margin
: 100px;
padding
: 100px;
border
: 1px solid black;
}
</style>
</head>
<body>
<ul class=”list” id=”list”>
<li class=”in” id=”test”>test</li>
</ul>
<script>
var oList = document.getElementById(list);
var oTest = document.getElementById(test);
document.onclick
= function(){
oList.style.position
= relative;
oList.style.overflow
= hidden;
oTest.style.position
= absolute;
//其他浏览器都输出100 100 而firefox浏览器输出 90 95
console.log(oTest.offsetTop,oTest.offsetLeft);
}
</script>
</body>
</html>

 

  要知道某个元素在页面上的偏移量,将这个元素的offsetLeft和offsetTop与其offsetParent的相同属性相加,并加上offsetParent的相应方向的边框,如此循环直到根元素,就可以得到元素到页面的偏移量。
    [注意]在默认情况下,IE8-浏览器下<html>和<body>的边框宽度都是medium,而其他浏览器是0px。
    兼容写法如下:

html,body{
border: 0;
}
function getElementLeft(element){
var actualLeft = element.offsetLeft;
var current = element.offsetParent;
while(current != null){
actualLeft
+= current.offsetLeft + parseFloat(getCSS(current,’border-left-width’));
current
= current.offsetParent;
}
return actualLeft + ‘px’;
}
function getElementTop(element){
var actualTop = element.offsetTop;
var current = element.offsetParent;
while(current != null){
actualTop
+= current.offsetTop + parseFloat(getCSS(current,’border-top-width’));
current
= current.offsetParent;
}
return actualTop + ‘px’;
}
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Document</title>
<style>
html,body
{
border
: 0;
}
body
{
margin
: 0;
}
ul
{
margin
: 0;
padding
: 0;
list-style
: none;
}
.list
{
height
: 500px;
width
: 500px;
background-color
: #ccc;
border
: 10px solid black;
}
.in
{
height
: 100px;
width
: 100px;
background-color
: red;
margin
: 100px;
padding
: 100px;
border
: 1px solid black;
}
</style>
</head>
<body>
<ul class=”list” id=”list”>
<li class=”in” id=”test”>test</li>
</ul>
<script>
var oList = document.getElementById(list);
var oTest = document.getElementById(test);
function getCSS(obj,attr){
if(window.getComputedStyle){
return getComputedStyle(obj)[attr];
}
return obj.currentStyle[attr];
}
function getElementLeft(element){
var actualLeft = element.offsetLeft;
var current = element.offsetParent;
while(current != null){
actualLeft
+= current.offsetLeft + parseFloat(getCSS(current,border-left-width));
current
= current.offsetParent;
}
return actualLeft + px;
}
function getElementTop(element){
var actualTop = element.offsetTop;
var current = element.offsetParent;
while(current != null){
actualTop
+= current.offsetTop + parseFloat(getCSS(current,border-top-width));
current
= current.offsetParent;
}
return actualTop + px;
}
oList.style.position
= absolute;
console.log(getElementTop(oTest));
//所有浏览器都输出110px
console.log(getElementLeft(oTest));//所有浏览器都输出110px
</script>
</body>
</html>

 

客户区大小client  

  元素的客户区大小(client dimension)指的是元素内容及其内边距所占据的空间大小。
    [注意1]若设置为display:none,则值为0
    [注意2]客户区大小是只读的,每次访问都要重新计算

 

【属性】
  有关客户区大小的属性有两个:clientWidth和clientHeight。其中,clientWidth属性是元素内容区宽度+左右内边距宽度。clientHeight属性是元素内容区高度+上下内边距高度。

 

【常用应用】确定浏览器视口大小
  [注意]IE6浏览器在标准模式下,视口大小与<html>大小一致;在怪异模式下,视口大小与<body>大小一致。所以兼容写法为:

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
};
}
}
<!DOCTYPE HTML>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Document</title>
<body>
<script>
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
};
}
}
//IE7-浏览器返回1895,因为默认有滚动条(可得出滚动条宽度为21px),IE8浏览器返回1916,其他浏览器返回1920
console.log(getViewport().width)
</script>
</body>
</html>

 

滚动大小scroll

  滚动大小是指包含滚动内容的元素的大小。有些元素(如html元素)即使没有执行任何代码也能自动添加滚动条;但另外一些元素,则需要通过CSS的overflow属性进行设置才能滚动。

 

【scrollHeight和scrollWidth】
  【scrollHeight】在没有滚动条的情况下,元素内容的总高度
  【scrollWidth】在没有滚动条的情况下,元素内容的总宽度
    [注意]scrollWidth和scrollHeight主要用于确定元素内容的实际大小。通常认为<html>元素就是在Web浏览器的视口中滚动的元素。因此,带有垂直滚动条的页面总高度就是document.documentElement.scrollHeight

 

【scroll和client的区别】
  【1】在有滚动条的情况下,scorllHeight表示元素的实际总高度,而clientHeight表示元素的视觉总高度(宽度也类似)

<!DOCTYPE HTML>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Document</title>
<style>
.box
{
height
: 100px;
width
: 200px;
overflow
: scroll;
}
</style>
<body>
<div class=”box” id=”box”>
我是测试内容
<br>
我是测试内容
<br>
我是测试内容
<br>
我是测试内容
<br>
我是测试内容
<br>
我是测试内容
<br>
我是测试内容
<br>
我是测试内容
<br>
我是测试内容
<br>
</div>
<script>
var oBox = document.getElementById(box);
//100 162
console.log(oBox.clientHeight,oBox.scrollHeight);
//183 183
console.log(oBox.clientWidth,oBox.scrollWidth);
</script>
</body>
</html>

 

<!DOCTYPE HTML>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Document</title>
<style>
html
{
height
: 2000px;
}
</style>
<body>
<script>
//500 2000
console.log(document.documentElement.clientHeight,document.documentElement.scrollHeight);
//1899 1899(IE9+及其他浏览器,说明滚动条的宽度为1920-1899=21px)
//
1895(IE8-浏览器)
console.log(document.documentElement.clientWidth,document.documentElement.scrollWidth);
</script>
</body>
</html>

 

  【2】在无滚动条的情况下,各浏览器的处理不一致
    【2.1】页面有高度时
    [a]firefox和IE8+浏览器中<html>的scrollHeight和clientHeight=可视区高度,<body>的scrollHeight和clientHeight=内容实际高度
    [b]chrome、opera、safari中<html>scrollHeight=内容实际高度,clientHeight=可视区高度;而<body>中scrollHeight=可视区高度,clientHeight=内容实际高度

<!DOCTYPE HTML>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Document</title>
<style>
body
{
margin
: 0;
line-height
: 20px;
}
</style>
<body>
<br>
<script>
//(firefox/IE8+)500 500
//
(chrome/IE7-/safari/opera)500 20
console.log(document.documentElement.clientHeight,document.documentElement.scrollHeight);
//(firefox/IE8+/IE7-)20 20
//
(chrome/safari/opera)20 500
console.log(document.body.clientHeight,document.body.scrollHeight);
</script>
</body>
</html>

 

    【2.2】页面无高度时
    [a]firefox和IE浏览器中<html>clientHeight=scrollHeight=当前可视区高度,<body>的clientHeight=scrollHeight=0
    [b]chrome、opera、safari中,<html>clientHeight=当前可视区高度,scrollHeight=0;<body>clientHeight=0,scrollHeight=当前可视区高度

<!DOCTYPE HTML>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Document</title>
<style>
body
{
margin
: 0;
}
</style>
<body>
<script>
//(firefox/IE/)500 500
//
(chrome/safari/opera)500 0
console.log(document.documentElement.clientHeight,document.documentElement.scrollHeight);
//(firefox/IE8)0 0
//
(chrome/safari/opera)0 500
console.log(document.body.clientHeight,document.body.scrollHeight)
</script>
</body>
</html>

 

    【2.3】元素无滚动条时
    [a]IE7-浏览器的可视高为设置的高度,而滚动高为子元素的实际高度
    [b]其他浏览器的可视高等于滚动高都等于设置的高度

<!DOCTYPE HTML>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Document</title>
<style>
.box
{
height
: 100px;
}
</style>
<body>
<div class=”box” id=”box”>
12440
<br>
12440
<br>
12440
<br>
</div>
<script>
var oBox = document.getElementById(box);
//IE7-浏览器的可视高为设置的高度100,而滚动高为子元素的实际高度57
//
其他浏览器的可视高等于滚动高都等于100
console.log(oBox.clientHeight,oBox.scrollHeight);
</script>
</body>
</html>

 

   因此要取得文档实际高度时,要取得<html>元素的scrollHeight和clientHeight的最大值

var docHeight = Math.max(document.documentElement.scrollHeight,document.documentElement.clientHeight);
var docWidth = Matn.max(document.documentElement.scrollWidth,document.documentElement.clientWidth);

 

【scrollLeft和scrollTop】
  通过scrollLeft和scrollTop属性既可以确定元素当前滚动的状态,也可以设置元素的滚动位置。

  【scrollLeft】被隐藏在内容区域左侧的像素数。元素未滚动时,scrollTop的值为0,如果元素被水平滚动了,scrollLeft的值大于0,且表示元素左侧不可见内容的像素宽度。
  【scrollTop】被隐藏在内容区域上方的像素数。元素未滚动时,scrollTop的值为0,如果元素被垂直滚动了,scrollTop的值大于0,且表示元素上方不可见内容的像素宽度。

  【页面滚动条的兼容】
    对于firefox及IE浏览器,使用document.documentElement.scrollTop可获得页面的滚动高度
    对于chrome、safari、opera基于webkit的浏览器,使用document.body.scrollTop可获得页面的滚动高度
    所以兼容写法是

var docScrollTop = document.documentElement.scrollTop || document.body.scrollTop
<!DOCTYPE HTML>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Document</title>
<style>
body
{
margin
: 0;
line-height
: 2000px;
}
</style>
<body>
<br>
<script>
document.onclick
= function(){
document.title
= (document.documentElement.scrollTop || document.body.scrollTop);
}
</script>
</body>
</html>

 

元素大小getBoundingClientRect()

  getBoundingClineRect()方法返回一个矩形对象,各个浏览器返回的对象包含的属性不相同
    (firfox):top/left/right/bottom/width/height/x/y[x=left,y=top]
    (chromesafarioperaIE9+):top/left/right/bottom/width/height
    (IE8-):top/left/right/bottom
  [注意1]该方法的所有属性值都没有单位,且给定的是元素在页面中相对于视口的位置
  [注意2]IE7-浏览器认为视口的左上角坐标是(2,2),其他浏览器则将(0,0)作为起点坐标。
  兼容写法:(利用IE7-浏览器中特性节点的specified属性)

function getBoundingClientRect(obj){
var temp = obj.getBoundingClientRect();
//IE7-浏览器
if(Boolean(obj.attributes[0]) && !obj.attributes[0].specified){
return{
left: temp.left
-2,
top: temp.top
-2,
right: temp.right
-2,
bottom: temp.bottom
-2
}
}
else{
return temp;
}
}
<!DOCTYPE HTML>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Document</title>
<style>
body
{
margin
: 0;
line-height
: 50px;
}
.box
{
width
: 100px;
height
: 100px;
padding
: 10px;
border
: 1px solid black;
background-color
: lightgreen;
}
</style>
<body>
<div>
测试内容
<br>
测试内容
<br>
测试内容
<br>
测试内容
<br>
测试内容
<br>
</div>
<div class=”box” id=”box”></div>
<div>
测试内容
<br>
测试内容
<br>
测试内容
<br>
测试内容
<br>
测试内容
<br>
</div>
<script>
var oBox = document.getElementsByTagName(div)[1];
function getBoundingClientRect(obj){
var temp = obj.getBoundingClientRect();
//IE7-浏览器
if(Boolean(obj.attributes[0]) && !obj.attributes[0].specified){
return{
left: temp.left
2,
top: temp.top
2,
right: temp.right
2,
bottom: temp.bottom
2
}
}
else{
return temp;
}
}
document.onclick
= function(){
console.log(getBoundingClientRect(oBox).top,document.body.scrollTop);
}
</script>
</body>
</html>

 

      

  

本文链接:DOM盒模型,转载请注明。



You must enable javascript to see captcha here!

Copyright © All Rights Reserved · Green Hope Theme by Sivan & schiy · Proudly powered by WordPress

无觅相关文章插件,快速提升流量