CSS学习笔记(十六) CSS最佳实践之可维护性篇

前言

CSS代码难维护众所皆知。

  • 为一个元素设置样式的方式可以通过定义的class、定义的id、元素的标签名、元素的属性等选择器以及这些选择器的组合来实现;

  • 作用于某个元素上的样式又可能来自单个样式规则,也可能来自多个样式的组合,还可能来自父元素;

  • CSS样式可以定义在元素的style属性里面,也可以定义在页面head部分,还可以定义在单独的CSS文件中。

CSS样式定义上的灵活性带来的是CSS代码的多样性,如果毫无章节地使用这些定义样式的方式,势必会导致CSS代码的混乱和难以维护。本文将抛砖引玉,总结出几个方面来讨论如何编写可维护性的CSS代码。

Web前端开发入门难度并不高,但是初学者如果没有一个很好地学习和编码习惯,则开发水平的提高速度会变得很慢。 by 《Web前端开发最佳实践》党建

1.代码规范

不管有多少人共同参与同一项目,一定要确保每一行代码都像是同一个人编写的。by 编码规范 @mdo

命名规范和格式规范是代码规范中最基本的规范,任何代码的混乱都是从命令和格式的混乱开始,而意义明确的命名和规整的代码格式则提高了代码的可读性与可维护性,给阅读者和维护者留下来良好的第一印象。每个开发团队都应该有一套自己的规范。

  • 组成类名称的关键字的连接符为中划线-

.page-content-title {
    ...
}
  • 为了避免class命名的重复,命名时取父元素的class名作为前缀。

/* 父元素的样式声明 */
.page-content {
    ...
}

/* 子元素的样式声明 */
.page-content-body {
    ...
}
  • 在CSS样式定义中,左大括号放置在选择器的同一行,并和选择器之间添加一个空格分隔,在保证可读性的基础上缩短代码的行数;在样式声明中,属性名称和值之间用一个空格分隔,提高代码可读性。

/* 不推荐 */
.page-content-title
{
    border-left:1px solid #fff;
} 

/* 不推荐 */
.page-content-title{border-left:1px solid #fff;}

/* 推荐 */
.page-content-title {
    border-left: 1px solid #fff;
}

单行显示不好注释,不好备注,这应该是压缩工具的活儿~ by 前端编码规范之CSS - Barret Lee

  • 多个选择器具有相同的样式声明时,每个选择器应该单独占一行,便于阅读和维护。

/* 不推荐 */
h1, h2, h3 {
    font-weight: bold;
    line-height: 1.5;
}

/* 推荐 */
h1,
h2,
h3 {
    font-weight: bold;
    line-height: 1.5;
}
  • 在CSS样式文件中添加注释主要有两种类型:文件头部的文件信息注释和正文中的解释说明性注释。文件信息 一般包括文件版本、版权信息以及作者等;解释性说明的注释 有给模块的注释和单独给选择器的注释,模块的注释则需要添加注释表明模块样式定义的开始和结束,CSS选择器的注释需要添加在选择器的上一行,而不是和选择器相同一行。注释可以在压缩的时候选择性去掉。

/* 注释规范说明:文件头部的文件信息注释 */
/*!
 * page content v1.0
 *
 * Copyright 2015
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 * Designed and built by dopppler
 * /

/* 注释规范说明:模块样式定义的开始和结束 */
/* page container start */
.page-content {
    ...
}
.page-content-title {
    ...
}
...
/* page container end */

/* 后面加一个感叹号,表示这是"重要注释"。即使是压缩模式编译,也会保留这行注释,通常可以用于声明版权信息。by SASS用法指南 - 阮一峰的网络日志

2.结构组织

规范的 CSS 代码首先应该具有结构清晰和模块分明的特点。想象一下,如果在平时的开发中,拿到效果图就切,切完写,没有先从页面整体来规划样式,那么在开发的过程中就会出现某些代码块难以重用的情况,这样就只能从原来的代码中复制部分内容组合成新的样式定义。随着站点功能越来越多,CSS 代码中重复的代码就会越来越多,最终一发不可收拾。那么,该如何做才能组织CSS代码呢?

首先,组织CSS代码文件。所有的CSS都可以分为两大类:通用类和业务类。代码的组织应该把通用类和业务类的代码放置于不同的目录中。

css
 |-[业务类文件夹]
 |-[通用类-样式重置].css
 |-[通用类-公用组件].css
 |-[通用类-ie兼容].css
  • [通用类-样式重置].css 的作用是重置元素的默认样式,目的时让元素在各浏览器中有统一的外观。CSS Reset 简单的一句全部重置太过粗暴,大部分人都已投向 Normalize.css 的怀抱,当然国内不少团队也总结出自己的一套 reset.css,建议自行搜索了解。

Normalize.css - A collection of HTML element and attribute style-normalizations.

  • [通用类-公用组件].css 的作用是放置公用模块的样式和一些基础样式。公用模块包括页面对话框、提示框等公用组件的样式以及页面头部、底部、侧边栏等 UI 公用模块的样式。基础样式包括全局的页面布局设置、字体设置、背景和前景色等,也包括一些公有的class,这些公有class使用频繁,所以需要单独定义和使用,以提高代码的复用度。

强烈推荐使用 LessSass 等动态样式语言和预处理工具,方便写出高复用和高扩展性的 CSS 代码。

  • [通用类-ie兼容].css 的作用是放置兼容旧版 IE 浏览器的样式。如果把兼容旧版IE的CSS代码和正常的代码放置在一起,这种做法有两个缺点,一是增加了非IE浏览器的加载样式文件的负担,二时如果未来决定不再支持旧版的IE浏览器,则需要修改多个文件,从而增加了维护的复杂度。

  • 其余的CSS样式文件 则用于具体业务模块。不同模块的样式文件放置于不同的文件夹中。分隔模块的粒度并没有一个标准,原则上尽量保证每个模块对应的样式文件行数不超过200行,如果某个模块的样式文件太大,则会继续划分为更小的模块。

不要担心CSS样式文件过多,把关注点放在文件的管理上即可,因为到最后可以用自动构建工具把多个样式文件进行合并压缩处理。

3.元素单位

empx 还是 % ?亦或是 rem ?页面元素的尺寸(长度、宽度、内外边距等)以及页面字体的大小时和页面整体布局息息相关的,而页面布局的方式又是多种多样的。因此,如果没有合理地设置页面元素尺寸以及字体的大小,就会增加页面布局的复杂性,也会使得页面布局维护变得困难,还会使页面的扩展性和使用平台受到限制。那么该如何设置元素的尺寸和字体大小,从而达到最佳的可维护性呢?可参考以下三个建议:

  1. 尽量设置相对尺寸。页面应该是自适应呢,还是固定尺寸呢?这个取决于页面的设计。这里关注的是局部元素的尺寸要求使用相对大小,即局部自适应。这样当整体模块的尺寸更改时就不需要更改模块内部子模块的尺寸了。

  2. 只有在可预知元素尺寸的情况下使用绝对尺寸。编写的代码一定要先遵循设计要求,在某些场合可能必须使用绝对尺寸,例如网页整体的宽度固定、侧边栏宽度固定、页头和页尾的高度固定等。

  3. 使用 rem 设置字体大小。rem是个低调的单位,但在近一两年中开始火了起来。国内各大公司都已经投入使用,在一些常见的网站,如淘宝、腾讯、小米等移动站点,随处可见其踪影。详细用法可参见以下三篇文章或自行搜索了解。

web app变革之rem - 腾讯ISXUX
手机淘宝的flexible设计与实现 - 前端乱炖
MobileWeb 适配总结 - Lok'tar Ogar

4.样式重置

上文已提及,这里推荐阅读 @alsiso 同学写的 CSS Reset 专题文章。

关于CSS Reset那些事(一)- SegmentFault
关于CSS Reset那些事(二)- SegmentFault
关于CSS Reset那些事(三)- SegmentFault
关于CSS Reset那些事(四)- SegmentFault

5.样式排序

为什么要给样式排序?因为,如果CSS属性按照一定的规则排序,那么在开发过程中可以防止属性的重复定义,代码的检查者也能很清晰地查看CSS样式定义,更关键的是在后续维护过程中能快速定义特定的样式属性。尽管对CSS样式属性进行排序需要花费一些精力,但从代码的可读性和可维护性角度来考虑,这些付出将会是值得的。更何况,我们可以借助一些工具来完成。: )

一种较为合理的排序方式是 按类型分组排序。著名的 Web 前端专家 Andy Ford 推荐过一种按照类型分组排序的方式,他把CSS属性分为7大类:

  • 显示与浮动(Display & Flow

  • 定位(Positioning

  • 尺寸(Dimensions

  • 边框相关属性(MarginsPaddingBordersOutline

  • 字体样式(Typographic Styles

  • 背景(Backgrounds

  • 其他样式(OpacityCursorsGenerated Content

这种按照样式类型分组排列的方式不仅把功能相似的属性归类到一起,并且按照样式功能的重要性从上到下进行了排序。可以把影响元素页面布局的样式(如 floatmarginPaddingheightwidth等)排到前面,而把不影响布局的样式(如backgroundcolorfont等)放到后面。这种主次分明的排列方式,极大地提高了代码的可维护性。

整理推荐的CSS属性书写顺序 - CSDN
推荐大家使用的CSS书写顺序、规范 - 设计达人

当然,如果在编写代码的时候直接按照这种方式写肯定有难度,而且不方便频繁地修改。最佳方式是编写代码的时候按照自己最有效率的方式来写,编写完成并提交的时候使用工具对其进行排序。推荐工具:CSScomb,一款免费高效并提供在线和主流代码编辑器插件的CSS排序工具。

CSScomb - Makes your code beautiful.

6.权重制衡

什么是权重?如果前端工程师没有深刻理解这个概念,将会很难写出高质量的CSS代码。在讨论权重之前,我们先来讨论一下一些基础知识。

CSS样式有 6 种基础选择器:

  • ID 选择器(如 #page_content{}

  • 类选择器(如 .page-content-title{})

  • 属性选择器(如 a[href="http://www.google.com"]{}

  • 伪类和伪对象选择器(如 :hover{}、::after{}

  • 标签类型(如 div{}

  • 通配符选择器(如 body *{}

所有在CSS样式中定义的选择符都是由这 6 种基础选择器组合而成的,组合的方式分为三种:

  • 后代选择符(如 .page .title{}

  • 子选择符(如 .page>.title{}

  • 相邻选择符(如 .page+.title{}

CSS权重指的是这些选择器的优先级,优先级高的CSS样式会覆盖优先级的样式。优先级越高说明权重越高。根据 W3C 制定的CSS规范,CSS权重是通过如下规则计算的:

  1. 计算选择符中的ID选择器的数量(=a)

  2. 计算选择符中的类选择器、属性选择器以及伪类选择器的数量(=b)

  3. 计算标签类型选择器的伪对象选择器的数量(=c)

  4. 忽略全局选择器

按照规则,基础选择器具有这样的优先级:
ID > 类 | 伪类 | 属性选择器 > 标签类型 | 伪对象 > 通配符

分别计算 a、b、c 的值后,按顺序连接 a、b、c 三个数字组成一个新数值,此数值即为所计算的选择符的权重。另外,如果两个选择符的权重相同,则依照“就近原则”,最后定义的被采用。

你应该知道的一些事情——CSS权重 - W3CPlus

明白权重的计算规则后,我们可以制定一些相关原则来提高样式代码的重用性和可维护性。

  1. CSS样式中尽量不要使用ID选择器。一个页面中不允许有两个相同的ID,如果使用了ID选择器就意味着此此样式只能作用于一个元素,不能复用于其他元素。

  2. 减少子选择器的层级。降低选择符整体的权重,减少对HTML结构的依赖。

  3. 使用组合的CSS类选择器。面向对象编程一条原则:“多组合,少继承”。

7.兼容分离

上文已提及。

那些为了兼容旧版浏览器而添加的额外代码,被成为 hack 代码。大部分前端程序员都不愿意写 hack 代码,因为 hack 代码不易理解且维护困难。

以下是兼容 IE 浏览器的一些实践:

  • 熟悉 IE 浏览器中常见的样式兼容问题。IE 浏览器下的兼容问题一般分为两类,一类时浏览器本身的Bug,另一类是标准不兼容,或者不支持标准(这类问题居多)。

Browserhacks - ie

  • 分离样式兼容代码。为了当未来某个时期不在支持某个旧版本的浏览器时,方便移除这些兼容代码。

在 IE 浏览器中可以使用条件注释,让不同浏览器加载不同的样式文件以达到兼容代码和正常代码分离的目的。

<link rel="stylesheet" media="screen" href="css/style.css" />
<!--[if IE 8]><link rel="stylesheet" media="screen" href="css/ie8.css"><![endif]-->
<!--[if IE 7]><link rel="stylesheet" media="screen" href="css/ie7.css"><![endif]-->

另外,为了提高兼容样式的优先级,可以在根元素(<html>或者<body>元素)上针对不同的浏览器添加不同的样式类。

<!--[if IE 7]>       <html class="ie7"><![endif]-->
<!--[if IE 8]>       <html class="ie8"><![endif]-->
<!--[if gt IE 8]><!--><html>        <--<![endif]-->

参考

以上,欢迎拍砖斧正。

相关推荐