生为程序员,死做程序鬼
.NET开始,JavaScript结束?

前言我挣脱了 DOCTYPE 的魔咒,让那些看似残缺的布局在 IE7+ 中获得了重生,可我一不小心又成为id的傀儡,您将会看见一个迷失在id的“层叠和特殊性”上的我,纵使实现了想要的布局效果,却缔造了一个臃肿的CSS文件,难道这真的是我想要的吗?

      在看这篇文章之前,我友善的提醒您,如果您不喜欢看长篇大论,那么我建议您,直接通过下面的目录挑选自己感兴趣的内容,点击链接就会跳转到文章中指定的部分。当然,我最大的愿望是您能用心把整篇文字认真看完,就如同我用心写这篇文字时一般,衷心感谢您的阅读,希望您收获满满!

知识点目录:

 

     额混混的上篇终于完结了,也不知道自己罗列了多少个字符,如果您还没有阅读过上篇中内容,建议您受累花点时间粗略的看看吧。您或许会反问道:“看此文为何要看上篇中的内容啊!”真不好意思,我本想把文章内容之间的“耦合度”尽量低一些,让内容之间的关联被稀化,最好能做到各自成章。不过吾能力有限让您失望了,此文与上篇之间依然存在着藕断丝连的关系,请您听我细细道来。

     在上篇中,我破解了DOCTYPE 的魔咒,使得三列布局在 IE7+、Firefox3.0+、Chrome2.0 等现代浏览器上一统江湖,如果身处江湖,就脱不了江湖,我只好硬着头皮向前冲,没有回旋的余地了。就在我刚刚挣脱 DOCTYPE 魔咒的同时,外包给美工的百克网新版首页的静态页面终于辗转到我手中。既然是工作,首先保证把活干好,稀里哗啦的按照要求做完本职工作,百克网新版首页在几个小时之后从静态变成了动态并且上线正式使用了。这样一来,老板高兴,我也高兴了,这样一来我暗地里为自己重构首页赢得了更多的可控时间。

     2009年3月7号晚,我终于走完了重构长征路上的第一步,百克网的第一个遵从Web标准设计的首页(您可以通过点击该链接下载静态文件的源码,包括HTML、Images和CSS文件)在我的电脑上诞生了,不过它只是静静地躺在本地硬盘上,在本地的IIS服务器中偶露峥嵘罢了。

     如果您还记得我在上篇提到过,这次重构被我定义为一次“龌龊”的重构,“龌龊”从何而来,理当从束缚中来。我就像一个被捆绑了手脚的泳者,在泳池里凭借着意念控制全身,希望通过挣扎来摆脱束缚,可我发现这样做是徒劳的。外包的美工出图并设计好了静态页面,采用了他熟悉的 Tables 布局,这一切就是束缚的开始,这位外包美工身在何处我不从而知,也从未与之沟通过,他的切图均是建立在使自己的布局更加方便的基础之上。而我,却冥思苦想如何挣脱切图所带来的束缚获得重生的机会,越挣扎我越感到无助的痛,自己一时半会是不大可能将支离破碎的切图还原成一张高质量的PSD格式的平面设计图,也就不可能按照自己的布局需求重新切片。罢了,我不是黄蓉,也不是美工,这些愁苦不想也罢,既来之,则安之,拿来就用,就地取材,我就从那些不太满意的切图开始重构之旅吧,即使在您看来这或许不够“龌龊”,可蜗居在我心底深处的欲望之虫,已经快要“龌龊”至死了,呵呵。

     重构的第一步,已经在上篇中完成,三列布局的基调不变,其后的工作就是重新组织页面上的文档和其他元素,如何将抽象出来的布局与页面上重要的信息元素重新完美的揉合到一起,成为我其后工作的中心。此刻,让我完全还原当时的思考过程已经不大可能了,因为思考一直没有停息,越来越多的错误在被自我纠正。

     来吧,先看看我重构之后的百克网首页效果如何,再做评论吧!

                                                                                            图片1

     细心的您,发现图片1与在线运行的百克网首页有哪些不同吗?您不妨点击百克网,将打开的新窗口中的画面与图片1稍微比对一下,您或许已经发现两者很多细微的不同,如果您赞同从图片1的表现力上来看,比正在运行的百克网首页更具亲和力的观念,那我会笑的很灿烂,因为付出得到认可,必常乐啊。当然,如果您乐意指出感受到的更多不同,我将报以更多的微笑和谢意。

     看完了最终的效果图,紧接着来看看图片1背后所隐藏的 HTML 源码吧。在此之前请允许我向您提一个小小的要求,请通过任何一种您熟知的方式快速查看一下正在运行的百克网首页的 HTML 源码,之后请展开下面所贴出的 index.html 源码示例,将两者简单的比较一下吧,您是否有会有新的感观呢?

index.html 示例代码


     OK,如果您不太熟悉如何从浏览器缓存的历史文件中获取上线运行的百克网首页外部引用的CSS文件,那么请您点击此处下载mainStyle.css,然后请用记事本打开,并与下面贴出的 Style090308.css 样式表相互比较一下吧,您是否也会有新的感触呢?

Style090308 样式表示例

     小提示:如果您觉得看这些示例代码是件苦差事,那么我可以告诉您一个更好用于分析页面文档结构的方法。请您下载最新的简体中文版 Firefox 浏览器,然后为 Firefox 浏览器安装 Firebug 插件,之后在 Firefox 浏览器的工具条中点击“工具(T)”——“Firebug”——“查看元素”,当然也可以通过 Ctrl + Shift + C 的快捷方式直接在 Firefox 浏览器中启动查看页面 HTML 文档的工具。好了,剩余的工作就请您在 Firefox 浏览器中点击重构后的百克网首页,然后按照上面的操作步骤开启工具慢慢的观摩一下 HTML文档结构吧。

    
     有一个声音,又开始在脑海里回荡——为什么要重构?是啊,我的重构动机在那里,是为了证明能让别人设计的页面在自己手中变得更有亲和力吗;是为了在实践中积累更多符合 Web 标准布局的能力吗;是为了让重构之后的页面瘦体裁衣便于维护吗;是为了克服自己对 Tables 布局的的恐惧吗。到底页面重构后,我又得到了些什么?尝试清点一下所谓的战利品,是否能逆向探究出重构的动力之源呢,来吧,请您倾听我的陈述,哪怕它显得有点冗长。  

1. 瘦身的 HTML 文档

   1.1 语义、结构化真的重要吗?    Top

     重构前的百克网首页采用传统的 Tables 布局,因大量使用 table 标签致使 HTML 代码中内置太多用于表现元素样式的标签属性,无意之间增加首页 HTML 文档的大小,进而会占用了更多的带宽,这是因为浏览器每次响应 HTTP 请求时,都会重新下载 HTML 文档,内置在文档中的标签属性当然也逃脱不了重新下载之列。如何让 HTML 瘦身自然成为重构过程中不可或缺的环节,那么,就请您动手尝试去掉那些不必要的标签属性,改为外部引用CSS文件来控制元素的表现;尽量尝试正确使用标签所表达的语义,合理构造 HTML 文档。

     这么做的理由很简单,外部引用的CSS文件会被浏览器首次下载之后缓存于本地的某个文件夹内,当同一个页面再次发出重复的 HTTP 请求后,您最乐于见到的情况出现了,浏览器首先会从本地的缓存文件夹寻找指定的CSS文件,如果该CSS文件不存在的话,才会重新从服务器上下载。同样的道理,JavaScript脚本和指定类型的图片文件均会被浏览器缓存于本地,但是这种缓存机制并不是无条件执行的,您可以亲手打破这个机制,让每一次 HTTP 请求都重新下载所有页面文件,当然这么做是否有必要,就看您的需求所定了。还有一种异样的声音存在,他们代表着因外部引用 CSS 文件和 JavaScript 脚本文件引起的多次 HTTP 请求是否合理的争议之声,对此我保持缄默,时间会证明一切。

     重构之后的百克网首页采用了Without Tables的布局设想,正确使用标签的语义让我获得结构较为清晰的 HTML 文档,其 17KB 的大小与上线运行的百克网首页所生成的 27KB 大小的文档相比,可谓瘦了一圈。同时,重构后的首页用到的图像文件数量也从 47 个锐减至 34 个,所有图像文件大小也从重构前的 265KB 缩减至重构后的 255KB 。在重构过程中,我通过样式表来定义表现区域的背景色,进而摒弃了重构前采用图片平铺的方式;我最大限度挖掘如何重复利用同一张图像文件实现页面的表现效果,并挥起大刀砍去了多余的图像文件,一场持久战暂时结束了,我也感觉有点累了,显然我获得了阶段性的胜利,不是吗?

     不知您是否注意到上一段话中,我用来陈述自己重构后页面文档结构的措辞——较为清晰。为何只是较为清晰呢,如何验证这一结论呢,请您先去掉外部引用的CSS 文件,看看重构后的页面效果,然后再去掉所有引用的图像文件,还原一个干净纯粹的 HTML 页面。是的,页面在您的眼中的确有点凌乱,但是页面中的文字信息基本按照当初我设想的重要程度的依次从上至下排列,这样做的目的又是为何呢?您不用奇怪我的自问自答,在二十一世纪的今天,浏览网页不再只是个人电脑上的各种浏览器的专利,许多手持移动设备和一些屏幕阅读器都可以用来畅游我们的 Web 世界,那么如何让这些设备识别自己编写的网页呢,很简单,您只需要依据 Web 标准中规范的语义组织页面结构,您的页面就有可能类似于刚才看到的画面(如果您按照上述我说的步骤去操作后看到的画面)一般排列显示在上述的各种设备中,而我正努力尝试着这样去做。坚信不远的将来,大多数人不再选择正襟危坐在自己的电脑面前,通过点击浏览器上的网页来获取信息,大家都会选择在各种各样复杂的场合通过一些移动设备上网“冲浪”,那么您的网站是否具有更好的可用性和可访问性将决定着是命运的未来,听起来仿佛很遥远,哦,那只能说您信息真的太闭塞了。

     经我重构之后的 HTML 文档是否真的做到结构化良好呢?不然,因为切图带来的束缚,为了弥补图片之间 1px 的缝隙效果,我在文档中多处使用破坏结构化的 div 元素,从而让我看起来像一位 Divitis 患者,至于我所说的“多处”指代何处,您不妨将上面的“index.html 示例代码”拷贝到文本编辑器中一探究竟,我相信这样做对您是有好处,如果您能帮我挑出更多破坏结构化的地方,将万分感谢。

     当然,破坏良好结构的因素不止一项,你在 HTML 文档中发现“热区”了吗,哦,您或许对“热区”的概念不太熟悉,没关系,作为僧者的吾曰:请您在浏览器的地址栏中输入g.cn,然后在打开的页面中找到唯一可输入的框内填写上“HTML 热区”,点击搜索,将会发现更多关于“热区”的有用信息。您可以用同样的方法搜索关于“marquee”标签元素的信息,这个标签像个特殊的婴儿,从来就没有被人抚育似的,没人疼没人爱,也没有标准支持他。您是否奇怪过,为什么他在所有现代浏览器上都能正常表现,他是如何破坏文档结构的呢?我不禁要问,您不觉得这个标签让其包含在内的元素滚来滚去的方式更像在执行一种行为吗?既然是行为方式,为什么不在更符合标准的行为层来处理呢?噢,对了,遗漏了一个家伙,img 标签你很熟悉了吧,可您是否知道在未来的 W3C 标准中他或许会被 object 标签所替代,你要是真的仔细看过“index.html 示例代码”一定会奇怪我为何会在每一个 img 标签的后面,用“ />”替代了“ >”,如果您在仔细点,会诧异我为何在所有的 img 标签元素中,都包含了 width 和 height 这两个用于表现的属性,好的,别再抱怨我这种卖关子的行为了,下面我将揭晓答案。

     我们回头看看,“热区”是否也可以被结构化呢,答案是肯定的,Andy Budd 早已悄悄传授于我这样的技巧,您想知道是怎么做的吗?我有两个很好的选择给您:一是守候《你重构过自己的页面吗?——为何不标准彻底一点呢!》的发布,里面描述着我如何继续重构百克网首页,也会详细介绍我是如何把“热区”结构化;二是您亲自动手去查阅 Andy Budd 的大作《CSS Mastery》中“创建 CSS 图像映射”一节,Andy 会用更易理解的方式向您展示此项技术。同样的,我会在行为层中,利用 JavaScript 实现无缝的滚动显示,并且尝试当您禁止掉浏览器执行 JavaScript 时,我会将“marquee”作为后备重新引回您的浏览器。最后,我会小声告诉您在使用 img 标签时中为何会加上了 width 和 height 属性,这是 Jennifer Niederst Robbins 女士传授于我的技巧,在当前还无法用 object 标签完全替代 img 标签时,我们如何挖掘 img 标签的最大能量呢,通过为其加上 width 和 height 属性可以加快页面上的图像文件在浏览器中渲染的速度,至于效果如何建议您找来大量的图片,可以专门制作一个用于显示这些图片的页面,测试一下这个技巧是否有用。您可能会问,为何不为每一个 img 标签设置 id 属性,然后在 CSS 文件中通过样式表来设置他们的 width 和 height 属性呢。恩,我也曾想过,但是真那么做后感觉怪怪的,于是我听从 Jennifer 前辈友善的建议,并且从有利于带宽的角度来考量,我从样式表中删除掉了为 img 元素抒写的只包含 width 和 height 属性的定义,于是重构之后的 HTML 文档中就多了些难得一见的用于表现的标签属性。

  1.2 收获的经验和技巧     Top

     经验:为了能编写出良好结构化的文档,请您不要一味的先写上 <div>[……]</div>,然后再向其中添加更多的标签元素和文档内容,这样做最终受累只会是您自己。在我看来,更为合理的做法是,先尽量使用准确的语义描述文档中的内容,至于如何来做,需要遵循一些通用的规则,例如:

 *  段落的标题应该包含在 <h1>[……]</h><h2>[……]</h2> 等标签元素之间;
   
 * 不要只为了让段落的一级标题的字体显得更小巧一些,而用将  
<h1> 标签改为 <h3> 标签,这是破坏语义的做法,字体的大小是表现层的事,应通过样式表来控制;
    
 * 段落的文本内容应该使用 
<p>[……]</p> 标签包含,切记不要将文本内容直接裸露在 <div>[……]<div> 元素之间,这样做等同于孩子没有了父母,成为了没人爱的孤儿,这难道不是破坏良好结构的要素吗;
    
 * 永远不要在 
<p>[……]</p> 标签中嵌套 <p>[……]</p> 标签,这是游戏的规则,我们必须遵守。同样的,规则也不允许我们向 <span>[……]</span> 这样的内联元素中嵌套块级元素;
    
 * 如果文本是类似于诗歌这样的具有文本缩进等预定义格式的内容,那么请您将它们包含在 
<pre>[……]</pre> 元素之间;
    
 * 段落中条理性较强的内容可以通过列表元素
<ul><ol><dl>等进行分组,并由此给这些内容添加语义和结构;

         当您将页面上的文档内容按照上面的建议组织完毕时,是否会感触到页面就像一位五官端正的“素颜”(我觉得这个词汇非常恰当,正如一个美丽动力的妙龄女子,如果卸妆之后依然婀娜多姿,势必会更加吸引人)女子,外表朴实无华却有着优美身段呢?如果您的回答:是,那么恭喜您,已经掌握要诀了。如果您希望把相关性很强的内容聚合到一块时,就可以动手将它们包含在一个泛型的 div 元素之中了,所有内容按照设想的次序紧密的排列着,这一切或许会让人感觉很乏味,那么您要做的就是通过编写样式表将这些块和其中的内容,按照自己的奇思妙想呈现在屏幕上,好比您正给一位“素颜”的女子化妆一般。

          技巧:请您仔细看看图片2中所呈现的情况,滚动显示的文字内容恰好垂直居中于黄色背景之间,如果是您来设计又会如何实现这个效果呢?
         
                                                       图片2

          那么,先来看看目前我是如何实现的,HTML 代码片段如下:

    <div id="marqueeInfobg2_mid">
         
    <marquee scrollamount="2">
        
    <id="international_market"><strong>WTI</strong><em>43.61</em><em class="priceGreen">-1.77</em><strong>布伦特</strong><em>43.64</em><em class="priceGreen">-2.48</em></p>
          
    </marquee>
    </div>

        
         CSS代码片段如下:

    .priceRed { color: #FF0000; }
    .priceGreen 
    { color: green; }

    #marqueeInfobg2_mid
    {
         width
    :423px;
         height
    :33px;
         background
    : #FFFDF1 url(../images/info_bar02.jpg) repeat-x;
    }

    #marqueeInfobg2_mid p#international_market 
    { height:24px; margin-top:10px; white-space:nowrap; }    
    #marqueeInfobg2_mid #international_market strong 
    { margin:0px 10px 0px 12px; color:#FF6600; font-weight:normal; }
    #marqueeInfobg2_mid #international_market em 
    { margin:0px 10px 0px 0px; font-style:normal; }


         从上面展示的 HTML 代码片段中,您可以看出我将滚动显示的文本信息包含在一个 id 属性值为 international_market 的 p 元素之中,并利用 <strong>  和 <em> 标签的语义,分别将文本中重要的信息使用“特别强调”(<strong>)和“一般强调”(<em>)作为标记将信息分别包含起来,然后通过编写 <strong> 和 <em> 标签元素的特殊样式来控制文本的间距和颜色。注意了,<strong> 和 <em> 标签在几乎所有浏览器中默认的样式都是黑体和斜体,这只是浏览器的默认的表现方式罢了,与它们自身的语义无关。

         在描述经验时,我已经向您阐述过若干的规则,或许您也记住了不要将文本内容直接裸露在 div 元素之中,当然,我在这里额外的提及,不要简单的设想直接通过 div 元素的 padding 属性控制裸露文本内容垂直居中于 div 元素之间那么看看我的实现方式如何,用 <p> 标签元素包含文本内容,将其嵌入到 div 元素之中,控制 <p> 标签元素的 margin-top 属性,用于调整其与 div 元素之间的垂直距离,这样就很轻松地将文本内容垂直居中了,在几乎所有的现代浏览器上,您将获得几乎一直的表现效果,不信您就试试看,这应该算是一个合理的技巧吧。

         这里需要说明一点,最好是将 <p> 标签元素的高度设置为至少能够完全显示文字的高度,因为 Firefox3.0 需要您这样做,我在测试中发现如果您去掉 #marqueeInfobg2_mid p#international_market { height:24px; margin-top:10px; white-space:nowrap; } 中的 height:24px 属性值,那么您在Firefox3.07 上将看见一个奇怪的表现——字体在垂直方向无法完全显示,而在其它如 IE7+、Chrome1.0+、Opera9.5+等现代浏览器上表现却完好无缺。

         其实还有很多细节上的处理,体现出了一些有价值的技巧,也还有太多的经验值得总结,由于篇幅被我拉的太长,这里就暂时不在叙述了,留待以后专门撰文陈述吧。再此我以表声明,这里收获的经验和技巧仅建立在个人实践之上,如有错误还望请纠正,也欢迎您与我探究更好的实现方式。

    2. 臃肿的CSS代码

          2.1 为何爱上 id     Top

        摒弃表现层的 HTML 代码,放弃了Classitis(一种为了每一个需要特殊处理的元素就附加一个类的做法的统称)和Divitis(上篇已提到过),不要因为失去了它们而恐慌如何表现自己的布局,您甚至不禁要问放弃了它们,我们还剩什么,当然,我们还剩那可爱的 id 属性。从我初步重构后的 HTML 文档来看,大量使用了标签的 id(唯一标识符) 属性,几乎见不到 class 属性,是的,我爱上了 id,因为她是无害的。

      id 属性将在未来的 Web 标准中被赋予每一个标签元素,而现在的 HTML 4.01 中也只有少量的如base, head, html, meta, param, script, style, 以及 title 元素不提供 id 属性。使用 id 属性的理由,嗯哼,我来帮您想想——我们不是一直在尝试编写结构化的 HTML 文档吗,通俗的说就是将文档中的内容通过普通的标签元素进行标记,而这些元素通过特定的结构化属性标志来指示出它们在网站设计中所扮演的语义角色。那什么是“特定的结构化属性标志”呢,没错,可爱的 id 属性就是了,她惊人的魔力会给每一个标签元素烙上一个唯一的、元结构化的标记,有了这个标记你就可以在一个分离的样式表内为干净的、紧凑的标记代码进行特别的表现层处理了。

          2.2 重温如何编写CSS     Top   

          恩,您是否有那么一点点感觉,在 CSS 文件中,您是如何编写那些选择器的呢?哦,好吧,暂且假设您还不明白什么是样式表、选择器,借用 Zeldman 的方式简单的给您解释一下或许就明白了。样式表简单的说就是由一个或多个规则定义组成,这些定义控制着被选择的元素将如何显示。一个完整的CSS定义由两部分构成:选择器和声明。

         例如 p { color: #FFF; } 中, p 就是选择器,而在大括号内的 { color: #FFF; } 就是声明了。相应地,声明也由两部分组成:属性和值,采取正是程序员们非常熟悉的键值对形式,上面 color 就是属性,#FFF 是十六进制值 #FFFFFF 缩写而来的属性值。一般会将规则中只使用了标签元素的选择器统称为“元素选择器”或者“类型选择器”。

         好了,有了上面的基础,我可以大胆的引入“id 选择器”了,其形似 #elementID { font: 12px/14px Verdana, sans-serif, "Times New Roman"; } ,很好您需要明白 elementID 指代的是元素的 id 属性的值,而规则如何定义的,我想您已经看明白了。

         最后,我隆重的向您介绍“class 选择器”,也叫“类选择器”,其形似 .className { color: #123; background-color:#FFF; } ,同样您需要明白 className指代的是元素的 class 属性的值。

         对了,要想让您看懂我抒写的 Style090308.css 样式表,还有一个名字不得不提及,它就是锚伪类选择器。下面我给出一段示例代码,您稍微体味一下,就能明白其中的奥妙了。

    /*将所有未被访问过的链接设置为蓝色*/
    a:link 
    { color:blue; }

    /*将所有已被访问过的链接设置为绿色*/
    a:visted
    { color:green; }

    /*当鼠标悬停或被选定时将链接设置为红色*/
    a:hover, a:active
    { color:red; }

    请注意,在阅读上面的CSS代码时,您是否注意到a:hover, a:active
    { color:red; } 这种写法所描述的意义——当页面上的几个元素共享样式属性时,用逗号分割,这种选择器被称为“群选择器”。

    在 CSS 定义中,a:hover 必须被置于 a:link 和 a:visited 之后,才是有效的;a:active 必须被置于 a:hover 之后,才是有效的。


         2.3 层叠和特殊性     Top

         有了上面这些基础知识,您回头再看 Style090308.css 样式表,是否底气十足了,什么,您还是有很多地方看不大懂吗?哦,别着急,我会继续给您介绍一些关于样式表的有趣话题。

         2.3.1 层叠     Top

         您是否尝试过在同一个 CSS 文件或不同 CSS 文件中,编写两个或更多的规则去控制同一个元素。CSS 是通过一种被称为层叠(cascade )的机制处理这种冲突,它会给每个规则分配一个重要性,其基本原则如下:

    * 一般来说,页面设计者所编写的样式表被认为是最重要的;
    * 其次是用户根据自己需求编写的样式表;
    * 最后是浏览器/用户代理应用的默认样式表。


    为了让用户有更多的控制能力,可以通过将任何规则制定为 !important 来改变用户样式表的重要度。那么,通过标志 !important 后层叠机制会按照下面重要度从上至下依次排列:

    * 标记 !important 的用户样式;
    * 标记 !important 的设计者样式表;
    * 设计者样式表;
    * 用户样式表;
    * 浏览器/用户代理应用的默认样式表。


         嗯哼,您可能要问“用户样式表”是什么呀,好的,我将以 IE 浏览器为例,告诉您如何设置自己的“用户样式表”。首先,我们需要编写一个“用户样式表”如下:

    *  { color: green !important; }
    body {
    color: red !important; font:16px/19px Verdana, sans-serif !important; }

    注:这里的“*”表现通配符,其含义是对 HTML 文档中所有元素进行设置,俗称“通用选择器”。
         “16px/19px” 的含义是 font-size/line-height,即字体大小/字体行高。

    如果您是新手,可以将上面的CSS代码复制粘贴到记事本中,然后将.txt文件更改为.css文件即可。

         然后再 IE7 浏览器的工具栏中找到“工具”——“Internet 选项”,找到图片3中红圈标注的地方,点击浏览选择需要加载的“用户样式表”,然后确定即可。

                                                                      图片3

         呵呵,您是否发现在 IE7 下浏览的页面字体都变成了深绿色?这就是使用“用户样式表”所起的作用,您明白了吗?

         2.3.2 特殊性     Top

         慢着慢着,您没觉得奇怪吗,如果您真的按照上面的步骤操作了,回头再仔细看看 IE7 中那些被浏览过的页面。对了,有些文本的标题大小显然非 16px,行高也并非 19px 。是啊,为什么会这样,不是说标记 !important 的用户样式被赋予最高的权重吗,理论上页面文档中包含的所有文本内容都应该是深绿色,并且文字的大小和行高分别为 16px 和 19px吗?可如今您看到,却只有文本的颜色是深绿色,而字体的大小却并不统一,是的,之前我告诉您的重要性原则没有错,不过我还要告诉您另一套处理 CSS 规则的特殊性原则。

         我将简单介绍下 CSS 中的重要性原则和特殊性原则如何协同工作的,以上面描述的问题为例,浏览器在所有的 CSS 文件下载完毕后,首先会将所有的类似于 body  { color: red !important; font:16px/19px Verdana, sans-serif !important; } 这样的组合规则分解为

        body { color: red !important;
        body { font-size: 12px !important;
        body
    { line-height: 14px !important; }
        body { font-family: Verdana, sans-serif !important; }

    四个单一的规则来解析。理解这一点很重要,实际上我们所编写的各种组合规则都是依据重要性原则特殊性原则单独的覆盖每一个规则声明的,比如:

    { color:red; font:12px/32px 宋体, Verdana; }
    { color:gray !important; font-size: 20px !important; font-family: Verdana !important; }

    定义在同一个 CSS 文件中,并非如您所想那般第二个规则会直接完全取代第一个规则声明,不信您就编写一个简单的 HTML 文档测试一下看看,文本的行高属性 line-height 并没有被覆盖掉。嗯哼,上面的内容并非与特殊性原则有什么直接的关系,但是又不得不阐述,您多了解一点总归没有坏处的。

         好了,我会给出一个关于特殊性非常权威的说明,来源于 Andy 的著作《CSS Mastery》,目前为止我还未发现任何其他 CSS 著作的作者能向他一样阐述这个问题。一般来说,选择器的特殊性被分成四个等级:a、b、c和d。

    • 如果样式是内联样式(或称为行内样式),那么 a = 1。
    • b = ID 选择器的总数。
    • c = 类、伪类和属性选择器的数量。
    • d = 类型选择器和伪元素选择器的数量。

    使用上面这些原则可以计算出任何 CSS 选择器的特殊性。表1-1给出一系列选择器以及相应的特殊性值。

    表 1-1 特殊性示例
    选择器
    特殊性
    假设以10为基数的特殊性
    Style=""
    1,0,0,0
    1000
    #wrapper #content{}
    0,2,0,0
    200
    #content .datePosted{}
    0,1,1,0
    110
    div#content{}
    0,1,0,1
    101
    #content{}
    0,1,0,0
    100
    p.comment.datePosted{}
    0,0,2,1
    21
    p.comment{}
    0,0,1,1
    11
    div p{}
    0,0,0,2
    2
    p{}
    0,0,0,1
    1

         初看表1-1,您会对特殊性的讨论和那假设的基数有点迷糊,所以有必要在大概的总结一下。基本上,用 style 属性内嵌在 HTML 文档中的规则声明总是比其他任何规则声明特殊。具有 ID 选择器的规则比没有 ID 选择器的规则特殊,具有类选择器的规则比只有元素(或简单)选择器的规则特殊。最后,如果两个规则的特殊性相同,那么厚定义的规则优先。

         OK,还有最后一个问题要向您阐述一下,在上面的 body  { color: red !important; font:16px/19px Verdana, sans-serif !important; } 示例中,隐藏着一个继承的概念,body 元素在 HTML 文档结构中被认为是其内包含的所有元素的父元素,如果您想要 <body> 标签内的所有元素都应用同一个规则,恰当的做法就是为 body 元素编写样式。但是您千万记住,不要将继承层叠混为一谈,并且非常不幸的告诉您,一个元素通过继承获得的规则声明的特殊性为空,意味着当您直接为任何元素的编写某一种规则声明时,总会覆盖掉它从继承父元素获得的相同的规则声明。

         回头再看看本小节一开始所描述的问题是否迎刃而解了呢?好吧,我再来分析一遍,因为 *  { color: green !important; } 这条规则利用重要性原则获取最高权重,然后应用到每一个元素身上,并迫使特殊性原则失效,即使您为某一个元素编写了行内(内联)样式 style=“color:red;” 也不会让改变这个元素在页面中的绿色命运。好了,再来看看为什么页面中的许多文字大小和行高没有如 body  { color: red !important; font:16px/19px Verdana, sans-serif !important; } 规则中声明的那样:<body> 标签中的所有文本变为红色,文字大小为 16px,字体行高为 19px,字体类型为首选 Verdana 系列字体,备选为 sans-serif 系列字体呢?还记得刚刚提到的继承吗,body 说描述的规则声明与 * 所描述的规则声明具有同样的最高权重,又因为 <body> 标签内的元素继承的这些规则没有任何特殊性,当然会被 * {} 规则所覆盖,好了,如果我的陈述让您更迷糊了,我感到抱歉,因为我明白了,您却没有明白,只能说明我的表达式在有所欠缺。

         2.4 CSS文件为何臃肿     Top

         整篇文字的战线被拉的太长,对于这个问题的分析也就长话短说了。经过重构之后,我所编写的 CSS 被放在同一个文件中,大小为 13KB,是的,看起来的确比较庞大,这么臃肿的CSS是怎么诞生的呢?

         这一切都是因为我的个人喜好和控制欲造成的,为 id 命名过长, 过于追求锚链接的表现效果,于是利用选择器的层叠和特殊性编写了大量不一样的表现样式,其实从根本上这种做法是对页面的可达性造成障碍的,只是,只是……

         如何压缩自己的 CSS 文件呢,来吧,我们做些简单的事情就能得到不错的效果。重新审视您的命名是否合理,过长的命名或许并非带来清晰的理解,适当的使用缩写也不错;去掉 CSS 文件中的所有注释和空白,尽量将每一条规则编写在同一行内;充分利用层叠样式表的继承、重要性原则和特殊性原则,重构您的 CSS 文件,这样可以帮助您删除掉许多不要的规则声明;最重要的一条建议,重新审视您的 HTML 文档结构,构建合理化的文档结构才能编写出更清晰明了的样式表,不是吗?

        好了,结尾真的有点虎头蛇尾的感觉,我实在太累了,长达五天的琢磨,真的精疲力尽了。我把自己的思考历程变成文字与您分享,从内心来说是件愉快的事情,我也希望您能够喜欢。如何真正的让自己的设计和开发符合 Web 标准,不是一两句话能说清楚,更重要的是,我只是一位 走在 Web 标准这条荆棘大道上的苦行僧者,能把走过的路铺上砂石,却无法用未知来布道。我们要怎么做,应该如何去做,还希望大家能积极的贡献良策。但是在行动起来之 前,我们要有着充分的心理准备,任何变革都会伴随着无限次的阵痛,也会灼伤我们自己,逃避不了的,就必须去面对,既然标准预示着未来,为何不去尝试呢?总 会有那么一天,涌现出大量懂得合理运用标准的 Web 设计师和开发者,美妙的未来还会远吗?

     

     

         下篇提示:您是否想过,浏览器是如何将外部引用的样式表、内联样式表、导入样式表等用于渲染页面的吗?浏览器到底采取什么样的机制来解决层叠带来的规则冲突,不同的浏览器会有不同的处理机制吗?为什么同一个符合 Web 标准页面,当在不同的浏览器中完整呈现于您眼前的瞬间会有差异性呢?用户样式表只是为特殊群体而存在的吗?……

         我花掉了两天的空闲时间去探究上面的那些疑惑,经查阅大量资料和使用类似于 HttpWatch 之类工具做了些简单的测试,并从中了解到许多您并不一定知道的“秘密”,由于在总结如何展示这些“秘密”的过程中,完全超越自己设想的篇幅,我将单独将这些“秘密”成文后和大家一起分享。

         先给您模拟这样一个场景,是否会感兴趣呢?作为一名 Web 设计师,如果您不幸需要为自己设计的页面编写至少两个或以上的独立 CSS 文件,并一不小心在两个不同的 CSS 文件中编写了不同的规则声明来呈现同一个元素的样式,而您又更加大意的在 HTML 文档中为这个元素编写了内联样式(直接通过元素的 style 属性为其指定样式的方式),甚至忘记删除掉在 <head> 标签之间通过 <style type="text/css" > [……] </style> 为这个元素编写的某一规则声明。很不凑巧,此时页面正被一位特殊用户使用,他为自己的浏览器编写一份“用户样式表”,万万没想到,这位用户在自己的样式表中,也为这个元素指定了一条标注了 !important 的规则声明。这一切,让您有了天旋地暗的感觉吗,不要慌,他将是我用于总结“秘密”而虚拟出来的,敬请期待,不会让您失望的,呵呵。

     


    posted on 2009-03-13 22:45  rainnoless  阅读(4605)  评论(36编辑  收藏  举报