DOM之样式
jQuery有css这个方法很便利的获取或者设置文档的样式,如果原生的方式呢?可以回顾一下js是如果操作DOM样式的。
className
className属性总是和html上的class特性保持一致的。用法例如:
<body class="class1 class2">
<script>
alert(document.body.className)
document.body.className += ' class3'
</script>
</body>
如果想要删除一个class,可以把字符串中的class字符replace成空,也可以应空格split字符串后删除class再join回来。多数js框架都会提供内置方法来做这些工作,例如jq中:
$( "p" ).removeClass( "myClass noClass" ).addClass( "yourClass" );
style
style属性是读写元素style的通道,用它可以修改大多数css的属性,例如:
element.style.width='100px';
这句话就相当于在html上添加了style="width:100px"的特性。有一点要注意的是,和css一样,赋值的时候需要提供测量的单位,例如:'px', '%', 'rem', 'em'等。对于多单词字符属性,需要转换成小驼峰才可以,例如:
background-color => backgroundColor
z-index => zIndex
border-left-width => borderLeftWidth
使用style赋值的属性值总会覆盖用css样式的属性值,所以我们可以这样来删除width的赋值:
element.style.width = '';
又比如这样赋值:
// enter an empty value to reset the color
document.body.style.backgroundColor = prompt('background color?', 'green')
对于有浏览器前缀的使用例子如下,当然把属性放到css中,使用element.className来添加和删除style更加清晰。
//-moz-border-radius, -webkit-border-radius
button.style.MozBorderRadius = '5px'
button.style.WebkitBorderRadius = '5px'
cssText
style.cssText这个属性可以用来读写整个样式声明:
<div>Button</div>
<script>
var div = document.body.children[0]
div.style.cssText='color: red !important; \
background-color: yellow; \
width: 100px; \
text-align: center; \
blabla: 5; \
'
alert(div.style.cssText)
</script>
看到和用style[property]使用的不同了吧,cssText是对整个html中style特性的覆盖,也就说如果原本拥有的style在cssText中没有被写到,则该style就被清空了。
注意的是cssText中赋值的样式,只有浏览器认识它才会添加,如果不存在的例如blabla, 则会被忽略。
style.cssText是在js中可以添加css值中!important的唯一途径。
读取style中的值
特别需要注意的是,style属性仅仅可以访问那些被直接用element.style[propery]这样赋值或者用html中style特性赋值的样式,所以如下,如果你试图访问marginTop的样式的值你是访问不到的:
<style>
body { margin: 10px }
</style>
<body>
<script>
alert(document.body.style.marginTop)
</script>
</body>
这是因为margin是css样式表作用的渲染结果,并不是html的style特性上的值或者用style属性赋的值。如果你用style属性赋值则可以成功读取值:
<style>
body { margin: 10px }
</style>
<body>
<script>
document.body.style.margin = '20px'
alert(document.body.style.marginTop)
</script>
</body>
从上面可以看出来,浏览器对margin属性进行了解开,即提供了它相关子属性的读取,有这种现象了属性还有border、background等等。
还有一点需要注意的是,通常不应该用js直接个style属性赋值而应该用css的classes(用js来添加删除class来实现),除非用class无法完成需求(通常比较少,但是有这种情况)。
getComputedStyle and currentStyle
上面说了,使用style无法获取那些在css里定义的样式,那如果我们需要知道此刻渲染到页面上的元素样式时该怎么办呢?
在css样式表和style特性描述以及js操作style属性之后,我们读取此刻元素真正运用上的属性值需要DOM Level2规范中提出的window.getComputedStyle方法。该方法的语法:
getComputedStyle(element, pseudo)
其中pseudo是伪类选择器,例如'hover',如果不需要刻意不传。
这个方法在所有浏览器都支持,除了IE<9,如下:
<style>
body { margin: 10px }
</style>
<body>
<script>
var computedStyle = getComputedStyle(document.body, null)
alert(computedStyle.marginTop)
</script>
</body>
那么对于低版本IE怎么办呢?IE提供了currentStyle属性,基本和getComputedStyle方法效果一样。但是这个属性有一个缺陷,就是currentStyle返回的值是css中的值,也就是说css中的单位是什么返回的就是什么,而不是被换算成了实际的pixels。例如:
<style>
body { margin: 10% }
</style>
<body>
<script>
if (window.getComputedStyle) {
var computedStyle = getComputedStyle(document.body, null)
} else {
computedStyle = document.body.currentStyle
}
alert(computedStyle.marginTop)
</script>
</body>
在火狐中,pixels也许是小数的;在其他浏览器中是整数的pixels;在IE中还是原有的单位,也就是上面会看到%。怎么解决呢?有一个方案可以转换,具体理解可以去参考IE特有的两个属性runtimeStyle和pixelLeft,方法如下:
function getCurrentPixelStyle(elem, prop) {
var value = elem.currentStyle[prop] || 0
// we use 'left' property as a place holder so backup values
var leftCopy = elem.style.left
var runtimeLeftCopy = elem.runtimeStyle.left
// assign to runtimeStyle and get pixel value
elem.runtimeStyle.left = elem.currentStyle.left
elem.style.left = (prop === "fontSize") ? "1em" : value
value = elem.style.pixelLeft + "px";
// restore values for left
elem.style.left = leftCopy
elem.runtimeStyle.left = runtimeLeftCopy
return value
}
<style> #margin-test { margin: 1% } </style>
<div id="margin-test">margin test</div>
<script>
var elem = document.getElementById('margin-test')
if (elem.currentStyle) // IE
document.write(getCurrentPixelStyle(elem, 'marginTop'))
else
document.write('Open the page in IE please')
</script>
嗯嗯~幸好我不用兼容IE。。。
翻译原文的链接here