高流量网站CSS开发技术

讲解CSS基础知识、CSS高级技巧、CSS3选择器/属性,以及各种CSS设计模式的图书可谓浩如烟海。本书无意在这些领域标新立异,而是探讨了大型团队或多个团队一同工作的情况,以及处理包含众多页面或子站点且访问量相当可观的网站时,所要面对的挑战。我们不介绍如何用最新最炫的技术实现图片替换或跨浏览器的圆角,而将关注点放在让团队中的新人更容易理解原有代码,并在其上添砖加瓦,让网页中的CSS代码从一开始就经过深思熟虑,且以完善、高效的方式构建。

本书对新手和专家同样有用。不过,若是你已经有一些HTML和CSS的使用经验,或至少熟悉相关语法,那再好不过了。对代码重用、模块化、健壮性和实用性的讨论,将贯穿本书各章。

亚马逊购买《高流量网站CSS开发技术》

本书适合以下读者:

  • 所有在高流量网站工作的人,所谓高流量指独立访问用户数日均1万以上,或峰值超过1万;
  • 所有在大型网站工作的人,大型网站至少要包括2000个独立网页,或30个子网站;
  • 所有在公司负责网站开发的人,所在公司有大量员工在同一个代码库上工作,参与修改CSS的程序员超过30人;
  • 所有在有潜力的公司工作、希望为公司Web开发建立一套良好流程的人;
  • 所有缺少大型团队工作经验的开发人员。

通过阅读这本书,你将了解以下内容:

  • 流程的价值;
  • 如何在员工和团队之间共享知识;
  • 如何尽快让新来的CSS程序员上手工作;
  • 如何将CSS修改纳入构建、部署流程;
  • 如何编写可重用、模块化的CSS;
  • 如何最大限度提升网站性能;
  • 如何保持品牌的一致性;
  • 跨浏览器和无障碍访问的CSS最佳实践;
  • 动态CSS技术。

最后一章提供了一套简单的CSS框架,是我们为本书定制的,其中演示了大量书中讨论过的内容,包括创建这个框架时所遵循的流程。书后的四个附录提供了规范和流程的具体例子,供读者参考。

作者简介:

Antony Kennedy

自2010年6月至今先后在苹果公司担任资深前端工程师和前端设计主管,曾在BBC、BSkyB、Tesco、迪士尼和Channel4等多家公司的高流量网站担任前端研发重要职位。在Web开发技术领域打拼近20年,对CSS、HTML5、JavaScript、敏捷开发和持续交付等具有深刻独到的见解。关于他的更多信息,请查看 http://uk.linkedin.com/in/kennedyantony。

Inayaili de León

Web设计师,目前受雇于Canonical公司(Ubuntu的创建者)。她热衷研究如何在Web设计过程创建清晰、语义化和高效的HTML/CSS。Inayaili热爱Web,热爱自己的工作,享受每天都能获取新知识的生活。她设计的网页简洁、美观、易用,http://yaili.com/ 有她的更多介绍,以及她的一些优秀的设计作品。

更多阅读:

CSS选择器的特殊性

使用CSS的时候,要对特殊性(specificity)进行慎重的考虑和规划,在CSS文件较大,频繁需要重写和导入的情况下,更是如此,而这在高流量网站更容易发生。

一条不错的经验法则是,在开始编写CSS文件时,首先使用比较宽泛的选择器,在过程中再酌情增加特殊性。否则的话,工作要困难得多,而且不可避免地会产生过于特殊、无法重用的选择器,以及过于冗长、缺乏灵活性的样式表。

依赖选择器顺序的样式表更脆弱,还可能导致不必要的冗余。当你需要重写某个规则时,你会在文件后面再新建一个同样的规则,然后再在它后面新建,直到你重复一遍又一遍同样的事情。如果样式表的顺序由于某种原因发生变化,你要应用到元素的那些属性(通常是在最后定义的)将会失效,因为它依赖于选择器的顺序。依赖特殊性而不是选择器的顺序,将使得样式表更易于编辑、维护,便于将来进行重构,同时也更健壮。

选择器的特殊性也会影响一个网站的性能,进行DOM(Document Object Model,文档对象模型)查询时,选择器各个部分是按照反直觉的顺序(从右到左)来进行计算的,选择器的特殊性和复杂度越高,对性能的影响越大。

说到底,CSS文件的模块化和灵活性程度,对于较深层的元素是否要采用高特殊性的规则,是由你自己的选择来决定的。然而在团队中,应当将特殊性作为首要关注的问题,来对样式表进行规划。

特殊性计算

在级联计算中指定一个CSS规则的权重时,会首先根据重要性(是否有!importance)和CSS来源对规则进行排序。重要性和来源相同的规则,就按特殊性排列:特殊性高的选择器会覆盖特殊性低的选择器。最后,如 果两个选择器具有同样的来源、重要性和特殊性,写在样式表后面的那个规则就会覆盖写在前面的规则。这也适用于单一的属性,因此,如果在同一个规则中多次声明了相同的属性,最后的声明就会覆盖前面的声明。

因为使用@import声明导入的样式表必须要写在其他规则之前,如果在CSS文件后面出现的非导入规则,与导入文件中的规则具有同样的权重,导入规则将被覆盖(因为选择器的顺序,后面的覆盖前面的)。

根据W3C规范(http://www.w3.org/TR/css3-selectors/#specificity),特殊性的计算使用四个字母"a、b、c、d"来代表重要性依次递减,其中:

  • a 如果该声明是在style属性中定义的,则为1,否则为0;
  • b 等于id选择器的数目;
  • c 等于属性选择器、class和伪class的数量;
  • d 等于元素名和伪元素的数目。

非CSS语法的标记(如font属性),特殊性都归为0。基于这一系列规则,以下选择器的特殊性为 1,0,0,0 (a=1,b=0,c=0,d=0):

<section style="padding-bottom: 10px;"> 

因为这里是内联CSS,a=1,其余数字是0。记住,假如在非内联的链接样式表中,有一处带10个id选择器(特殊性为0,10,0,0)的规则,它的优先级仍然不如以上选择器——特殊性的计算不是基于十进制升位的,后面的数再高也不能升到前一位:a=1的规则将始终优先于其他a=0的规则。

以下选择器更复杂一些,特殊性为0,0,1,3(a=0,b=0,c=1,d=3):

article section h1.title {
    ...
} 

因为不是内联的,a=0;因为没有id,b=0;因为有一个class选择器,c=1;因为有三个元素选择器,d=3。

基于这一系列算法来对特殊性进行计算,可能令人望而生畏。但实际上,有了一些经验后,很容易看出一个选择器比起另一个选择器特殊性是高还是低,如有一个或两个id选择器,或其他类似的明显提示。编写CSS时应该小心,如果没有必要,不要创建高特殊性的选择器。如果遇到棘手的情况,类似Firebug或Safari Web Inspector等工具将帮助你了解特殊性如何应用于元素,它们能按照特殊性排序来显示规则,将特殊性更高的规则显示在最上面,并将被特殊性更高的规则覆盖的属性用删除线划掉。有关内容详见第10章。然而应该记住两件重要的事情:内联CSS要比嵌入或链接CSS优先级更高;一个ID选择器要比任意数量的class、属性或元素选择器优先级更高。

!important声明

如果在缩写属性中使用了!important声明,就等于用!important重新逐个声明了每个子属性,而这样可能会导致属性恢复为初始默认值。

例如,假设我们有这样一个选择器:

h1 {
    font-family: Georgia, serif;
    font-size: 18px;
    font-style: italic;
}

然后在样式表的后面有如下声明:

h1 {
    font: 18px Arial, sans-serif !important;
} 

其结果将等价于以下声明:

h1 {
    font-style: normal !important;
    font-variant: normal !important;
    font-weight: normal !important;
    font-size: 18px !important;
    line-height: normal !important;
    font-family: Arial, sans-serif !important;
} 

发生这种情况的原因是,在!imporot声明内,某些属性没有获得明确定义(如本例中的font-style、font-variant、font-weight和line-height),这时,即使较低特殊性的规则已经存在,它们也会恢复到属性规范中所规定的初始值(如本例中的font-style: italic)。

命名空间和特殊性

有一些情况下,高特殊性的选择器是必要的。例如要创建在不同网页、子网站、迷你网站,甚至第三方网站广泛使用的部件和代码片段,常见的做法是对这部分代码采用命名空间,对CSS来说,基本上意味着要通过一个特殊的class、id或class/id前缀,将其分离出来。要对一个页面应用不同的风格,也经常会使用命名空间,这种情况下,我们将为body元素添加一个id或class,例如:

<body> 

重要的是要认识到,虽然在为不同页面或页面不同部分创建不同样式时,这是一种常见而简单的方法,但它会影响特殊性。当在CSS里指定这些页面或代码片段时,我们不得不在规则中引入一个class或id,从而增加了它的特殊性,导致它更难被覆盖。例如,在定义了class="home"的页面中,我们想要让h2标题比其他页面更大,可以用以下规则设置:

h2 {
    font-size: 24px;
}
.home h2 {
    font-size: 36px;
}

如果由于某种原因,我们需要在同一网页内再次覆盖此设置,就需要再添加一个class来指定特殊的标题,并创建一个更特殊的规则:

.home h2.highlight {
    font-size: 30px;
}

这样像滚雪球一样,规则的特殊性越来越高,难免会导致CSS不必要的复杂度。应对的秘诀是针对这种情况仔细进行规划。贯穿整站的设计元素要采用的变化越多,这种情况的发生就会越频繁。而如果没有建立一套设计库,或虽然建立了设计库,但更新不及时,这个问题就会更严重。你应该建立一份具有良好适应性的样式表,并定义一组指导标准,告诉开发者如何具体问题具体处理——为了CSS的灵活性,不要用更高特殊性的选择器去反复覆盖。但刻意避免class/id的办法也不适用于高流量网站,在某些时候,class/id方案的效率和健壮性更好。

使用工具

使用Chrome的开发者工具、Safari的Web Inspector或Firefox的Firebug等工具能帮助你了解哪些属性优先级更高,哪些属性覆盖了其他属性。这些工具也可以显示用户代理样式表和计算值,即使它们没有在CSS中声明。

使用工具,你仍然需要理解级联的工作原理,但工具减少了调试过程中的痛苦。

本文摘自《高流量网站CSS开发技术》(人民邮电出版社,2013)。要更多了解文章中提到的CSS脆弱性、前端性能优化、设计库、开发工具等内容,可阅读该书相关章节。

收藏
点赞

复制本文链接 文章为作者独立观点不代表优设网立场,未经允许不得转载。