对于结构化HTML和CSS的一些思考。

网页的三个构成部分

网页是由三个部分构成的:结构、展示和内容。变动最大的是内容,随时都有可能变。其次是展示,而最稳定的是结构。

结构化 HTML

网页的结构分成两个,一个是其信息结构,一个是其 HTML 的结构。HTML 本身应该是于展示无关的,仅仅是为了描述信息的结构和做内容的容器。所以,我们应该这样写 HTML:

<h1 class="logo">Site Name</h1>

h1 代表其结构类型(第一级 heading,即网站名称),而 logo 则是其内容类型。此处,不考虑样式的问题,只考虑信息的结构。

我们所熟知的信息结构一般是从书本或者平面媒体中发展而来的,而信息结构的某些元素常常是有固定位置的。比如有些东西总是放在页眉的,页码什么的一般则是放在页尾。HTML5 考虑到了这一点,所以为我们加上了一些和位置语义元素,比如 header、footer、aside 等等。

此外,有些印刷效果也是有标准的,比如在行文中如果提到主要描述对象(比如产品介绍中的产品、个人介绍中的人名等等)的时候,常常会使用粗体,而在使用舶来语的时候则常常会使用斜体。HTML5 也考虑到了这一点,所以把 b、i 这样的元素又重新招了回来,用作行文语义元素。

除此之外,HTML5 还提供了 article、section 等结构语义元素,以及 nav、menu 等功能语义元素,帮助你尽量减少无意义的 div 和 span 的使用。

结构化 CSS

CSS 的结构包括两部分,如何使用 CSS 选择器,以及如何使用 CSS 属性。

CSS 的属性应该按照某种顺序来排列,以便快速浏览和查错。可以按照字母顺序排列,也可以按照其意义来排列(比如定位-显示-尺寸-内外边距-背景-边框-字体-行等等),个人推荐后者。我个人采取的顺序是:

position
float, clear
display
width, height
padding, margin
background
border
font, color
line-height
text-align
...

我们之前提过,结构是高度稳定的,所以,要想写出稳定的、结构化的 CSS,我们必须参照 HTML 结构。正如此前所说,元素名字是结构类型,class 是内容类型,二者结合则可以知道这个元素在结构中处于哪个部分(或者哪种角色),还可以知道其具体意义和作用。

不过,光有这些还不够,还得知道其在结构中所处的层级才能准确定位到这个元素,所以,我们可以采用下面这种办法来选择元素:

article.product section.coupon {
}

关于 id

从标准上来说,id 是不适合做选择器的。HTML5 的标准草案认为 id 应该是不透明的,是无意义的,所以,我认为它不适合用作 CSS 选择器。id 的最大作用有两个,一是作为锚点来做文档定位,二是作为 label 的 for 对象。

尽管标准称 id 和其所在元素不应有对应关系,但是我仍然推荐你使用有意义的 id 名,但是不要用它来做选择器,因为其唯一性和超高的选择器优先度会让其很难使用。假设你有一个 id 叫做 logo,比如就是 h1#logo,看上去不错,但是万一你想在页尾再加一个 logo 怎么办?如果用的是 class,你完全可以上面的是 h1.logo,下面的是 small.logo,同样的上下文意义,但是不同的类别。这样的例子还有很多。

此外,使用 id 将会让你的 CSS 结构受到限制。你在网站的一个页面使用过此 id 之后,必须小心全站的其他页面以及将来的新页面中都不能出现这个 id——除非你把这些样式全部分布在不同的 CSS 文件,但那样又会造成其他问题。

所以,简单一句话,就是不要用 id 来做样式。

也许你会觉得上面这种选择器的用法不好。为什么呢,因为写得太麻烦了,层级很多,每一个都要写元素名字和 class。你也许会说,拿掉前面的元素名字吧。不妥,因为这样你就无法准确定位到这个元素了,因为用的是 class,如之前所说,除了 h1.logo,还可能会有 small.logo。那么,中间拿掉几个元素?也不妥,因为这也会造成样式继承的问题。当然,这是 CSS 本身语言的问题,不过幸好,我们还有帮手可以帮忙解决。

这个帮手就是 LESS。

LESS

LESS 最直白的作用就是帮你省去反复写 CSS 层级关系的烦恼,比如:

article.product {
    section.coupon {
    }
}

除此之外,LESS 还有很多的功能,可以帮助我们写出条理清晰的 CSS。

变量

@PRIMARY-COLOR: #FF0000;
@SECONDARY-COLOR: #00FF00;
@MAIN-FONT: sans-serif;
@BODY-FONT: serif;

LESS 的变量可以用来:

  • 定义主字体、副字体
  • 定义主颜色、副颜色、着重色等等

总之一切可以简单替换的属性都可以用它来定义。

Mixin

用惯了 Bootstrap 的朋友会说,用 Bootstrap 多好,任何东西加一个 .btn 就变成按钮,再加一个 primary-btn 就变成主按钮,还可以切换主题和颜色等等。这样的结构是非语义化的,因为它把结构类型写进了本应是内容类型的 class 中。不过,LESS 的 Mixin 可以帮助我们解决这个问题。

.PRIMARY-BUTTON {
    background-color: #FF0000;
    color: #FFF;
    border-radius: 5px;
}

a.quote {
    .PRIMARY-BUTTON;
}

此外,Mixin 还可以嵌套和传参数,这是非常方便的。不过,一定要小心嵌套层次过多导致新的结构以及可读性问题。

函数和运算符

LESS 提供了很多使用的函数和运算符,其中最有用的是颜色函数。

a {
    color: darken(@PRIMARY-COLOR, 50%);
    color: @PRIMARY-COLOR * 2;
}

总结

网页是分成三部分的,结构、展示和内容。最稳定、最清晰的是结构,所以 HTML 和 CSS 应该贴合结构。要让 HTML 贴合信息结构,可以用元素名称来指代其结构类型,用 class 来指示其上下文的意义。要让 CSS 贴合 HTML 结构,则应该使用完整的元素名+ class 来选择元素,并在 CSS 里复制 HTML 的结构。由于要复制HTML的结构是很麻烦的,而且可能产生很多重复的代码,所以我们可以使用 LESS 来帮忙。

这样的写法有几个好处:

  • 结构清晰,条理清楚,方便查阅,看着舒服
  • 结构和展示的完全分离,方便修改、信息导出或者做响应式设计等等
  • 语意化的网页,方便搜索引擎等来获取信息