dojo(三):样式处理
提到 CSS,很多 Web 开发人员都不陌生。它是在 Web 应用中控制展现的标准技术。CSS 与 HTML 和 JavaScript 一起,构成了 Ajax 应用的基础。对于 CSS,已经有很多图书和文章进行过详细的介绍。本文不介绍 CSS 语法的细节,而是从一些实际开发中会遇到的问题出发,讨论一些与具体实践相关的话题。 下面首先介绍 CSS 中的一些重要概念,可以帮助读者加深对 CSS 的理解。本文中以 CSS 2.1 规范来进行说明。 CSS 的重要概念 CSS 的语法非常简单,包含的元素也很少,主要有“@ 规则”和样式规则集。“@ 规则”是以 声明是 CSS 中样式属性的名值对,其形式是“ 属性继承 对于 CSS 中的某些样式属性来说,如果元素没有显式的指定一个值,该属性就会继承该元素的父元素的这个属性的值。常见的会被继承的属性有: 在介绍完 CSS 的重要概念之后,下面介绍 CSS 规则的层叠顺序。 CSS 规则的层叠顺序正如 CSS 的全称“层叠式样式表(Cascading Style Sheets)”所表示的含义一样,CSS 中的样式声明规则是有层叠顺序的。可以在不同的地方把相同的规则应用在相同的元素上面。比如对某个 P 元素,某条 CSS 规则将其文本颜色设为红色,而另外一个规则把其文本颜色设为蓝色。显然这两条规则是互相冲突的。在具体显示的时候,浏览器会根据层叠顺序来判断应用哪条规则,从而确定该 P 元素的文本颜色。层叠顺序的基本原则很简单,那就是越具体的规则,优先级越高。浏览器根据优先级高低来确定应用哪条规则。具体的来说,一条规则的优先级与其使用的选择器和所在的位置相关。下面分别进行说明。 根据所使用选择器的优先级顺序在判断一条规则的优先级时,会首先判断其所用的选择器的优先级顺序。按照优先级从高到低的顺序排列如下:
当浏览器需要判断应用互相冲突的规则中的哪条规则的时候,首先会根据上面的顺序来判断优先级。优先级高的规则就会被应用。如果优先级相同,则需要进一步判断所使用的选择器的个数。选择器数目较多的规则优先级较高。比如下面两条规则: 如果按照上面的优先级顺序来判断,规则的优先级相同的话(即所用的选择器类别相同,同类选择器的数量也相同),则需要进一步根据规则所在的位置来判断。 根据规则所在位置的优先级顺序对于规则所在的不同位置,可以按照优先级从高到低排列如下:
如果规则所在的位置相同的话,出现在样式表后面的规则的优先级更高。 通过这样的两套规则机制,就保证了浏览器可以解决互相冲突的规则的优先级问题。下面通过一个示例来具体说明层叠顺序的机制。 层叠顺序示例演示层叠顺序的示例所使用的 HTML 和 CSS 如代码清单 1所示。 清单 1. 层叠顺序示例<style> * { color : black; } p { color : gray; } .p_red{ color : red; } p.p_blue { color : red; } #p1 { color : green; } .p_blue { color : blue; } .p_blue2 { color : blue !important;} </style> <body> <p id="p1" class="p_red"> 示例文本 1</p> <p class="p_red"> 示例文本 2</p> <p class="p_blue"> 示例文本 3</p> <p class="p_blue p_blue2"> 示例文本 4</p> </body> 如代码清单 1所示,HTML 文档中定义了 4 个 P 元素以及一些 CSS 规则用来定义其文本颜色。对于第一个 P 元素来说,可以应用在之上的有两条规则:一条是通过 ID 选择器定义的,另外一条是通过类选择器定义的。由于 ID 选择器优先级高,第一条规则被应用,所以文本颜色是绿色;第二个 P 元素只能应用一个类选择器,所以文本颜色是红色;第二个 P 元素有两个规则可以被应用。规则 对于上面提到的两套规则机制,一个重要的例外就是用户样式表中的包含的带 熟悉了 CSS 规则的层叠顺序之后,就可以解决常见的 CSS 样式被覆写的问题。很多时候,尤其在团队开发中,一个 CSS 文件可能被多个开发人员修改。经常会遇到的一个问题是,自己的 CSS 样式没有起作用。通过 Firebug 可以发现,原因是自己的 CSS 样式被其他人写的样式给覆写了。根本原因是自己样式声明中使用的选择器的优先级较低。解决这个问题的办法就是查看与你的样式发生冲突的 CSS 规则所使用的选择器,并相应提升自己的选择器的优先级,防止自己的样式被覆写。 在介绍完 CSS 规则的层叠顺序之后,下面介绍 CSS 布局中重要的概念:盒模型。 回页首 盒模型盒模型(box model)是 CSS 中进行页面布局的重要概念。页面上文档树中的每个元素在显示的时候,都会对应生成一到多个矩形盒子。布局是根据这些盒子来进行的。盒子之间可以互相嵌套。对于一个元素来说,其产生的盒子如图 1所示。 图 1. CSS 的盒模型示意图 从图 1中可以看到,一个盒子从里到外有四个层次:最里面的是内容区域,包含元素本身的内容;紧接着是填充区域;然后是边框;最后是空白区域。内容区域的宽度和高度的确定比较复杂,需要综合考虑样式 在介绍完盒模型之后,下面介绍如何对页面上的元素进行布局和定位。 回页首
布局和定位浏览器在渲染 HTML 页面的时候,所进行的操作就是把上面提到的文档树上的元素所对应的盒子,按照一定的规则进行排列。下面将详细介绍布局的规则以及元素是如何在页面中定位的。 盒子类型 不同的盒子类型在布局时的行为不一样。盒子的类型是由生成它的元素的类型来决定的。通过样式
包围块 在对页面上的元素进行定位的时候,包围块(containing block)是个很重要的概念。很多时候都需要根据其包围块来确定某元素对应的盒子的位置和大小。包围块的确定并不复杂:对于文档根元素,其包围块是浏览器的窗口;如果元素的样式 元素的定位由样式 在 CSS 中,一个盒子可能有三种定位方式:正常文档流、浮动和绝对定位。通过样式 正常文档流正常文档流是按照盒子的类型来定位的。每个盒子都会属于某个格式化上下文中,块或是行内的。块格式化上下文会按照从上到下的垂直顺序来排列盒子。行内格式化上下文则按照水平顺序来排列盒子,从左到右还是从右到左取决于文档的顺序。 通过将样式 浮动定位 通过将元素的样式 浮动的盒子不属于正常文档流的一部分。在浮动盒子之前和之后的非定位块盒子按照其在正常流中的位置排列,相当于浮动盒子不存在一样。而浮动盒子之后的行内盒子则会被缩短,紧跟在浮动盒子的后面。所形成的效果就是后面的行内盒子包围着浮动的盒子。在网页中文字环绕图片的效果就可以通过这种方式来实现。通过样式 绝对定位 将样式 在介绍完 CSS 中的布局和定位之后,下面介绍如何解决不同浏览器之间 CSS 样式的兼容性问题。 浏览器兼容性在使用 CSS 为网页添加样式的时候,不得不面对的一个棘手的问题就是浏览器的兼容性所带来的复杂性。不同的浏览器对于 CSS 规范本身的理解,以及具体的实现都有很大不同。浏览器本身还可能存在各种各样的 bug。在 Firefox 上面显示正常的网页,用 IE 打开的话就可能发现整体的布局错位。相同浏览器的不同版本之间的差别也会很大。开发人员需要花费大量的时间和精力来保证网页在各种浏览器上呈现的样式是一致的。一般来说,解决浏览器兼容性问题有三种做法:利用浏览器本身的支持、使用招数和使用 JavaScript。下面先介绍浏览器本身的支持。 浏览器本身的支持可以利用浏览器本身支持的能力,在一定程度上解决兼容性的问题。比较典型的是 IE 提供的条件注释。通过条件注释,可以在页面由特定版本的 IE 来显示的时候,设置特殊的样式,如代码清单 2所示。 清单 2. IE 提供的条件注释 <!--[if IE 6]>
<style type="text/css">
span {
color : red;
}
</style>
<link rel="stylesheet" href="ie6.css" type="text/css">
<![endif]-->
代码清单 2中条件注释中包含的样式和引入的 CSS 文件 招数 招数(hack)是利用浏览器本身对 CSS 规范支持的不完善或是实现上的 bug,来针对特定的浏览器应用样式的一些做法。这些招数通常用来满足这样的需求,即对某个或某些浏览器应用特定的样式。IE 6 不支持直接后代选择器,即不识别 清单 3. 招数示例 div span {
margin-left : 20px;
}
div > span {
margin-left : 10px;
}
如代码清单 3所示,首先通过浏览器都支持的后代选择器来设定样式 一般来说,可以使用的招数分成两类:一类是利用浏览器对 CSS 规范支持的不完善,如上面给出的直接后代选择器的例子;另外一种是浏览器本身实现的 bug,也就是说浏览器没有按照预期的行为来工作。比如 IE 6 不认为 由于招数可能随着浏览器的升级而变得不可用,建议只在必要的时候才使用它。需要使用招数的时候,也尽量借助已有的CSS 框架。下面介绍使用 JavaScript 代码来解决兼容性的问题。 使用 JavaScript在有些时候,单纯依靠浏览器本身的支持,以及已有的招数,并不能完全解决 CSS 样式在不同浏览器上面的兼容性问题。这个时候可以通过 JavaScript 来解决。通过 JavaScript 可以判断当前的浏览器类型,从而应用不同的样式。一般来说,有两种典型的实现方式。 一种做法是直接在 JavaScript 代码中修改 CSS 样式。很多 JavaScript 库都提供了这样的能力,如 Dojo 就提供了很好的支持。对于上面的例子,用 Dojo 解决的做法如代码清单 4所示。 清单 4. Dojo 的浏览器检查与样式修改 if (dojo.isIE == 6) {
dojo.style(node,"marginLeft","20px");
}
如代码清单 4所示,Dojo 提供了浏览器检测和直接修改 CSS 样式的功能。这样的话,在 CSS 里面只需要添加对绝大多数浏览器都适用的样式声明。对于个别浏览器的少量样式调整,可以在 JavaScript 代码里面来完成。相对于直接修改样式来说,另外一种更好的做法是添加额外的 CSS 类声明,如 另外一种做法是用 JavaScript 为页面根元素添加一个特殊的 CSS 类。比如用 IE 6 访问使用了 Dojo 的页面,页面根元素会添加 CSS 类 清单 5. 为页面根元素添加 CSS 类 .dj_ie6 {
margin-left : 20px;
}
在介绍完浏览器的兼容性问题之后,下面介绍如何开发出可维护的 CSS 文件。 可维护的 CSS前面提到过,CSS 本身的语法非常简单,包含的元素非常少。但是要编写模块清晰,可维护性高的 CSS 样式表,并非一件容易的事情,尤其对于样式繁多的复杂站点来说。一种比较好的解决办法是把面向对象的思想引入到 CSS 样式表的编写过程中,用它来指导 CSS 样式的组织。具体的指导原则有组件化和单一职责。 组件化 用面向对象的思想解决复杂问题的一种常用做法是组件化,即把复杂的对象拆分成若干小的组件。每个组件相对独立,用来解决更小的问题。这样既降低了组件的开发难度,也提高了复用性。具体到 CSS 样式表来说,就是开发出针对页面上某类元素的样式组件。这些样式组件可以在不同的页面中任意组合使用。常用的样式组件有针对标题( 单一职责在面向对象的开发中,通常鼓励的一种实践是为每个对象分配单一的职责,从而使得它只会因为一种原因而改变。这种实践对 CSS 样式表也适用。具体来说就是把结构和外观分开,让它们分别变化。比如网页上的一个窗口小部件,从结构上来说,需要定义其标题栏和内容区域的大小和位置,还有右上角的按钮的位置;从外观上来说,需要定义文本的字体大小、颜色以及背景图片等。通过把描述结构和外观的样式分开,可以提高可维护性。当需要为窗口小部件提供一套新的配色方案时,只需要修改外观样式即可。 多文件组织 如果使用上面提到的面向对象的思想来组织 CSS 样式表,会得到多个 CSS 文件,每个文件里面包含一到多个样式组件。多个 CSS 文件相对于单一文件来说,可读性和可维护性都更好。在开发新页面的时候,只需要根据页面内容的需要,引入包含所需样式组件的 CSS 文件即可。通过 清单 6. 引入多个 CSS 文件 @import "heading.css"
@import "list.css"
@import "widget.css"
以分开的方式单独引入多个 CSS 文件可能会带来性能上的问题,对此可以使用工具来进行压缩。 在介绍完可维护的 CSS 之后,下面介绍一些帮助开发 CSS 的框架和工具。 框架与工具在编写网页的过程中,使用已有的成熟的 CSS 框架与工具,可以减少开发的工作量,也更容易解决浏览器的兼容性问题。下面介绍一些常用的 CSS 框架和工具。 YUI CSS作为 JavaScript 库之一的 YUI 也提供了一些基础的 CSS 样式,可以供开发人员使用。这些样式分成三类,分别是重置 CSS、字体 CSS 和基本 CSS。通常来说,浏览器会为网页提供一个默认的样式表。如果开发人员的样式表中没有定义某些属性的值的话,浏览器在显示的时候就会使用自己的样式。不同浏览器的默认样式是不同的,这样会导致网页在不同浏览器上的显示有所不同。重置 CSS 的功能就是通过显式的样式声明,来覆写浏览器的默认样式。开发人员的样式表以重置之后的样式作为基础,就保证了不同浏览器上的一致性。YUI 提供的重置 CSS 只是一个简单的 CSS 文件,可以直接在网页中引用。YUI 字体 CSS 可以为网页设置默认的字体,以及调整字体的大小。YUI 基本 CSS 为一些常用的 HTML 元素提供了基本样式。关于 YUI CSS 的更多信息,见参考资料。 Blueprint Blueprint 是一个复杂的 CSS 框架,提供了多个 CSS 文件,所提供的样式包括重置、网格、字体、表单、IE 支持和打印等。这里值得一提的是它的网格样式。绝大多数网页采用的都是某种网格型的布局,比如常见的两列布局和三列布局等。对于简单的两列或三列布局,通过简单的 CSS 样式就可以实现。如果列的数目过多,或是存在嵌套列的话,自己开发和维护的代价就太高了。使用 Blueprint 的网格样式可以很容易的实现,并且可维护性和灵活性更好。Blueprint 的网格样式提供了 24 个列。元素可以选择横跨任意多个列。比如只需要为元素添加 CSS 类 CSS 文件压缩相对于 JavaScript 文件的压缩来说,CSS 文件的压缩并没有那么的流行。其原因可能是一般网站的 CSS 文件数量较少,单个文件的体积也较小。相对于 JavaScript 文件来说,CSS 文件对性能的影响要小得多。但是如果应用上面提到的可维护的 CSS实践的话,会产生较多的 CSS 文件。过多的 CSS 文件意味着过多的 HTTP 请求,对网站性能会有较大的影响。目前已经有不少的工具支持对 CSS 文件的压缩,如 YUI 压缩器和 Minify(见参考资料)。 在介绍了其它的 CSS 框架和工具之后,下面介绍 Dojo 提供的对 CSS 的支持。 Dojo 的支持Dojo 对于 CSS 的支持,主要体现在修改元素的样式、获取元素的定位信息和辅助页面布局上。下面分别加以介绍。 修改样式Dojo 提供了一些方法用来对 Ajax 应用中元素的样式进行修改。 一般推荐的做法是不直接设置样式的值,而是修改元素的 CSS 类,这样 CSS 样式规则的可维护性更好。Dojo 也提供了几个方法用来修改元素的 CSS 类,分别是: dojo.addClass(node,classStr)用来添加新的CSS类。 dojo.removeClass(node,classStr)用来删除已有的CSS类。如果第二个参数为空的话,则删除所有的CSS类。 dojo.toggleClass(node,classStr,condition)用来切换CSS的出现状态。如果元素已有了classStr指定的CSS类,则删除掉这些类;否则的话就添加这些类。参数condition用来显示的声明是添加还是删除,传入true表示执行添加操作。 dojo.hasClass(node,classStr)用来判断元素是否已经包含了某些CSS类。 获取定位信息 在有些时候,需要用 JavaScript 来获取和设置页面元素所对应的盒子的大小和位置。Dojo 提供了两个方法 辅助页面布局 在进行页面设计的时候,通常会使用一些经典的布局样式,比如常用的“标题栏 + 侧边栏 + 内容 + 底部栏”的布局。这些布局使用手工编写的 CSS 样式或是Blueprint都可以很容易的实现。如果网页中使用了 Dojo 的话,利用它提供的布局容器组件是个不错的选择。它可以很好的与网页上的其它 Dojo 组件结合在一起。布局可以使用的容器组件是 清单 7. 使用 Dojo 实现的布局 <div dojoType="dijit.layout.BorderContainer" style="width:400px;height:300px;">
<div dojoType="dijit.layout.ContentPane" region="top">
<div> 标题栏 </div>
</div>
<div dojoType="dijit.layout.ContentPane" region="left" splitter="true">
<div> 侧边栏 </div>
</div>
<div dojoType="dijit.layout.ContentPane" region="center">
<div> 内容 </div>
</div>
<div dojoType="dijit.layout.ContentPane" region="bottom">
<div> 底部栏 </div>
</div>
</div>
如代码清单 7所示,通过属性 总结正如之前一直说到的,CSS 本身语法非常简单,但是要在复杂的 Ajax 应用中合理的编写和组织 CSS 样式表,是需要很多经验积累才能做好的一件事情。本文并没有对 CSS 的语法细节做过多的介绍,而是重点说明了 CSS 语法中复杂的部分。除此之外,还讨论了 CSS 样式表的浏览器兼容性问题的解决办法。接着介绍了编写可维护的 CSS 的一些原则。最后介绍了 CSS 框架和工具,以及 Dojo 中与 CSS 相关的内容。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |