码迷,mamicode.com
首页 > 其他好文 > 详细

DOM盒模型

时间:2015-09-29 20:21:54      阅读:269      评论:0      收藏:0      [点我收藏+]

标签:

 

偏移量offset

技术分享

  偏移量包括元素在屏幕上占用的所有可见的空间。元素的可见大小由其高度、宽度决定,包括所有内边距、滚动条和边框大小(注意,不包括外边距)。
    [注意1]所有偏移量属性都是只读的,而且每次访问他们都需要重新计算
    [注意2]若给元素设置了display:none,则它的四个offset属性都为0
【offsetParent】元素的定位父级,(标准浏览器包括IE8下)
  【1】若元素自身是fixed定位,则offsetParent是null
  【2】若元素有进行过CSS定位(relative\absolute\fixed)的父级,则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】自身有定位元素(relative\absolute)
      【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]
    (chrome\safari\opera\IE9+):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盒模型

标签:

原文地址:http://www.cnblogs.com/xiaohuochai/p/4847118.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!