JavaScript权威指南--脚本化CSS

 知识要点

客户端javascript程序员对CSS感兴趣的是由于样式能够经过脚本编程。脚本化css启用了一系列有趣的视觉效果。例如:能够建立动画让文档从右侧“滑入”。创造这些效果的javascriptcss技术在之前统称为动态HTML(DHTML).而如今,这个技术术语已经不流行了。javascript

为了理解CSS脚本化,咱们必须CSS的基础和最经常使用的样式属性。css

1.CSS概述

HTML的视觉显示包含不少变量:字体,颜色、间距等。css标准列举了这些变量,称为样式属性。html

紧跟属性名的是冒号和值。多个属性时用分号隔开。CSS忽略了/* */之间的注释,可是它不支持//后面的注释。java

两种方式将一组定义视觉表现的CSS属性和对于的HTML元素关联在一块儿。第一种是经过给每一个单独的HTML元素设置style属性的方式,称为内联样式。ios

尽管如此,一般将单独的HTML元素和CSS样式表分开,并把他们定义在一个样式表(stylesheet)中会更有用,样式表经过选择器将一组样式属性和使用选择器(selector)描述的一组HTML元素关联在一块儿。程序员

CSS样式表的基本元素是样式规则,它们由选择器和包裹在一对{}中的css属性和值所组成。每一个样式表能够包含任意数量的样式规则。在<style>标签使用或者保存为单独文件并经过<link>引入。web

1.1.层叠

回想下,在CSS的“C”表明了“层叠”、该术语指定了应用于文档中任何给定元素的样式规则是各个“来源”的“层叠”效果:chrome

  • web浏览器的默认样式表
  • 文档的样式表
  • 每一个独立的HTML元素的style属性 

style属性的样式表覆盖了样式表中的样式,而且文档的样式表中的样式覆盖了浏览器的默认样式。编程

为了显示文档元素,web浏览器“必须”组合元素的style属性。计算结果是一组实际用于显示元素的样式属性和值。这组值就是元素的“计算样式”(computed style)。数组

1.2.CSS历史

CSS历史是一个相对较老的标准,CSS1在1996年12月被采纳,它定义了具体的颜色,字体,外边距,边框和其它的旗本样式。该标准的第二版css2在1998年被采纳,定义了不少高级特性,最著名的就是元素的绝对定位。css2.1澄清和更正了css2,而且它删除了浏览器供应商从未实现的功能。如今的浏览器基本上都彻底支持css2.1,可是低于IE8的IE还有一些遗漏问题。在css后续的工做中,针对版本3,CSS规范意见拆分红各类各样的专门化模块,分别来经过标准化进程。能够经过http://www.w3.org/Style/CSS/current-work找到css规范和工做草案。

1.3.复合属性

某些常常在一块儿使用的样式属性能够组合起来使用一个特殊的复合属性。例如font-family、font-size、font-weight属性能够用font的复合属性一次性设置

1.4.非标准属性

当浏览器厂商实现非标准CSS属性时,他们将属性名前加了一个厂商前缀。Firefox使用-moz-,Chrome使用-wibkit-,而IE则使用-ms-,它们甚至用这种方式来实现未来会标准化的属性。

在不一样的浏览器中不一样名字的CSS属性一块儿工做,你能够能发现一个属性定义一个类方式比较好:

.radius10{
  border-radius:10px; /*针对现代浏览器*/
  -moz-border-radius:10px; /*针对firefox 3.x*/
  -webkit-border-radius:10px; /*针对safari 3.2和4*/
}

像这样定义一个类叫“radios10”,能够将它添加到任意须要10像素圆角的元素的类上。

1.5.CSS举例

 

2.重要的css属性

对于客户端程序员来讲,最重要的css特性是那些指定文档中每一个元素的可见性、尺寸和精肯定位的属性。其它css属性容许指定堆叠的次序、透明度、裁剪区域、外边距、内边距、边框、颜色。为了脚本化css。理解这些样式属性的工做原理是很是重要的。

2.1.用css定位元素

CSS的position指定了应用到元素上的定位类型,以下是4个可能出现的属性值:

  • static:默认属性.指定元素按照常规的文档内容流。静态定位的元素不能使用top,left和相似其它的属性定位。若是想对该文档元素使用css定位技术,必须将position属性值设置为除此以外的其它3个属性值。
  • absolute:该值指定元素是相对于它包含的元素进行定位。相对于全部其它的元素,绝对定位的元素是独立定位的,它不是静态定位的元素中文档流的一部分。它的定位要么是相对于最近定位祖先元素,要么是相对于文档自己。
  • fixed:该值的定位元素是相对于浏览器窗口进行定位的。固定定位的元素始终显示在那里。固定定位的元素和其它元素是独立的。不是文档流的一部分。除了ie6不支持外 ,其它现代的浏览器都支持它。
  • relative:当position属性设置为relative,元素会按照常规的文档流进行布局,它的定位相对于它文档流中的位置进行调整。系统保留着元素正常文档流中的空间。不会由于要填充空间将其各边合拢。也不会将新的元素重新的位置“推开”

一旦设置了元素的position属性为除了static之外的值,就能够经过元素的left,top,right,bottom属性的一些组合指定元素的位置。

若是元素使用绝对定位,它的top和left属性应该解释为它是相对于其position属性设置为除static值之外的祖先元素。若是绝对定位的元素没有定位过的祖先,则使用文档坐标进行度量——就是相对于文档左上角的偏移量。若是想相对于一个属于常规文档流中的容器绝对定位一个元素,则将容器的position指定为relative,top和left指定为0px。这就让容器变成了动态定位,但它仍留在文档流中原来的位置。

指定元素的宽度能够用width,另外一种方法是同时指定left和right属性,高度也同样。若是同时指定left、right和width,那么width属性将覆盖right属性,height属性优先于bottom属性。

<head>
    <meta charset="utf-8">
</head>
<style type="text/css">
    .out{position: relative;left: 0;right: 0;width: 500px;height: 500px;background: #ccc;}
    .in{position: absolute;left: 100px;right: 100px;top: 100px;bottom: 100px;width: 200px;background: #aaa;}
</style>
<body>
    <div class="out">
        <div class="in">绝对定位</div>
    </div>
</body>

单位:px、in、cm、pt、em等等。

1.第三个维度

上面讲的是在二维坐标中指定X和Y坐标,z-index定义第三个维度容许指定元素的堆叠次序。默认为0,能够是正负整数若是重叠元素的z-index值同样,则按照在文档中出现的顺序绘制,即最后一个重叠的元素显示在最上面

注意:z-index只对兄弟元素应用堆叠效果。

非定位元素(例如,默认使用position:static定位)老是以防止重叠的方式进行布局,由于z-index属性不会应用到他们上面。尽管如此,它们默认的z-index值为0,这意味着z-index为正值的定位元素显示在常规文档流的上面,而z-index为负直的定位元素显示在常规文档流的下面。

2.CSS定位示例:文本阴影

CSS3有text-shadow属性能够产生文本阴影效果,用CSS定位也能够实现,只要重复输出这段文本并从新定义一下样式:

<body>
    <!-- text-shadow属性 -->
    <span style="text-shadow: 3px 3px 1px #888">Shadowed</span>

    <!-- 利用定位 -->
    <span style="position: relative;">
        Shadowed
        <span style="position: absolute;top: 3px;left: 3px;z-index: -1;color: #888">
            Shadowed
        </span>
    </span>
</body>

2.2.边框,外边距,内边距

边框样式border,指定边框的样式、样式和厚度,也能够单独指定。

在CSS3中能够用border-radius指定圆角,也能够设置单独的圆角。

margin和padding属性。

2.3.CSS盒模型和定位细节

以上描述的margin,border和padding等样式属性在脚本化时极可能不常用。由于他们是CSS盒模型(box model)的一部分

left和top属性指定了从容器边框内侧到定位元素边框外侧的距离。这些属性不是从容器内容区域的左上角开始度量的,而是从容器内边距的左上角开始的。一样,right和bottom属性是从容器内边距的右下角开始度量的。

有一个例子说明这点。假设已建立一个在内容区域四周有10px padding和5px border的动态定位的容器元素。假设一个定位的子元素将left设为0px,则子元素会靠在容器左边框的右边,覆盖了容器的内边距。因此若是要这样作的话须要设置left为10px。

边框盒模型和box-sizing属性

标准CSS盒模型规定width和height样式属性给定内容区域尺寸,并且不包含内边距和边框。能够称此为“内容盒模型”。在老版的IE和新版的CSS都有一些例外 ,在IE6以前和当IE6-8在怪异模式下,显示一个页面(页面缺乏<!DOCTYPE>或有一个不严格的doctype时),width和height属性确是包含内边距和边框宽度的。

可是这样也有用,因此CSS3引进了box-sizing属性,默认值是content-box,它指定执行页面的标准盒模型,若是替换为box-sizing:border-box,浏览器将会为那个元素应用IE的盒模型,即:width和height包含边框和内边框。当想以百分比形式为元素设置整体尺寸,又想以像素指定边框和内边距时,边框盒模型特别有用。

<div style="box-sizing:border-box;width: 50%;padding: 10px;border: 2px solid red;"></div>

box-sizing属性在当今的浏览器中都支持,可是还没不带前缀通用地实现。能够在chrome和safari中使用-webikit-box-sizing,在firefox中,使用-moz-box-sizing。在IE后等其余浏览器更高的版本中,可使用不带前缀的box-sizing。

在CSS3中一个可选方案是使用盒子尺寸的计算值:

<div style="width: calc(50%-12px);padding:10px;border: solid red 2px;"></div>

在IE9中支持使用calc()计算css的值。在Firefox4中为-moz-calc()。

2.4.元素的显示和可见性

两个CSS的属性影响了文档元素的可见性:visibility和displayvisibility属性很简单。当其值设置为hidden时,该元素不显示。当其值设置为visible时,该元素显示。display属性更加通用。它用来接收它的容器指定元素显示的类型。它指定元素是块级元素、内联元素、列表项等。但当display设置为none,受影响的元素将不显示,甚至根本没有布局。

visibility和display属性之间的差异能够从他们对使用静态或至关定位元素的影响中看到。对于一个常规布局流中的元素,设置visibility属性为hidden使得元素不可见,但在文档布局中保留了它的空间。相似的元素能够重复隐藏和显示而不改变文档布局。可是,当display属性设置为none,在文档布局中不给它分配空间。使得各边元素会靠拢,就当不存在。例如在建立和展开折叠的效果时display属性就颇有用。

visibility和display属性对绝对和固定定位的元素影响是等价的。由于这些元素都不是文档布局的一部分。然而,在隐藏和显示定位元素时通常首选visibility属性。

注意,使用visibility和display属性是的元素不可见没有什么意义。除非使用javascript动态设置这些属性让元素在某一刻可见!

2.5.颜色、透明度和半透明度

文本元素、背景颜色、边框颜色。

在CSS中更通常指定颜色的语法是使用十六进制数分别指定组成颜色的红、绿和蓝色份量,每一个份量可使用一位后两位数字

CSS3也指定RGBA彩色空间。CSS3也定义了对HSL(色相-饱和度-值)和HSLA颜色规范的支持。他们在FIrefox、Safari、Chrome中都支持,除了IE。

除了background-color属性,也能够为元素指定背景图像:background-image属性以及一些高级细节设置。使用复合属性background直接搞定。

若是没有为元素指定背景颜色或图象,它的背景一般透明,理解这点很是重要,例如一个空的<div>绝对定位。尽管如此,默认状况下不是全部元素都是透明的,例如,具备透明背景的表单元素看起来不透明,而且元素<button>有默认的背景颜色用background-color属性能够覆盖默认颜色,若是强烈要求能够将其显式设置为"transpanrent"。

CSS3的opacity属性处理元素的透明,该属性值为0-1之间的数字、opacity属性在当今全部的浏览器都支持。除了IE,IE提供可选方式:特有的filter属性。

opacity:.75
filter:alpha(opacity=75);

2.6.部分可见:overflow和clip

visibility属性可让文档元素彻底隐藏,而overflow和clip属性容许只显示元素的一部分。overflow属性指定内容超出元素的大小(例如:用width和 height样式属性指定)时如何显示。该属性的值和含义以下所示:

  • visible :默认值。若是须要,内容能够溢出并绘制在元素边框的外面
  • hidden:裁剪掉和隐藏溢出的内容。
  • scroll:元素一直显示水平和垂直滚动条。
  • auto:滚动条只在内容超出元素的尺寸时显示,而非一直显示。

clip属性确切地指定了应该显示元素的哪一个部分,无论是否溢出在建立元素渐进显示的脚本效果时特别有用

clip属性的值指定了元素的裁剪区域,在css2中,裁剪区域是矩形的,不过clip属性的语法预留了开放的可能性,该标准在未来的版本可能将支持更多形状的裁剪。它的语法是:

/*相对于元素边框的左上角*/
rect(top right bottom left)

例如只显示元素的100X100的部分:

style="clip:rect(0px 100px 100px 0);"

注意:圆括号4个值时长度,因此必须包含明确单位。不容许使用百分比,能够指定负值,也能够为任何4个值使用auto关键字来指定裁剪区域的边缘就是元素边框的对应边缘。例如只显示元素最左的100像素:

style = "clip:rect(auto 100px auto auto);"

值之间没有逗号。将clip设置为auto来停用裁剪功能。

2.7.示例:重叠半透明窗口

 

3.脚本化内联样式

脚本化css最直接了当的方法就是更改单独的文档元素的style属性,相似大多数HTML属性,style也是元素对象的属性,它能够在javascript操做,可是style属性不一样寻常:它的值不是字符串,而是一个CSSStyleDeclaration对象。该style对象的javascript属性表明了HTML代码中经过style指定的css属性。例如让元素e的文本变大号、加粗和蓝色,可使用以下代码设置font-size,font-weight和color样式属性对应的javascript属性。

e.style.fontSize = "24px";
e.style.fontWeight = "bold";
e.style.color = "#007F9F";

名字约定:JavaScript中的CSS属性

有连字符的属性,在JavaScript是减号,不能用。所以,CSSStyleDeclaration对象中的属性名和实际的CSS属性名有所区别。例如连字符改成首字母大写:CSS属性border-left-width的值在JavaScript中为borderLeftWidth。另外,当一个CSS属性(如float)在JavaScript中对应的名字是保留字时,在以前加"css"前缀来建立合法的CSSStyleDeclaration名字。如float为cssFloat。

使用CSSStyleDeclaration对象的style属性时,记住全部值都应该是字符串,全部的定位都有有单位。

e.style.left = (x0 + left_margin + left_border + left_padding) + "px";

回想一下,一些css属性(如margin)是margin-top/margin-right/margin-bottom/margin-left)的复合属性。CSSStyleDeclaration对象也有与之对应的复合属性,例如。也能像这样设置magin属性:

e.style.margin = topMargin + "px" + rightMargin + "px" + bootomMargin + "px" + leftMargin + "px";

独立设置4个margin属性值更加便捷:

e.style.marginTop = topMargin + "px";
e.style.marginRight = rightMargin + "px";
e.style.marginBottom = bottomMargin + "px";
e.style.marginLeft = leftMargin + "px";

HTML元素的style属性是它的内联样式,它覆盖在样式表中的任何样式说明。内联样式通常在设置样式值时很是有用,就像上面的例子所说的同样。CSSStyleDeclaration对象的属性能够理解为表明内联样式,可是它只返回有意义的值:javascript代码已经设置过的值或者HTML元素显式设置了想要的内联样式的值。例如,文档可能包含一个样式表以设置全部段落的左边距为30px,可是挡在读取段落元素的marginLeft属性时会获得一个空字符串,除非该段落有一个style属性覆盖了样式表中的设置。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <style type="text/css">
        #mar0,#mar1{
            width: 100px;height: 100px;border: 2px solid #ccc;margin-left: 10px;
        }
    </style>
</head>
<body>
    <div id="mar0">margin</div><br>
    <div id="mar1" style="margin-left: 20px">margin</div>
    <script type="text/javascript">      
        window.onload = function(){
            var ma0 = document.getElementById("mar0");
            var ma1 = document.getElementById("mar1");            
            console.log(ma0.style.marginLeft);
            console.log(ma1.style.marginLeft);
        }
    </script>
</body>

读取元素的内联样式特别困难,对style属性来讲必须包含单位,对复合属性来讲,在真正使用这些值的时候,代码不得不包含非同寻常的css解析能力。总之,元素的内联样式只有在设置样式的时候有用,但若是须要查询元素的样式,就要使用计算样式,这将在本章4节讨论。

有时,发现单个字符串值来设置或查询元素的内联样式反而比做为CSSStyleDeclaration对象更加简单。为此,可使用元素的getAttribute()和setAttribute()方法或CSSStyleDeclaration对象的cssText属性来实现:

 //二者均可以设置e的样式属性为字符串s
e.setAttribute("style", s);
s = e.style.cssText;
 //二者均可以查询元素的内联样式
s = e.getAttribute("style");
s = e.style.cssText;

CSS动画

脚本化的css最多见的用途之一就是产生视觉动画,使用setTimeout()或setTinterval()(12章1节),重复调用函数来修改元素的内联样式达到目的。下面的例子用shake()和fadeOut()来举例说明。shake()将元素从一边快速移动到另外一边震动。例如当输入无效数据时,会吸引用户注意力。fadeOut()经过制定时间(默认500毫秒)下降元素不透明度,使得元素淡出和消失。

//将e转化为相对定位的元素,使之左右“震动”
//第一个参数能够是圆度对象或者元素的id
//若是第二个参数是函数,以e为参数,将在动画结束时调用;第三个参数指定e震动的距离,例如5px
//第四个参数指定震动多久,默认500毫秒
function shake(e, oncomplete, distance, time) {
    //句柄参数
    if (typeof e === "string") e = document.getElementById(e);
    if (!time) time = 500;
    if (!distance) distance = 5;
    
    var originalStyle = e.style.cssText; //保存e的原始style
    e.style.position = "relative"; //使e相对定位
    var start = (new Date()).getTime(); //注意,动画的开始时间
    animate(); //动画开始
    //函数检查消耗时间,并更新e的位置
    //若是动画完成,它将e还原为原始状态
    //不然,更新e的位置,安排它自身重新运行
    function animate() {
        var now = (new Date()).getTime(); //获得当前时间
        var elapsed = now - start; //从开始以来消耗了多长时间
        //是总时间的几分之几
        var fraction = elapsed / time;
        if (fraction < 1) { //若是动画未完成
            //做为动画完成的比例函数,计算e的x位置
            //使用正弦函数将完成的比例乘以4pi
            //因此,它来回往复两次
            var x = distance * Math.sin(fraction * 4 * Math.PI);
            e.style.left = x + "px";
            //在25毫秒以后或在总时间最后尝试再次运行函数
            //目的是为了产生每秒40帧的动画
            setTimeout(animate, Math.min(25, time - elapsed));
        } else { //不然动画完成
            e.style.cssText = originalStyle //恢复原始样式
            if (oncomplete) oncomplete(e); //调用完成后回调函数
        }
    }
}
//以毫秒级时间将e从彻底不透明到透明
//在调用函数时假设e是彻底不透明的
//oncomplate是一个可选函数,以e为参数,在动画结束调用
//若是不指定time.默认500
//本函数ie中不能正常构造
//除了opacity,ie使用非标准的filter属性
function fadeOut(e,oncomplete,time){
    if(typeof e === "string") e = document.getElementById(e);
    if(!time) time =500;
    
    //使用Math.sqrt做为一个简单的缓动函数来建立动画
    //精巧的非线性:一开始淡的比较快,而后慢一些
    var ease = Math.sqrt;
    
    var start = (new Date()).getTime(); //注意动画开始的实际
    animate();//动画开始
    
    function animate(){
        var elapsed = (new Date()).getTime() - start ;//消耗时间
         //总时间的几分之几
        var fraction = elapsed/time;
        if(fraction < 1){//动画未完成
            var opacity = 1 - ease(fraction);//计算元素不透明
            e.style.opacity =String(opacity); //设置在e上
            setTimeout(animate,Math.min(25,time-elapsed));
        }
        else{
            e.style.opacity = "0";
            if(oncomplete) oncomplete(e); //调用完成后回调函数
        }
    }
}

shake()和fadeOut()都能接受可选的回调函数做为第二个参数,若是指定了,当动画结束时函数将被调用。该动画元素将做为回调函数的参数传递进去。下面的代码建立了一个按钮,当单击时,左右震动并淡出。

<button onclick="shake(this,fadeOut)">点击我</button>

注意,shake()和fadeOut()示例函数之间很是类似,都能做为相似css属性动画的模板。客户端类库,如jQury一般支持预约义的视觉效果,所以,除非想建立特别复杂的视觉效果,实际上不用写相似shake()动画函数。scriptaculous是早期一个值得关注的类库,它是为prototype框架设计的。http://scripty2.com/

为了不使用任何脚本,CSS3的过渡模块定义了在样式表中指定动画效果的方式。例如,为了替代定义相似fadeOut()这样的函数,可使用以下的css:

.fadeable{transition:opacity .5s ease-in}

4.查询计算出的样式

元素的style属性表明了元素的内联样式,它覆盖全部的样式表,它是设置CSS属性值来改变元素的视觉表现最好的地方。可是,它在查询元素实际应用的样式时用处不大。为此,你想要使用计算样式。元素的计算样式是一组属性值,它由浏览器经过把内联样式结合全部连接样式表中全部可应用的样式规则后导出(或计算)获得的:它就是一组在显示元素时实际使用的属性值相似内联样式,计算样式也是一个CSSStyleDeclaration对象来表示的,区别是,计算样式是只读的。虽然不能设置这些样式,但为元素计算出的CSSStyleDeclaration对象确切地决定了浏览器在渲染元素时使用的样式属性值。

用浏览器窗口对象的getComputedStyle()方法来获取一个元素的计算样式。接收两个参数:第一个是要取得其计算样式的元素,第二个也是必须的,一般是null或空字符串,也能够是命名CSS伪对象字符串,如“:before”、“:after”、“:first-line”、“:first-letter”。

var title = document.getElementById("section1title");
var titlestyles = window.getComputedStyle(element,null);

getComputedStyle()方法返回一个CSSStyleDeclaration对象,其中包含当前元素的全部计算的样式。

表示计算样式的CSSStyleDeclaration对象和表示内联样式的对象之间有一些重要的区别:

  • 计算样式的属性是只读的;
  • 计算样式的值是绝对值,相似百分比和点之类相对的单位将所有转换绝对值。全部指定尺寸的属性都有一个以像素为度量单位的值。该值将是一个冠以"px"后缀的字符串,使用时仍然须要解析它,可是不用担忧单位的解析或转换。其值是颜色的属性将以“rgb(#,#,#)”或“rgba(#,#,#,#)”的格式返回;
  • 不计算复合属性,它们只基于最基础的属性,如不要查询margin,应该使用marginTop等;
  • 计算样式的cssText属性未定义;

计算样式和内联样式能够同时使用。下面例子定义了scale()和scaleColor()函数。一个用来查询和解析指定元素的计算文本尺寸,另外一个查询和解析元素的计算背景颜色。两个函数都将结果值按比例缩放并做为元素的内联样式设置缩放值。

。。。。。。

计算样式也具备欺骗性,查询它们获得的信息也不老是如人所愿好比font-family属性:为了适应跨平台可移植性,可能会接受字体列表,当查询一个计算样式的fontFamily属性时,可能返回一系列的字体如"arial,helvetica,san-serif",而没法告诉你实际使用哪一种字体。相似的,若是没有使用绝对定位,试图经过计算样式的top和left属性会返回"auto",这个是合法的,但不是想要的。

在IE中,每一个HTML元素有本身的currentStyle属性,它的值是CSSStyleDeclaration对象。IE的currentStyle组合了内联样式和样式表,但他不是真正的计算样式,由于相对值都没有转换为字符串(会带有"%"、"em"或"red"等等)。

查询元素的计算样式不是断定元素尺寸和位置的完美方法,另外一种更简单的在15.8.2节。

5.脚本化CSS类

经过内联style属性脚本化CSS样式的一个可选方案是脚本化HTML的clss属性值。改变了元素的class就改变了应用于元素的一组样式表选择器,它能在同一时刻改变多个CSS属性。例如,假设想让用户对文档中的单独段落(或其它元素)引发注意。首先,为任意元素定义一个名为"attention"的类:

.attention{/*吸引用户注意*/
    background-color:yellow;
    font-weight: bold;
    border: solid black 2px;
}

标识符class在javascript中是保留字,因此HTML属性class在javascript代码中应该可用于使用calssName的javascript代码。以下的代码设置和清除元素的className属性来为元素添加和移除"attention"类:

function grabAttention(e){e.className = "attention";}
function releaseAttention(e) {e.className = "";}

HTML元素能够有多个CSS类名,class属性保存了一个用空格隔开的类名列表。上面的函数假设className属性只指定零个或一个类名,若是有多个类名就没法工做了。若是元素已经有一个类,调用上面grabAttention()函数将覆盖已经存在的类。

HTML5为了解决这个问题,为每一个元素定义了classList属性该属性的值是DOMTokenList对象:一个只读的类数组对象(7.11节),它包含元素的单独类名。可是,和数组元素相比,DOMTokenList定义的方法更加剧要。add()和remove()从元素的class属性中添加和清除一个类名。toggle()表示若是不存在的类名就添加一个;不然,删除它。最后,contains()方法检测class属性中是否包含一个指定的类名。

相似其余DOM集合类型,DOMTokenList对象“实时的”表明了元素类名集合。而并不是是在查询classList属性时类名的一个静态快照。若是从元素的classList属性中得到了一个DOMTokenList对象,而后元素的className属性改变了,这些变化在标识列表中及时可见。一样,改变标识列表,在ClassName属性中及时可见。

不是全部的浏览器都支持classList属性。可是这个重要的功能容易近似实现。以下代码或使用相似的代码,把class属性当作一个类名的集合。使得许多脚本化的css类工做更加简单。

。。。。。。

6.脚本化样式表

到目前为止,咱们已经看到如何设置和查询CSS样式和单个元素的类名。脚本化样式表固然是也是可能的。虽然不常常这么作,但偶尔却很是有用。本节概述该技术。

在脚本化样式表时,将会碰到两类须要使用的对象。第一类是元素对象,由<style>和<link>元素表示,两种元素包含或引用样式表。这些是常规的文档元素,若是他们有id属性值,可使用document.getElementById()函数来选择它们。第二类是CSSStyleSheet对象,它表示样式表自己。document.styleSheets属性是一个只读的类数组对象,它包含CSSStyleSheet对象,表示与文档关联在一块儿的样式表。若是为定义或引用了样式表的<style>或<link>元素设置title属性值,该title做为对应CSSStyleSheet对象的title属性就能够。

6.1.开启和关闭样式表

最简单的校本化样式表的技术特是最便捷和健壮的。<style>、<link>元素和CSSStyleSheet对象都定义了一个在javascript中能够设置和查询的disabled属性。顾名思义,若是disabled属性为true,样式表就被浏览器关闭并忽略

如下disableStyleSheet()函数就说明了这一点。若是传递一个数字 。函数将其当作document.styleSheet数组中的一个索引,若是传递一个字符串。函数就将其当作CSS选择器并传递给document.querySeleCtorAll()(15.2.5节),而后设置全部返回元素的disabled属性:

function disableStyleSheeet(ss) {
    if (typeof ss === "number")
        document.styleSheets[ss].disabled = true;
    else {
        var sheet = document.querySelectorAll(ss);
        for (var i = 0; i < sheet.length; i++)
            sheet[i].disabled = true;
    }
}

6.2.查询、插入与删除样式表规则

除了样式表的开启和关闭之外,CSSStyleSheet对象也定义了用来查询、插入和删除样式表的规则API。IE8及更早版本实现的API和其它浏览器实现的标准API之间有一些轻微的区别。

直接操做样式表一般没什么意义。典型地,相对编辑样式表或增长新规则而言,让样式表保存静态并对元素className属性编程更好。另外一方面,若是容许用户彻底控制页面上的样式,可能就须要动态操做样式表。

document.styleSheets[]数组的元素是CSSStyleSheet对象。CSSStyleSheet对象有一个cssRules[]数组,它包含全部样式表规则:

var firstRule = document.styleSheets[0].cssRules[0];

IE使用不一样的属性名rules代替cssRules

cssRules[]或rules[]数组元素为CSSRule对象。在标准的API中,CSSRule对象表明全部的CSS规则,包含如@import和@page等指令。可是在IE中,rules[]数组只包含样式表中实际存在的样式规则。

CSSRule对象有两个属性能够很便捷的使用。(在标准API中,非样式规则没有定义这些属性,当遍历样式表时但愿跳过去它。)selectText是规则的CSS选择器,它引用一个描述与选择器相关联的样式的可写CSSStyleDeclaration对象。回想一个,CSSStyleDeclaration是用来表示内联和计算样式的相同类型。能够利用它来查询规则的样式值或设置新样式。一般,当遍历样式表时。你对规则的文本比它解析后的表示形式更感兴趣。此时,使用CSSStyleDeclaration对象的cssText属性来得到规则的文本表示形式。

除了查询和修改样式表中已存在的规则之外,也能向样式表添加和从中删除规则。标准的API接口定义了insertRule()和deleteRule()方法来添加和删除规则

document.styleSheets[0].insertRule("H1 {text-weight:bold}",0);

IE不支持insertRule()和deleteRule(),但定义了大体等效的函数addRule()和removeRule()。(除了名字之外)仅有的不一样是addRule()但愿选择器文本和样式文本做为两个参数。

如下代码遍历样式表样式表的规则,举例说明了用API对样式表进行一些可疑的修改:

。。。。。。

6.3.建立新的样式表

最后,建立整个新样式表并将其添加到文档是中可能的。在大多数浏览器中,能够用标准的DOM技术:只要建立一个新的<style>元素,将其插入到文档的头部,而后用其innerHTML属性来设置样式表内容。可是在IE8以及更早的版本中,CSSStyleSheet对象经过非标准方法document.createStyleSheet()来建立,其样式文本用cssText属性值来指定。请看下面的例子。

。。。。。。

相关文章
相关标签/搜索