擅长CSS的Web开发人员不仅可以从视觉上复制实物原型,还可以用代码进行完美的呈现。无需使用表格、尽可能少的使用图片。如果你是个名副其实的高手,你可以快速把最新和最伟大的技术应用到你的项目中,比如媒体查询、过渡、滤镜、转换等。虽然这些都是一个真正的CSS高手所具备的,但CSS很少被人单独拿出来讨论,或者用它去评估某个人的技能。
有趣的是,我们很少这样去评价其他语言。Rails开发人员并不会因为其代码比较规范,就认为他是一名优秀的开发人员。这仅仅是个基准。当然,他的代码得必须规范。另外,还需集合其他方面考虑,比如代码是否可读?是否容易修改或扩展……
这都是些很自然的问题,CSS和它们并没有什么不同之处。今天的Web应用程序要比以往更加庞大。一个缺乏深思熟虑的CSS架构往往会削弱发展,是时候像评估其他语言那样,来评估一下CSS架构了,这些都不应该放在“事后”考虑或者单单属于设计师们的事情。
1.良好的CSS架构目标
在CSS社区,很难提出某个最佳实践已经成为大家的普遍共识。纯粹地从Hacker News的评论上判断和开发者们对CSS Lint发布后的反应来看,大多数人对基本的CSS东西是持反对意见的。所以,并不是为自己的最佳实践奠定一套基本的论据,而应该确定真正的目标。
好的CSS架构目标并不同于开发一个好的应用程序,它必须是可预测、可重用、可维护和可伸缩的。
可预测
可预测意味着可以像预期的那样规范自己的行为。当你添加或者修改某个规则时,它并不会影响到没有指定的部分。对于一个小网站来说,一些微乎其微的改变并不算什么。而对于拥有成千上万个页面的大网站来说,可预测却是必须的。
可重用
CSS规则应具备抽象和解耦性,这样你就可以在现有的基础上快速构建新的组件,无需重新修改编码模式。
可维护
当把新组件放置到网站上,并且执行添加、修改或者重新设计操作时,无需重构现有CSS,并且新添加的X并不会打破原有页面的Y组件。
可扩展
当网站发展到一定规模后,都需要进行维护和扩展。可扩展的CSS意味着网站的CSS架构可以由个人或者团队轻易地管理,无需花费太多的学习成本。
2.常见的错误实践
在实现良好的CSS架构目标之前,我们来看一些常见的错误做法,这对我们达成目标是有好处的。
下面的这些例子虽然都可以很好的执行,但却会给你带来很多烦恼,尽管我们的意图和愿望都是美好的,但是这些开发模式会让你头疼。
几乎在每个网站上,都会有一个特定的虚拟元素看起来与其他页面是完全一样的,然而只有一个页面除外。当面对这样一种情况时,几乎每个新手CSS开发人员(甚至是经验丰富的)都会以同样的方式来修改。你应该为该页面找出些与众不同之处(或者自己创建),然后再写一个新规则去操作。
基于父组件来修改组件
1..widget { 2. background: yellow; 3. border: 1px solid black; 4. color: black; 5. width: 50%; 6.} 7. 8.#sidebar .widget { 9. width: 200px; 10.} 11. 12.body.homepage .widget { 13. background: white; 14.}初看,这绝对是段无害的代码,但让我们来看看它是否达到了我们所设置的目标。
首先,widget在examle是不可预见的。当这些小部件出现在页面两侧或者主页面时,开发人员期望它们以某种特定的方式显示出来,且又不失特色。另外,它也是不可重用或不可扩展的。
另外,它也比较难维护。一旦这个widget需要重新设计,那么你不得不修改其他几个CSS样式。想象一下,如果这段代码是使用其他语言编写的,它基本就是一个类定义,然后在代码的另一部分使用该类定义并做出扩展。这直接违反了软件开发的开放/闭合(open/close)原则。
软件实体(类,模块,函数等)应对扩展开放,对修改闭合。
过于复杂的选择器
偶尔,会有些文章介绍CSS选择器对整个网站的展示起着非常重要的作用,并且宣称无需使用任何类选择器或者ID选择器。
但伴随着越深入的开发,我越会远离这种复杂的选择器。一个选择器越复杂,与HTML就越耦合。依靠HTML标签和组合器可以保持HTML代码干干净净,但却让CSS更加毛重和凌乱。
1.#main-nav ul li ul li div { } 2.#content article h1:first-child { } 3.#sidebar > div > h3 + p { }
对上面代码进行简单的理解。第一个可能是对下拉菜单进行样式化;第二个想说明文章的主标题应该与其他页面的H1元素不同;最后一个表示在第一段的侧边栏区域添加一些额外的空间。
如果这个HTML是永远不变的,那就无可说之处,但这根本毫不现实。过于复杂的选择器会让人印象深刻,它可以让HTML摆脱掉表面上的复杂,但对于实现良好的CSS架构目标却毫无用处。
上面提到的例子都是不具备可预测性、可重用、可扩展和可维护这四大特性的。例如第一个选择器(下来菜单)例子,如果一个外观非常相似的下拉列表需要用在不同的页面上,并且#main-nav并不属于内部元素,那么你是否需要重新设计?假设开发者想要修改第三个例子里div里面部分标记,那么整个规则都会被打破。
过于通用的类名
当创建可重用的设计组件时,在组件的类选择器中覆盖附件的子元素是很常见的现象。例如:
1.<div> 2. <h3>...</h3> 3. <div> 4. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 5. In condimentum justo et est dapibus sit amet euismod ligula ornare. 6. Vivamus elementum accumsan dignissim. 7. <button>Click Me!</button> 8. </div> 9.</div>
1..widget {} 2..widget .title {} 3..widget .contents {} 4..widget .action {}
像.title、.contents、.action这些子元素类选择器可以被安全地进行样式命名,无需担心这些样式会蔓延到拥有相同类名的其他元素中。这是千真万确的。但它并没有阻止相同样式类名称会蔓延到这个组件上。
在一些大型项目上,像.title这样的名称很有可能会被用在另外一个页面或者本身。如果这样的情况发生,那么整个标题部分明显会和预期的不一样。
过于通用的类选择器名称会导致许多不可预测的CSS样式发生。
一个规则做太多事
有时,你要在网站的左上角区域做一个20pixels的可视化组件。
1..widget { 2. position: absolute; 3. top: 20px; 4. left: 20px; 5. background-color: red; 6. font-size: 1.5em; 7. text-transform: uppercase; 8.}
下面,你需要在网站的其他区域使用该组件,那么上面的这个代码明显是错误的,不可重用的。
问题的关键是你让.widget这个选择器做的事情太多,不仅对该组件的位置进行了规定,还对它的外观和感觉方面进行了样式。外观和感觉可以通用,而位置是不可以的。有时候,把它们整合起来使用反而会大打折扣。