第十二章:DOM2 和 DOM3(样式)
2017-05-02 16:28
309 查看
DOM2 和 DOM3
样式
访问元素的样式
DOM样式属性和方法
计算的样式
操作样式表
CSSRule
创建规则
删除规则
元素大小
偏移量
客户区大小
滚动大小
确定元素大小
- 有个属性需要注意,那就是float。在JS中float是保留字,因此不能做属性名(书上原话)。经过前面的阅读可知,使用保留字未必会发生错误,也许最新的浏览器都已经可以使用float了。实验下来结果如下:
只要取得一个有效的DOM元素的引用,就可以随时通过JavaScript为其设置样式。
通过style对象同样可以取得在style特性中指定的样式
如果没有为元素设置style特性,那么style对象中可能包含一些默认的值,但这些值并不能反映该元素的特性。
cssText:返回style特性中的css代码
length:应用给元素的CSS属性的数量
parentRule:表示CSS信息的CSSRule对象(后续讨论)。
getPropertyCSSValue(propertyName):返回包含给定属性值的CSSValue对象(后续讨论)。
getPropertyPriority(propertyName):如果给定的属性使用了!important设置(提高指定CSS样式规则的应用优先权),则返回”important”,否则返回空字符串。
getPropertyValue(propertyName):返回给定属性的字符串值
item(index):返回给定位置的CSS属性的名称(等同方括号语法,不过返回的是名称而不是值)
removeProperty(propertyName):删除属性
setProperty(propertyName,value,priority):添加或设置属性,并加上优先权标志(”important”或”“)
来看下面的例子
书上说了一些getPropertyCSSValue(propertyName)和getPropertyValue(propertyName)的区别。后者只返回属性值的字符串表示。而前者返回一个包含两个属性的CSSValue对象,这两个属性分别是cssText和cssValueType。其中cssText属性的值和getPropertyValue(propertyName)获得的字符串相同,而cssValueType属性则是一个数值常量。0表示继承,1表示基本的值,2表示值列表,3表示自定义的值。书上说IE 9+、Safari 3+、Chrome支持这个方法?!反正我测试是not a function。这里就不再过多研究了。
结果非常地怪异,真是难以理解。在Chrome中怎么蹦出了一个小数(后来过了几天我又试了一下,结果居然正确了(不再显示小数),我这几天刚刚更新了Chrome的版本,难道是最近刚刚修复了这个bug?)?IE9中的border属性怎么没有了?也许以后我可能会知道,但是我现在的确想不出来。不过总的来说有两点,1是会得到该元素最终的样式信息对象(重写会覆盖)。2是没有设置的属性会有默认值(比如float属性,虽然IE中出现了undefined,但是Chrome中是none)
更神奇的是,书上居然说IE不支持getComputedStyle()方法(应该是笔误,是指IE8-不支持,也有可能是因为我看的是盗版的书)。
CSSStyleSheet继承自StyleSheet。从StyleSheet接口继承而来的属性如下:
disabled:表示样式表是否禁用(可读写)。设置为true可以禁用样式表。
href:如果样式表是通过
media:当前样式表支持的所有媒体类型的集合。这个集合也有length属性和item()方法,也可以通过方括号语法取得集合中的项。如果集合是空列表,表示适用于所有媒体。在IE中,media是一个反映
ownerNode:指向拥有当前样式表的节点的指针(一般是
13141
。如果样式表是其他样式表通过@import导入的,则这个值为null。IE不支持该属性。
parentStyleSheet:如果当前样式表是通过@import导入的,则这个属性指向导入它的样式表的指针。
title:title属性的值。
type:表示样式表类型的字符串。对CSS样式表而言,这个字符串是”type/css”。
上面都是继承而来的属性和方法,另外CSSStyleSheet类型还支持以下属性和方法:
cssRules:样式表包含的样式规则的集合。IE8-不支持这个属性,但IE都有一个类似的rules属性。
ownerRule:如果样式表是@import导入的,这个属性就是一个指针,指向表示导入的规则;否则为null。IE8-不支持这个属性。
deleteRule(index):删除cssRules集合中指定位置的规则。IE8-不支持这个方法,但IE都支持一个类似的removeRule(index)。
insertRule(rule, index):向cssRules集合中指定的位置插入rule字符串。IE8-不支持这个方法,但IE都支持一个类似的addRule()方法。
应用于文档的所有样式表是通过document.styleSheets集合表示的。同样也有length和item()。
也可以直接通过元素节点的sheet属性获得CSSStyleSheet对象。IE8-不支持该属性,IE8-仅支持styleSheet属性。IE9+后两个属性都支持。
下面是一个关于CSSRule的例子:
cssText:返回整条规则对应的文本。书上老说IE不支持,我发现IE9+都支持的。而不同浏览器的返回值可能有小区别(大小写)。
parentRule:如果当前规则是导入规则,这个属性引用的就是导入规则;否则这个值为null。
parentStyleSheet:当前规则所属的样式表。
selectorText:返回当前规则的选择符文本(比如body)。Opera允许修改该属性,其余浏览器该属性只读。
style:一个CSSStyleDeclaration对象(刚开始已经详细介绍过了),可以通过它设置和取得规则中特定的样式值。
type:表示规则类型的常量值。对于样式规则,这个值是1。
其中最常用的属性是cssText、selectorText和style。cssText属性与style.cssText属性类型。但前者包含选择符和花括号,后者只有花括号里面的内容。此外cssText是只读的,而style.cssText可以被重写。
offsetHeight:元素在垂直方向上占用的空间大小,以像素计。包括元素的高度、(可见的)水平滚动条的高度、上边框高度和下边框高度。
offsetWidth:元素在水平方向上占用的空间大小,以像素计。包括元素的宽度、(可见的)垂直滚动条的宽度、左边框和右边框宽度。
offsetLeft:元素的左外边框至包含元素的左内边框的像素距离。
offsetTop:元素的上外边框至包含元素的上内边框的像素距离。
其中offsetLeft和offsetTop和包含元素有关,包含元素的引用保存在offsetParent属性中。offsetParent不一定与parentNode的值相等。例如
如果想要知道某个元素在页面上的偏移量,只要将这个元素的offsetLeft和offsetTop与其offsetParent的相同属性相加,直至到根元素为止,就可以得到一个准确的值。
要注意这4个属性是只读的。并且每次访问他们都需要重新计算(至于为什么访问值也会计算,想想访问器属性就知道了)。应该尽量避免重复访问这些属性。如果需要重复使用,可以保存在局部变量中,不过要在距离不会修改的前提下。
获得页面视口大小,可以通过document.documentElement(即文档节点)的clientWidth和clientHeight属性。IE7之前的版本中得使用document.body的这两个属性去获取。
这两个属性也是只读的,每次访问都会重新计算。
scrollHeight:在没有滚动条的情况下,元素内容的总高度。
scrollWidth:在没有滚动条的情况下,内容的总宽度。
scrollLeft:被隐藏在内容区域左侧的像素数,通过设置这个属性可以改变元素的滚动位置。
scrollTop:同理,被隐藏在内容区域上册的像素数,通过设置这个属性可以改变元素的滚动位置。
scrollHeight和scrollWidth主要用于确定元素内容的实际大小。例如带有垂直滚动条的页面总高度为document.documentElement.scrollHeight。(在IE7之前为document.body.scrollHeight,因为IE7以前的版本将body元素视为浏览器的视口中的元素)
而对于不包含滚动条的页面,scrollWidth、scrollHeight、clientWidth和clientHeight之间的关系并不十分清晰。我们对同一个页面获取document.documentElement的这些属性,见上面的showWindow()函数。
上面的这个方法创建了一个div元素并获取它的坐标信息。然后将offset保存在该方法中,下次调用则直接使用offset变量。
注意到上面用到了arguments.callee属性,该属性在严格模式下是不能使用的。我们可以使用命名函数表达式的写法去完成(直接写成getBoundingClientRect耦合性太高)。
样式
访问元素的样式
DOM样式属性和方法
计算的样式
操作样式表
CSSRule
创建规则
删除规则
元素大小
偏移量
客户区大小
滚动大小
确定元素大小
DOM2 和 DOM3
样式
在HTML中定义样式的方式有3种:通过<link/>元素包含外部样式表文件,通过
<style>元素定义嵌入式样式,以及使用style特性定义针对特定元素的样式。DOM Level 2 Style围绕这3个应用样式的机制提供了一套API。可以用下列代码确定浏览器是否支持DOM Level 2 Style。
var supportsDOM2CSS = document.implementation.hasFeature("CSS", "2.0"); var supportsDOM2CSS2 = document.implementation.hasFeature("CSS2", "2.0");
访问元素的样式
任何支持style特性的HTML元素在JavaScript中都有一个对应的style属性。这个style对象是CSSStyleDeclaration的实例,包含这通过HTML的style特性指定的所有样式信息,但不包含与外部样式表或嵌入样式表经层叠而来的样式。在style特性中指定的任何CSS属性都将表现为这个style对象的相应属性。对于有短划线的CSS属性名,必须将其转换为驼峰大小写形式。CSS属性 | JavaScript属性 |
---|---|
background-image | style.backgroundImage |
color | style.color |
display | style.display |
font-family | style.fontFamily |
<div id="myDiv" style="float: left"></div> <script type="text/javascript"> var div = document.getElementById("myDiv"); console.log(div.style.float);//IE9、8:left Chrome:left console.log(div.style.cssFloat);//IE9:left IE8:undefined Chrome:left console.log(div.style.styleFloat);//IE9、8:left Chrome:undefined </script>
只要取得一个有效的DOM元素的引用,就可以随时通过JavaScript为其设置样式。
<div id="myDiv" style="float: left">1</div> <script type="text/javascript"> var div = document.getElementById("myDiv"); div.style.backgroundColor = "red"; div.style.width = "100px";//在混杂模式下不加px后缀没关系,在标准模式下会失效。 div.style.height = "200px"; </script>
通过style对象同样可以取得在style特性中指定的样式
<div id="myDiv" style="float: left;background-color: red;">1</div> <script type="text/javascript"> var div = document.getElementById("myDiv"); alert(div.style.backgroundColor);//red alert(div.style.float);//left </script>
如果没有为元素设置style特性,那么style对象中可能包含一些默认的值,但这些值并不能反映该元素的特性。
<!DOCTYPE html> <html> <head> <title>DOM Level 2 IFrame Example</title> <style> #myDiv { background-color: red; } </style> </head> <body> <div id="myDiv" style="float: left">1</div> <script type="text/javascript"> var div = document.getElementById("myDiv"); alert(div.style.backgroundColor);//"" 而不是"red" </script> </body> </html>
DOM样式属性和方法
下面是DOM Level 2 style规范为style对象定义的属性和方法:cssText:返回style特性中的css代码
length:应用给元素的CSS属性的数量
parentRule:表示CSS信息的CSSRule对象(后续讨论)。
getPropertyCSSValue(propertyName):返回包含给定属性值的CSSValue对象(后续讨论)。
getPropertyPriority(propertyName):如果给定的属性使用了!important设置(提高指定CSS样式规则的应用优先权),则返回”important”,否则返回空字符串。
getPropertyValue(propertyName):返回给定属性的字符串值
item(index):返回给定位置的CSS属性的名称(等同方括号语法,不过返回的是名称而不是值)
removeProperty(propertyName):删除属性
setProperty(propertyName,value,priority):添加或设置属性,并加上优先权标志(”important”或”“)
来看下面的例子
<div id="myDiv" style="float:left;background-color: red;">1</div> <script type="text/javascript"> var div = document.getElementById("myDiv"); //冒号后面的空格会被设置为1个。无论原格式如何,可见内部进行过解析。 console.log(div.style.cssText);//"float: left; background-color: red;" //重写cssText,会移除原有属性,重新添加属性。 div.style.cssText = "float:right"//省略分号 console.log(div.style.cssText);//"float: right;" 不再保留background-color属性,且结果同样也多了空格和分号 //length的作用主要是拿来遍历 var test_div = document.createElement("div"); test_div.style.cssText = "width: 25px; height: 100px; background-color: red;"; console.log(test_div.style.length);//3 for (var i=0, len=test_div.style.length; i<len; i++) { console.log(test_div.style[i]);//等价于 test_div.style.item(i)。 // 这里和普通的方括号语法不同地方是,在这里会返回propertyName而不是value。注意此时取到的不是驼峰命名! } console.log(test_div.style["width"]);//另外一种方括号用法,等价于test_div.style.getPropertyValue("width") console.log(test_div.style.getPropertyValue("width"));//同上 //console.log(test_div.style.getPropertyCSSValue("width")); //IE、Chrome 没有这个方法 console.log(test_div.style.parentRule); //null 目前还不知道有什么用 console.log(test_div.style.getPropertyPriority("width"));//"" test_div.style.setProperty("width", "50px", "important"); console.log(test_div.style.cssText);//"width: 50px !important; height: 100px; background-color: red;" console.log(test_div.style.getPropertyPriority("width"));//"important" test_div.style.removeProperty("width"); console.log(test_div.style.cssText);//"height: 100px; background-color: red;" </script>
书上说了一些getPropertyCSSValue(propertyName)和getPropertyValue(propertyName)的区别。后者只返回属性值的字符串表示。而前者返回一个包含两个属性的CSSValue对象,这两个属性分别是cssText和cssValueType。其中cssText属性的值和getPropertyValue(propertyName)获得的字符串相同,而cssValueType属性则是一个数值常量。0表示继承,1表示基本的值,2表示值列表,3表示自定义的值。书上说IE 9+、Safari 3+、Chrome支持这个方法?!反正我测试是not a function。这里就不再过多研究了。
计算的样式
所谓计算的样式,就是元素最终的样式!前面提到的关于style对象的一些方法和属性只能够获得style特性下的样式信息,它并不包含那些从其他样式层叠而来并影响当前元素的样式信息。DOM Level 2 Style增强了document.defaultView,提供了getComputedStyle()方法。该方法接收2个参数,第一个参数是需要取得计算样式的元素,第二个参数是一个伪元素字符串(例如”:after”,这个概念涉及其他知识:伪元素)。该方法同样也返回一个CSSStyleDeclaration对象(与style属性的类型相同),我们可以根据这个对象获得计算后的样式信息。<!DOCTYPE html> <html> <head> <title>Computed Styles Example</title> <style type="text/css"> #myDiv { background-color: blue; width: 100px; height: 200px; } </style> <script type="text/javascript"> function showComputedStyles(){ var myDiv = document.getElementById("myDiv"); var computedStyle = document.defaultView.getComputedStyle(myDiv, null); //前者Chrome 后者IE9 console.log(computedStyle.backgroundColor); //"rgb(255, 0, 0)" console.log(computedStyle.width); //"99.9844px" "100px" console.log(computedStyle.height); //"199.992px" "200px" console.log(computedStyle.border); //"1.5px solid rgb(0, 0, 0)" "" console.log(computedStyle.borderLeftWidth); //"1.5px" "1px" console.log(computedStyle.visibility); //visible console.log(computedStyle.float); //none undefined } </script> </head> <body> <div id="myDiv" style="background-color: red; border: 1px solid black"></div> <input type="button" value="Show Computed Styles" onclick="showComputedStyles()"> <p>(This example won't work in IE < 9.)</p> </body> </html>
结果非常地怪异,真是难以理解。在Chrome中怎么蹦出了一个小数(后来过了几天我又试了一下,结果居然正确了(不再显示小数),我这几天刚刚更新了Chrome的版本,难道是最近刚刚修复了这个bug?)?IE9中的border属性怎么没有了?也许以后我可能会知道,但是我现在的确想不出来。不过总的来说有两点,1是会得到该元素最终的样式信息对象(重写会覆盖)。2是没有设置的属性会有默认值(比如float属性,虽然IE中出现了undefined,但是Chrome中是none)
更神奇的是,书上居然说IE不支持getComputedStyle()方法(应该是笔误,是指IE8-不支持,也有可能是因为我看的是盗版的书)。
//替换上面例子中的方法 function showComputedStyles(){ var myDiv = document.getElementById("myDiv"); //IE 中支持currentStyle属性,返回一个CSSStyleDeclaration实例 var computedStyle = myDiv.currentStyle; alert(computedStyle.backgroundColor); //"red" alert(computedStyle.width); //"100px" alert(computedStyle.height); //"200px" //IE 不返会border样式,因为这个是一个综合属性(主要看浏览器心情) //border指定了border-left-width、border-top-width等等属性 alert(computedStyle.border); //undefined IE8之前 alert(computedStyle.border == ""); //IE9之后变成了空字符串 alert(computedStyle.borderLeftWidth); //"1px" }
操作样式表
CSSStyleSheet 类型表示的是样式表,包括通过<link>元素包含的样式表和在
<style>元素中定义的样式表,这两个元素本身是由HTMLLinkElement和HTMLStyleElement类型表示的。CSSStyleSheet类型只表示样式表,而不管这些样式表在HTML中是如何定义的。HTMLLinkElement和HTMLStyleElement类型是允许修改HTML特性,但CSSStyleSheet对象则是一套只读的接口(有一个属性disabled除外)。使用下面的代码可以确定浏览器是否支持DOM 2级样式表。
var supportsDOM2StyleSheet = document.implementation.hasFeature("StyleSheets", "2.0");
CSSStyleSheet继承自StyleSheet。从StyleSheet接口继承而来的属性如下:
disabled:表示样式表是否禁用(可读写)。设置为true可以禁用样式表。
href:如果样式表是通过
<link>元素包含的,则是样式表的URL,否则是null。
media:当前样式表支持的所有媒体类型的集合。这个集合也有length属性和item()方法,也可以通过方括号语法取得集合中的项。如果集合是空列表,表示适用于所有媒体。在IE中,media是一个反映
<link>和
<style>元素中media特性的字符串。
ownerNode:指向拥有当前样式表的节点的指针(一般是
<link>或
<style>元素节点)
13141
。如果样式表是其他样式表通过@import导入的,则这个值为null。IE不支持该属性。
parentStyleSheet:如果当前样式表是通过@import导入的,则这个属性指向导入它的样式表的指针。
title:title属性的值。
type:表示样式表类型的字符串。对CSS样式表而言,这个字符串是”type/css”。
上面都是继承而来的属性和方法,另外CSSStyleSheet类型还支持以下属性和方法:
cssRules:样式表包含的样式规则的集合。IE8-不支持这个属性,但IE都有一个类似的rules属性。
ownerRule:如果样式表是@import导入的,这个属性就是一个指针,指向表示导入的规则;否则为null。IE8-不支持这个属性。
deleteRule(index):删除cssRules集合中指定位置的规则。IE8-不支持这个方法,但IE都支持一个类似的removeRule(index)。
insertRule(rule, index):向cssRules集合中指定的位置插入rule字符串。IE8-不支持这个方法,但IE都支持一个类似的addRule()方法。
应用于文档的所有样式表是通过document.styleSheets集合表示的。同样也有length和item()。
<!DOCTYPE html> <html> <head> <title>Style Sheets Example</title> <link rel="stylesheet" title="blah" type="text/css" href="stylesheet1.css"> <!--不同浏览器的document.styleSheets返回的样式表有所不同,所有浏览器都会返回rel特性为"stylesheet"的样式表 而IE和Opera(我的Chrome也行,其他没求证过)也包含rel特性为"alternate stylesheet"的样式表--> <link rel="alternate stylesheet" type="text/css" href="stylesheet2.css"> <style type="text/css"> #myDiv { background-color: blue; width: 100px; height: 200px; } </style> <script type="text/javascript"> function outputStyleSheets(){ var sheet = null; //这里再强调一下,不使用len而直接写在'i<'后面会影响效率,且如果函数体中包含影响length属性的代码,会出现错误。 for (var i=0, len=document.styleSheets.length; i < len; i++){ sheet = document.styleSheets[i]; alert(sheet.href);//style元素返回null IE8- style元素返回"" } } function toggleStyleSheet(){ /*body { background-color: silver; }*/ //点击可以禁用/启用样式,立即改变背景颜色。 document.styleSheets[0].disabled = !document.styleSheets[0].disabled; } </script> </head> <body> <div id="myDiv"></div> <input type="button" value="Output Style Sheets" onclick="outputStyleSheets()"> <input type="button" value="Enable/Disable Style Sheet" onclick="toggleStyleSheet()"> </body> </html>
也可以直接通过元素节点的sheet属性获得CSSStyleSheet对象。IE8-不支持该属性,IE8-仅支持styleSheet属性。IE9+后两个属性都支持。
function getStyleSheet(element){ return element.sheet || element.styleSheet; } var link = document.getElementsByTagName("link")[0]; var sheet = getStyleSheet(link); console.log(sheet.href); console.log(sheet.media);//MediaList console.log(sheet.ownerNode == link); //true console.log(sheet.title);//例子中是blah 不设就是null console.log(sheet.type);//text/css console.log(sheet.cssRules);//CSSRuleList console.log(sheet.cssRules[0].cssText);//body { background-color: silver; }
下面是一个关于CSSRule的例子:
function getCssRule(sheet){ return sheet.cssRules || sheet.rules; } var link = document.getElementsByTagName("link")[0]; var sheet = getStyleSheet(link); var cssRuleList = getCssRule(sheet); console.log(cssRuleList[0].cssText);//body { background-color: silver; } IE8- undefined 下面会介绍这个cssText属性 console.log(sheet.ownerRule);//null IE8- undefined var stylerule = "body { border-color: red;border-style: ridge;}"; if (typeof sheet.insertRule == "function") { sheet.insertRule(stylerule, 0);//IE9+ } else { sheet.addRule("body", "border-color: red; border-style: ridge;", 0);//IE都支持 } console.log(cssRuleList[0].cssText);//body { border-color: red; border-style: ridge; } if (typeof sheet.deleteRule == "function") { sheet.deleteRule(1);//IE9+ } else { sheet.removeRule(1);//IE都支持 }
CSSRule
CSSRule对象表示样式表中的每一条规则(比如body{…}就是一条规则)。实际上,CSSRule是一个供其他类型继承的基类型,其中最常见的就是CSSStyleRule类型,表示样式信息。CSSStyleRule类型包含以下属性:cssText:返回整条规则对应的文本。书上老说IE不支持,我发现IE9+都支持的。而不同浏览器的返回值可能有小区别(大小写)。
parentRule:如果当前规则是导入规则,这个属性引用的就是导入规则;否则这个值为null。
parentStyleSheet:当前规则所属的样式表。
selectorText:返回当前规则的选择符文本(比如body)。Opera允许修改该属性,其余浏览器该属性只读。
style:一个CSSStyleDeclaration对象(刚开始已经详细介绍过了),可以通过它设置和取得规则中特定的样式值。
type:表示规则类型的常量值。对于样式规则,这个值是1。
其中最常用的属性是cssText、selectorText和style。cssText属性与style.cssText属性类型。但前者包含选择符和花括号,后者只有花括号里面的内容。此外cssText是只读的,而style.cssText可以被重写。
<!DOCTYPE html> <html> <head> <title>CSS Rules Example</title> <style type="text/css"> div.box { background-color: blue; width: 100px; height: 200px; } </style> <script type="text/javascript"> function getStyleInfo(){ var sheet = document.styleSheets[0]; var rules = sheet.cssRules || sheet.rules;//后者适用于IE8- var rule = rules[0]; alert(rule.selectorText);//div.box alert(rule.cssText);//div.box{...} rule.cssText = "div.box { background-color: red; width: 100px; height: 200px; }"; alert(rule.cssText);//不变,说明上一句代码无效(cssText只读不可写 Writable为false?) var cssText = Object.getOwnPropertyDescriptor(rule, "cssText");//undefined 也许DOM对象不能这么用? //alert(cssText.writable); alert(rule.style.cssText);//div.box{...}中的... alert(rule.style.backgroundColor);//blue alert(rule.style.width);//100px alert(rule.style.height);//200px } //可以使用下列方式重写样式规则 function changeStyleInfo(){ var sheet = document.styleSheets[0]; var rules = sheet.cssRules || sheet.rules; var rule = rules[0]; rule.style.backgroundColor = "red"; } </script> </head> <body> <div class="box" style="margin-bottom: 10px"></div> <div class="box"></div> <input type="button" value="Get Style Info" onclick="getStyleInfo()"> <input type="button" value="Change Style Info" onclick="changeStyleInfo()"> </body> </html>
创建规则
其实这个前面已经提到过了。使用insertRule(rule, index);可以样式表中添加新规则。而IE8-只支持addRule(selectorText, cssText, index);(据说这个方法最多创建上限4095条)删除规则
这个前面也提到过了,使用deleteRule(index);IE8-只支持removeRule(index)元素大小
DOM中没有规定如何确定页面的大小。IE 率先引入了一些属性,目前所有主流浏览器都已经支持这些属性。偏移量
首先要介绍的是偏移量(offset dimension),包括元素在屏幕上占用的所有可见的空间。元素的可见大小由其高度和宽度决定,包括所有内边距、滚动条和边框大小(不包括外边距)。通过下面四个属性可以取得元素的偏移量。offsetHeight:元素在垂直方向上占用的空间大小,以像素计。包括元素的高度、(可见的)水平滚动条的高度、上边框高度和下边框高度。
offsetWidth:元素在水平方向上占用的空间大小,以像素计。包括元素的宽度、(可见的)垂直滚动条的宽度、左边框和右边框宽度。
offsetLeft:元素的左外边框至包含元素的左内边框的像素距离。
offsetTop:元素的上外边框至包含元素的上内边框的像素距离。
其中offsetLeft和offsetTop和包含元素有关,包含元素的引用保存在offsetParent属性中。offsetParent不一定与parentNode的值相等。例如
<td>元素的offsetParent则是
<table>元素,因为
<table>元素是DOM层次中距离
<td>最近的一个具有大小的元素。
如果想要知道某个元素在页面上的偏移量,只要将这个元素的offsetLeft和offsetTop与其offsetParent的相同属性相加,直至到根元素为止,就可以得到一个准确的值。
function getElementLeft(element){ var actualLeft = element.offsetLeft; var current = element.offsetParent; while (current !== null){ actualLeft += current.offsetLeft; current = current.offsetParent; } return actualLeft; } //top同理
要注意这4个属性是只读的。并且每次访问他们都需要重新计算(至于为什么访问值也会计算,想想访问器属性就知道了)。应该尽量避免重复访问这些属性。如果需要重复使用,可以保存在局部变量中,不过要在距离不会修改的前提下。
客户区大小
clientWidth和clientHeight属性表示的是元素内容及内边距的长和宽。获得页面视口大小,可以通过document.documentElement(即文档节点)的clientWidth和clientHeight属性。IE7之前的版本中得使用document.body的这两个属性去获取。
<!--注意要写在body内部,如果写在head里面document.body为null--> <script> console.log(document.documentElement.clientWidth);//杂项下为0 其余正常 但是都有区别 console.log(document.body.clientWidth);//都是正常数字,但是都有区别 </script>
这两个属性也是只读的,每次访问都会重新计算。
滚动大小
最后介绍的是滚动大小(scroll dimension),指的是包含滚动内容的元素的大小。有些元素(例如<html>元素)即使没有执行任何代码也能自动地添加滚动条。有些元素则需要设置CSS的overflow属性才能滚动,下面是关于滚动大小的4个属性:
scrollHeight:在没有滚动条的情况下,元素内容的总高度。
scrollWidth:在没有滚动条的情况下,内容的总宽度。
scrollLeft:被隐藏在内容区域左侧的像素数,通过设置这个属性可以改变元素的滚动位置。
scrollTop:同理,被隐藏在内容区域上册的像素数,通过设置这个属性可以改变元素的滚动位置。
scrollHeight和scrollWidth主要用于确定元素内容的实际大小。例如带有垂直滚动条的页面总高度为document.documentElement.scrollHeight。(在IE7之前为document.body.scrollHeight,因为IE7以前的版本将body元素视为浏览器的视口中的元素)
<!DOCTYPE html> <html> <head> <title>Offset Dimensions Example</title> <meta charset="utf-8"> <style> .test { width: 500px;height:500px;overflow: auto } .test div{ width: 1000px;height:800px; background-color: red; } </style> </head> <body> <div class="test"> <div>1</div> </div> <button onclick="totop()">回到顶部</button> <button onclick="tobottom()">回到底部</button> <button onclick="show()">显示信息</button> <button onclick="showWindow()">显示页面信息</button> <script> var div = document.getElementsByClassName("test")[0]; function totop() { div.scrollTop = 0; } function tobottom() { div.scrollTop = div.scrollHeight - div.clientHeight; } function show() { alert(div.scrollWidth); alert(div.scrollHeight); alert(div.scrollLeft); alert(div.scrollTop); } function showWindow() { //以下结果为Chrome测试结果 //第一个539是body的高度,而768则是整个页面的高度。当我用调试窗口显示在浏览器下方时,clientHeight会变小 //但是scrollHeight没有发生变化 alert(document.documentElement.scrollWidth);//1440 alert(document.documentElement.scrollHeight);//539 alert(document.documentElement.clientWidth);//1440 alert(document.documentElement.clientHeight);//768 } </script> </body> </html>
而对于不包含滚动条的页面,scrollWidth、scrollHeight、clientWidth和clientHeight之间的关系并不十分清晰。我们对同一个页面获取document.documentElement的这些属性,见上面的showWindow()函数。
确定元素大小
主流浏览器为每个元素提供了getBoundingClientRect()方法。这个方法会返回一个矩形对象,包含4个属性:left、top、right、bottom。这个属性给出了元素在页面中相对于视口的位置。IE8及更早版本认为文档的左上角左边是(2,2),而其他浏览器包括IE9则认为是(0,0),可以通过下面的函数://"use strict"; //var getBoundingClientRect = function fname(element) { function getBoundingClientRect(element){ var scrollTop = document.documentElement.scrollTop; var scrollLeft = document.documentElement.scrollLeft; if (element.getBoundingClientRect){ //if (typeof fname.offset != "number"){ if (typeof arguments.callee.offset != "number"){ var temp = document.createElement("div"); temp.style.cssText = "position:absolute;left:0;top:0;"; document.body.appendChild(temp); //fname.offset = -temp.getBoundingClientRect().top - scrollTop; arguments.callee.offset = -temp.getBoundingClientRect().top - scrollTop; document.body.removeChild(temp); temp = null; } var rect = element.getBoundingClientRect(); //var offset = fname.offset; var offset = arguments.callee.offset; return { left: rect.left + offset, right: rect.right + offset, top: rect.top + offset, bottom: rect.bottom + offset }; } else {//如果不支持getBoundingClientRect()方法 //这两个方法在前面提到过通过while将offsetLeft累加获得 var actualLeft = getElementLeft(element); var actualTop = getElementTop(element); return { left: actualLeft - scrollLeft, right: actualLeft + element.offsetWidth - scrollLeft, top: actualTop - scrollTop, bottom: actualTop + element.offsetHeight - scrollTop } } }
上面的这个方法创建了一个div元素并获取它的坐标信息。然后将offset保存在该方法中,下次调用则直接使用offset变量。
注意到上面用到了arguments.callee属性,该属性在严格模式下是不能使用的。我们可以使用命名函数表达式的写法去完成(直接写成getBoundingClientRect耦合性太高)。
相关文章推荐
- js学习小结(十)2014.5.10.11(DOM2和DOM3的变化,操作样式的DOM API(1))
- JavaScript高级程序设计之DOM2和DOM3之样式之访问元素的样式第12.2.1讲
- 第十二章:DOM2 和 DOM3(遍历)
- JavaScript高级程序设计之DOM2和DOM3之样式之元素大小第12.2.3讲
- 《JS高程(3)》DOM2和DOM3-样式、视口尺寸问题-第12章笔记(23)
- W3C DOM2样式规范
- javascript dom 获取样式属性值
- javascript dom 获取样式属性值
- JavaScript DOM 利用样式实现元素移动位置
- JavaScript DOM 利用样式实现元素移动位置
- JavaScript DOM中 改变样式属性,实现动画效果
- JavaScript DOM中 改变样式属性,实现动画效果
- JavaScript DOM中 改变样式属性,实现动画效果 2
- DOM中的动态脚本和动态样式
- javascript基础:DOM4操作表格和样式
- 2015-03-12——简析DOM2级样式
- DOM2级样式
- JavaScript--DOM操作表格及样式(21)
- 使用js改变DOM样式的三种方式 - 动态创建style标签
- IE6共存、调试(查看Dom元素,修改元素样式)之我见 + IE6下Firebug Lite的使用