《精通 CSS(第3版)》试读:1.1 组织代码

人类天生好奇,喜欢摆弄东西。那天在办公室收到了新的遥控四轴飞行器Parrot AR Drone,我们都没看说明书,就开始动手组装起来。我们喜欢自己琢磨,喜欢按照自己认为的事物运作方式来思考和解决问题。零件只要能拼上就行,除非拼不上了,或者事实跟我们的想法相背离,才不得已去翻翻安装指南。 学习层叠样式表(CSS,cascading style sheets)最好的方法也一样,就是不管三七二十一,直接上手写代码。事实上,可能很多人都是这么学习编程的。比如在某个博客上看到了一些建议,又比如通过开源代码库研究自己喜欢的设计师创造的某个特效的源代码。几乎没人是在完整地看了一遍规范全文之后才开始动手写代码的,因为那样的话,人也早睡着了。 自己动手写代码是最好的开始方式,只是如果不够细心,可能会误解某个重要概念,或者给以后写代码埋下隐患。我们对此深有体会,因为自己给自己挖坑的事儿已经干了不是一回两回了。因此,这一章就来回顾一些基础但容易误解的概念,讲一讲怎么让HTML和CSS保持组织分明且结构良好。 本章内容:  可维护性的重要意义  HTML和CSS的不同版本  未来友好的代码与向后兼容的代码  使用新的HTML5元素为HTML赋予意义  在HTML中为添加样式设置恰当的接入点  通过ARIA、微格式、微数据扩展HTML的语义  浏览器引擎模式与验证 1.1 组织代码 人们通常不会注意到建筑物的基础。可是,没有坚实的基础,建筑物的主体就不可能稳固。虽然本书讲的是CSS的技术和概念,但这些内容的讲解与实现必须以结构良好且有效的HTML文档为前提。 本节会介绍结构良好且有意义的HTML文档对基于标准的Web开发的重要性,以及如何让文档更有意义、更灵活,从而减轻开发者的工作负担。但首先我们要讲一个对任何语言都同样重要的概念。 1.1.1 可维护性 可维护性可以说是所有优秀代码最重要的特点。如果你的代码已经看不出结构,变得难以阅读,那么很多问题就会接踵而至。开发新功能、修复bug、提升性能,所有这些操作都会因为代码可读性差以及代码脆弱而变得复杂,而且结果难料。这最终会导致开发人员一点代码也不敢改,因为每次只要改一点,就会出问题。于是,没人愿意再维护这个网站,更糟糕的情况是只能走严格的变更控制流程,每周发布一次,甚至每月才能发布一次! 如果你开发的网站最终要交付给客户或者另一个开发团队,那么可维护性就更重要了。这时候,代码是否容易看懂,是否意图明确,是否为将来的修改做过优化,都至关重要。哪个项目没有持续不断的变更需求?哪个项目不需要一直开发新功能?哪个项目不需要不断修复bug?因此,“唯一不变的就是变化”。 相对来说,CSS是随着代码量增加而最难保持可维护性的语言之一。即使网站规模不大,样式表也会很快变得难以控制。现代编程语言都有内置的变量、函数和命名空间等特性,这些特性都有利于保持代码的结构和模块化。这些特性CSS都没有,所以要按照使用这种语言和组织代码的特殊方式来管理它。本书后面在讨论各种主题时,大都会涉及可维护性。 1.1.2 HTML简史 Web的威力源自其普适性。即使残障用户也能使用是题中应有之义。 ——Tim Berners-Lee Tim Berners-Lee在1990年发明了HTML,当时是为了规范科研文档的格式。HTML是一种简单的标记语言,为文本赋予了基本的结构和意义,比如标题、列表、定义等。这些文档通常没有什么装饰性的元素,可以方便地通过计算机来检索,而人类可以使用文本终端、Web浏览器,或者必要时使用屏幕阅读器来阅读它们。 然而,人类是视觉发达的生物。随着万维网被越来越多的人所接受,HTML也逐渐增加了对展示效果的支持。除了用标题元素标记文档标题,还可以使用粗体标签和不同的字体来创建特殊的视觉效果。本来用于展示数据的表格(table),却成了页面布局的手段;块引用(blockquote)也经常被用来缩进文本,而不是只用来标记引文。HTML很快就偏离了为内容赋予结构和意义的初衷,变成了一堆字体和表格标签。Web设计者给这种标记起了个名字,叫“标签汤”(见图1-1)。

正当Web变得一团糟之际,CSS作为解决方案面世了。CSS的初衷是把跟HTML混在一起的表现性标记提取出来,使其自成体系,达到结构与表现分离的目的。这就让有意义的标签或者说语义悄悄返回了HTML文档。font之类的表现性标签可以不用了,而表格布局也可以被逐步取代。对大多数网站而言,CSS都能提升其可访问性和加载速度。不仅如此,CSS还给Web设计和开发人员带来了更多好处:  一种专用于控制视觉样式和布局的语言;  在同一网站中更易于重用的样式;  通过关注点分离得到了良好的代码结构。 关注点分离 关注点分离(separation of concerns)是软件开发行业的一个常见概念。对Web开发而言,关注点分离不仅适用于标记和样式,同样也适用于编写样式的方式。事实上,关注点分离也是确保代码可维护性的一种主要方法。 Unix开发社区有一句话很好地诠释了关注点分离的思想,即“分成小块,松散结合”(small pieces, loosely joined)。其中,每一“小块”都是一个模块,专注于做好一件事。而且,因为这个模块跟其他组件是“松散结合”的,所以它可以方便地在系统的其他部分中重用。Unix中的一“小块”可能是一个字数统计函数,可以应用于传入的任何文本片段。而在Web开发中,这一“小块”可能就是一个商品列表组件,如果能做到“松散结合”,就可以在一个网站的多个页面或者在同一布局的不同区块中重用。 可以把代码中的这些“小块”想象成积木。每一块积木都很简单,但把很多块积木以不同方式组装起来,就可以创造出无比复杂的东西。第12章还会讨论这个话题,届时会讲一讲怎样以结构化的方式应用这个策略。 1. HTML和CSS的版本 CSS有很多版本,或者“级别”。了解这些版本产生的背景,有助于了解应该或不应该使用哪些CSS特性。万维网联盟(W3C,World Wide Web Consortium)是制定Web技术标准的组织,该组织制定的每一个规范要经历几个阶段之后才能成为W3C推荐标准。CSS1是在1996年底成为W3C推荐标准的,当时只包含字体、颜色和外边距等基本的属性。CSS2在1998年成为推荐标准,增加了浮动和定位等高级特性,此外还有子选择符、相邻选择符和通用选择符等新选择符。 相比之下,CSS3则采用了完全不同的模式。实际上不存在所谓的CSS3规范,因为CSS3指的是一系列级别独立的模块。如果规范模块是对之前CSS概念的改进,那就从3级(level 3)开始命名。如果不是改进,而是一种全新的技术,那就从1级(level 1)开始命名。而我们所提到的CSS3,则是指所有足够新的CSS规范模块,比如CSS Backgrounds and Borders Level 3、 Selectors Level 4和CSS Grid Layout Level 1。这种模块化的方式可以让不同的规范有自己的演进速度。有些3级规范,比如CSS Color Level 3,已经成为推荐标准。而另外一些可能还处于候选推荐阶段,很多甚至还处于工作草案阶段。 虽然CSS3的制定工作在CSS2发布后就开始了,但这些新规范一开始的制定速度很缓慢。为此,W3C在2002年发布了CSS2 Revision 1。CSS 2.1修正了CSS2中的一些错误,删掉了支持度不高或者并非所有浏览器都实现了的一些特性,总体来说就是把CSS规范做了一番清理,好为浏览器实现提供更精准的蓝图。CSS 2.1在2011年6月成为推荐标准,此时距离CSS3启动已经有10多年了。由此可见,标准制定主体和浏览器开发商为了确保相应的特性得以原原本本地实现,需要花多么长的时间。不过,浏览器开发商经常会在标准还处于草案阶段时,就发布一些实验性的实现。这样,等到了候选推荐阶段,相应的实现就已经非常稳定了。换句话说,很多CSS特性早在相应模块成为推荐标准前就可以使用了。 HTML的历史也很复杂。HTML 4.01在1999年成为推荐标准,与此同时W3C也把注意力转向了XHTML 1.0。本来接着要发布XHTML 1.1,但其严格程度在实践中暴露了无法落地的问题,最终被Web开发社区抛弃。于是,这个Web主要语言的发展停滞了。 2004年,有几家公司共同组建了Web超文本应用技术工作组(WHATWG,Web Hypertext Application Technology Working Group),并致力于开发新的规范。2006年,W3C肯定了它们工作的必要性,并欣然加入该工作组。2009年,W3C完全放弃XHTML,正式接纳WHATWG制定的新标准,这就是后来的HTML5。起初,WHATWG和W3C都基于标准调整自己的工作,但后来它们的关系又变得复杂起来。今天,它们分别在编辑两份标准。WHATWG那份就叫HTML,而W3C那份则称为HTML5。没错,这种分裂确实不好。但万幸的是,这两份标准的内容相当接近,因此只讲HTML5是没有问题的。 2. 应该使用哪个版本 设计者和开发者经常问的一个问题就是应该使用HTML或CSS的哪个版本。这个问题不好回答。虽然规范反映了标准和Web技术开发的进度和焦点,但它其实跟设计者和开发者日常的工作关系不大。真正重要的是知道HTML和CSS的哪些部分已经在浏览器中实现了,以及这些实现是否稳健,有没有bug。比如,浏览器提供的这些特性是不是实验性特性,使用时需谨慎?或者,这些特性到底靠不靠谱,是不是已经得到了多数浏览器的支持? 今天,使用CSS和HTML就要了解浏览器对其中特性的支持程度。有时候我们会觉得技术发展太快,必须拼命追赶才不会落伍;有时候我们又会觉得技术发展太慢。本书会随时提示不同HTML和CSS特性的浏览器支持情况,还会给出在什么情况下可以使用它们的建议。不过显而易见的是,印在纸上的东西注定会过时,所以你得学会自己更新这方面的信息。 要了解浏览器支持情况,推荐几个不错的地方。对于CSS属性,可以访问“Can I use”网站(https://caniuse.com)。这个网站可以搜索属性或属性组,结果配有统计信息,显示支持它们的浏览器百分比,包括桌面浏览器和移动浏览器。另一个非常有想法的项目是https://webplatform. github.io/,是W3C和几家浏览器厂商及行业巨头合作搞出来的,目标是收集合并它们所有关于CSS、HTML、JavaScript API等支持情况的文档。不过,就跟很多大型项目一样,最终要完成那么庞大的Web技术文档的聚合,需要花很长时间。此外,Mozilla的开发者文档,即MDN,也是一个非常好的参考。 说到浏览器支持,关键要明白,并非所有浏览器都一样,实际上从来就没有完全一样的浏览器。某些CSS3特性只得到了少数浏览器的支持。比如,Internet Explorer 11和Safari 6.1之前的版本都没有正确支持Flexbox(Flexible Box Layout)。不过,就算需要支持老版本的浏览器,也不意味着不能使用Flexbox。核心布局上可以不用Flexbox,但对于某些特定的组件,Flexbox可能就非常合适。只要为不支持它的浏览器准备好可以接受的后备代码就行了。判断一个人是不是CSS大师,很大程度上要看他能否游刃有余地处理向后兼容的代码与未来友好的代码。 1.1.3 渐进增强 平衡向后兼容性与最新的HTML和CSS特性,涉及一种叫作渐进增强(progressive enhancement)的策略。所谓渐进增强,大意就是“首先为最小公分母准备可用的内容,然后再为支持新特性的浏览器添加更多交互优化”。使用渐进增强策略,意味着代码要分层,每一层增强代码都只会在相应特性被支持或被认为适当的情况下应用。听起来有点复杂,而实际上HTML和CSS的实现已经部分内置了这一策略。 对HTML而言,这意味着浏览器在遇到未知元素或属性时并不会报错,而且也不会对页面产生什么影响。比如,可以在页面里使用HTML5定义的新input元素。假设表单中有一个电子邮件字段的标记如下: <input type="text" id="field-email" name="field-email"> 要使用新的input元素,应该把type属性改成这样: <input type="email" id="field-email" name="field-email"> 尚未实现这个新字段类型的浏览器碰到它只会想:“这是啥意思呀?不明白。”然后回退为默认的text类型,结果和上面的第一行代码一样。而实现了这个类型的新浏览器则知道email想让用户在这里填写什么样的数据。而在很多移动设备中,相应的软键盘还会针对输入电子邮件地址调整界面布局。假如你还在这里使用了内置的表单验证,那么支持它的新浏览器也会帮你做验证。这样,我们既渐进增强了页面,也不会对旧版本浏览器产生不好的影响。 另外一个简单的变化就是,HTML5把文档类型声明更新为新的简短形式。所谓文档类型,就是位于HTML文档第一行的代码,供机器识别当前文档使用的标记语言版本。以往的HTML和XHTML版本中,这行代码很长很复杂,但在HTML5中,它已经简化成了下面这样: <!DOCTYPE html> 今后,只要这样声明HTML文档类型就好了,因为这个HTML5语法的doctype是向后兼容的。后面几节我们会再介绍一些HTML5中出现的新元素,但如果要更深入地学习如何使用HTML5标记,建议看一看Jeremy Keith的HTML5 for Web Designers。 CSS中的渐进增强同样也反映在浏览器如何对待新属性上。任何浏览器无法识别的属性或值都会导致浏览器丢弃相应的声明。因此,只要同时提供合理的后备声明,使用新属性就不会带来不良后果。 举个例子,很多现代浏览器支持以rgba函数方式表示的颜色值。这种方式可以分别传入红、绿、蓝通道,以及阿尔法(alpha,即透明度)通道的值。我们可以这样使用它: .overlay { background-color: #000; background-color: rgba(0, 0, 0, 0.8); } 这条规则定义了类名为overlay的元素背景为黑色,但随后又用rgba声明背景色应稍微透明。如果浏览器不支持rgba,那么相应元素的背景色就是不透明的黑色。如果浏览器支持rgba,那么第二条声明就会覆盖第一条。也就是说,即使并非所有浏览器都支持rgba,我们也可以使用它,只是要先为它声明合适的后备代码。 1. 厂商前缀 浏览器厂商也基于相同的原理为自家浏览器引入实验性特性。实验性特性的标准名称前面会加上一个特殊字符串,这样他们自己的浏览器就能识别该特性,而其他浏览器则会忽略该特性。有了这个方案,浏览器厂商就可以添加规范中没有或者尚不成熟的新特性,样式表作者也可以安心地试用这些新属性,不用担心浏览器因不认识它们而破坏页面。比如: .myThing { -webkit-transform: translate(0, 10px); -moz-transform: translate(0, 10px); -ms-transform: translate(0, 10px); transform: translate(0, 10px); } 这里使用了几个不同的前缀,给相应的元素应用了变换(第10章会介绍)。以-webkit-开头的适用于基于WebKit的浏览器,如Safari。Chrome和Opera都基于Blink引擎,而Blink最初也是基于WebKit开发的,所以-webkit-前缀通常也适用于这3个浏览器。-moz-前缀适用于基于Mozilla的浏览器,如Firefox。-ms-前缀则适用于微软的Internet Explorer。 最后我们又加了一条不带前缀的声明,这样那些支持标准属性名称的浏览器就不会漏网了。过去经常出现开发人员漏加不带前缀的标准声明的情况。为此,有些浏览器厂商也开始支持竞争对手引擎特定的前缀,以便让流行的网站能在自己的浏览器上打开。但这样做也造成了混乱,于是多数浏览器厂商抛弃了厂商前缀。那实验性特性呢?有的厂商选择把它们隐藏在chrome://flags中,有的选择只在特定的预览版中提供。 本书中绝大多数示例都使用不带前缀的标准属性名称,因此建议大家经常查一查http://caniuse. com,以了解相应的支持情况。 2. 条件规则与检测脚本 如果希望根据浏览器是否支持某个CSS特性来提供完全不同的样式,那么可以选择@supports块。这个特殊的代码块称为条件规则,它会检测括号中的声明,并且仅在浏览器支持该声明的情况下,才会应用块中的规则: @supports (display: grid) { /* 在支持网格布局的浏览器中要应用的规则 */ } 条件规则的问题是其自身也很新,只能将它应用于新的浏览器中,因为旧版本浏览器不支持(比如第7章要介绍的网格布局)。此外,还可以通过JavaScript来检测支持情况,比如使用Modernizr这个库。Modernizr的原理是为HTML添加支持提示信息,然后可以依据这些信息来编写CSS。 随后几章还会更详细地介绍类似的策略和工具,这里关键是要知道:渐进增强可以让我们放下对版本号和规范的很多担忧。只要加点小心,就可以在适当的时候使用一些簇新的特性,同时又不会丢掉使用旧版浏览器的用户。

>精通 CSS(第3版)

精通 CSS(第3版)
作者: [英]安迪•巴德 - Andy Budd, [瑞典]埃米尔•比约克隆德 - Emil Björklund
副标题: 高级Web标准解决方案
原作名: CSS Mastery
isbn: 7115506906
书名: 精通 CSS(第3版)
页数: 388
译者: 李松峰
定价: 99
出版社: 人民邮电出版社
出版年: 2019-2
装帧: 平装