v2-3622f785117e21116dc9837d6e3ac641_r.jpg

简评:CSS 是一门入门比较简单,但真正使用起来又很困难的语言(有些人认为它不应该称为一门语言)。CSS 看起来凌乱复杂,其实攻克也不难,了解了 CSS 的发展背景你就会有对它有了系统性的认知。通过这一篇文章,你基本就会对 CSS 有了一个熟识的了解。

v2-85d897b7e26a4f6d60131029e7248543_hd.jpg

CSS 一直被web 开发者认为是最简单也是最难的一门奇葩语言。它的入门确实非常简单——你只需为元素定义好样式属性和值,看起来似乎需要做的工作也就这样嘛!然而在一些大型工程中 CSS 的组织是一件复杂和凌乱的事情,你更改页面上任意一个元素的一行 CSS 样式都有可能影响到其他页面上的元素。

为了解决 CSS 错综复杂的继承问题,开发者建立了各种不同的最佳实践,问题是哪一个最佳实践是最好的目前尚无定论,而且有些实践相互之间是完全矛盾的。如果你第一次尝试学习 CSS ,这对于你来说是相当迷惑的。

这篇文章的目的是通过回顾 CSS 的历史背景,介绍下时至2018年的今天 CSS 发展过程中的一些设计模式和工具的演变。通过对这些背景的理解,你将会更轻松的理解每个设计思想并且学以致用。接下来让我们开始吧!

CSS 基本样式使用

我们从一个最简单的网页 index.html 开始,这个文件中包含一个独立的样式文件 index.css :

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Modern CSS</title>
  <link rel="stylesheet" href="index.css">
</head>
<body>
  <header>This is the header.</header>
  <main>
    <h1>This is the main content.</h1>
    <p>...</p>
  </main>
  <nav>
    <h4>This is the navigation section.</h4>
    <p>...</p>
  </nav>
  <aside>
    <h4>This is an aside section.</h4>
    <p>...</p>
  </aside>
  <footer>This is the footer.</footer>
</body>
</html>

上面的 HTML 标签中没用使用任何 class 或者 id。
在没有任何 CSS 样式的情况下,我们的网站看起来是这个样子:

v2-3bff7b89379dfb250fbedd11abc62b9b_hd.jpg
点击查看在线demo

功能可用,但看起来不好看,我们可以继续在 index.css 加点 CSS 美化下排版:

/* BASIC TYPOGRAPHY                       */
/* from https://github.com/oxalorg/sakura */
html {
  font-size: 62.5%;
  font-family: serif;
}
body {
  font-size: 1.8rem;
  line-height: 1.618;
  max-width: 38em;
  margin: auto;
  color: #4a4a4a;
  background-color: #f9f9f9;
  padding: 13px;
}
@media (max-width: 684px) {
  body {
    font-size: 1.53rem;
  }
}
@media (max-width: 382px) {
  body {
    font-size: 1.35rem;
  }
}
h1, h2, h3, h4, h5, h6 {
  line-height: 1.1;
  font-family: Verdana, Geneva, sans-serif;
  font-weight: 700;
  overflow-wrap: break-word;
  word-wrap: break-word;
  -ms-word-break: break-all;
  word-break: break-word;
  -ms-hyphens: auto;
  -moz-hyphens: auto;
  -webkit-hyphens: auto;
  hyphens: auto;
}
h1 {
  font-size: 2.35em;
}
h2 {
  font-size: 2em;
}
h3 {
  font-size: 1.75em;
}
h4 {
  font-size: 1.5em;
}
h5 {
  font-size: 1.25em;
}
h6 {
  font-size: 1em;
}

这地方大部分都是关于排版(字体、行高等)样式的定义,也包含一些颜色和一个 layout 居中设置。为了让每个属性有个合理的值你需要学习点设计理论,但是这个地方我们用到的 CSS 本身并不复杂,你可以直接定义,结果如下所示:

v2-ccfd2a62ec97bffec184f5c855a6bd21_hd.jpg

Click here to see a live example

有所变化了吧!正如 CSS 许诺的一样——用一种简单的方式给文档添加上样式,不需要编程或者复杂的业务逻辑。不幸的是,实际情况会复杂的很多,我们不单单使用的是 CSS 的排版和颜色这种简单的样式定义。

CSS 的布局使用

在20世纪90年代,CSS 还未广泛普及之前,对于页面的布局没有太多的选择。HTML 最初是被设计为创建纯文本的一门语言,并不是包含侧边栏、列等布局的动态页面。早期的时候,页面布局通常使用的是 HTML 表格,在行和列中组织内容,这种方式虽然有效,但是把内容和表现杂糅在一块了,如果你想改变网页的布局就得需要修改大量的 HTML 代码。

CSS 的出现推动了内容(HTML)和表现(CSS)的分离,人们开始把所有的布局代码从 HTML 中移除放入到 CSS 中,需要注意的是,和 HTML 一样 CSS 的设计也不是用来做网页内容布局的,所以早期的时候试图解决这种分离设计是很困难的。

我们来用个实际例子来看下如何实现布局,在我们定义 CSS 布局前先重置下 padding 和 margin(会影响布局的计算),不同的区域我们定义不同的颜色(不要太在意好看不好看只要不同区域间足够醒目就可以)

/* RESET LAYOUT AND ADD COLORS */
body {
  margin: 0;
  padding: 0;
  max-width: inherit;
  background: #fff;
  color: #4a4a4a;
}
header, footer {
  font-size: large;
  text-align: center;
  padding: 0.3em 0;
  background-color: #4a4a4a;
  color: #f9f9f9;
}
nav {
  background: #eee;
}
main {
  background: #f9f9f9;
}
aside {
  background: #eee;
}

现在页面应该看起来如下:

v2-8fba410c70130bb8836dd64aa7b3ad3f_hd.jpg

Click here to see a live example

接下来我们用 CSS 来布局下页面内容,我们将按照时间顺序采用三种不同的方式,先从最经典的浮动布局开始吧。

基于浮动的布局

CSS 浮动属性最初是为了将图片浮动在一列文本的左侧或者右侧(报纸上经常看到)。早在21世纪初,web 开发者将这个属性的优势扩展到了任意的元素,这意味着你可以通过 div 的内容浮动创建出行和列的错觉。同样,浮动也不是基于这样的目的设计的,所以兼容性上会有很多问题。

2006年,A List Apart 上发表了一篇热门文章 In Search of the Holy Grail,文章概述了实现圣杯布局的详细方法——一个头部、三列内容和一个底部,你一定觉得一个简单的布局被称为圣杯布局很疯狂吧,但是在当时纯 CSS 的时代这的确很难实现。

下面是一个基于浮动布局的例子,用到了我们文章中提到的一些技术点:

/* FLOAT-BASED LAYOUT */
body {
  padding-left: 200px;
  padding-right: 190px;
  min-width: 240px;
}
header, footer {
  margin-left: -200px;
  margin-right: -190px;   
}
main, nav, aside {
  position: relative;
  float: left;
}
main {
  padding: 0 20px;
  width: 100%;
}
nav {
  width: 180px;
  padding: 0 10px;
  right: 240px;
  margin-left: -100%;
}
aside {
  width: 130px;
  padding: 0 10px;
  margin-right: -100%;
}
footer {
  clear: both;
}
* html nav {
  left: 150px;
}

仔细看下 CSS 代码,这里面为了让它工作包含一些必须的 hack 方式(负边距、clear: both、硬编码的宽度计算等),稍后我们会对这些细节做详细的解释。最终的结果如下:

v2-6be1970ed53f49366f0a2965df927a0c_hd.jpg

Click here to see a live example

看起来不错了,但是通过三列的颜色可以看出来他们的高度不一样,页面的高度也没有填充满屏幕。这些问题是浮动布局导致的,所有的浮动只是将内容放在某一区块的左边或者右边,但是没法知道其他区块的高度。这个问题一直没有个好的解决方案,直到 Flexbox 布局的出现。

基于 Flexbox 的布局

Flexbox CSS 属性实在2009年第一次提出来的,但直到2015年才得到浏览器的广泛支持。Flexbox 被设计为定义一个空间在行或者列上如何分布的,这让它比浮动更适合用来做布局,这意味在使用浮动布局十多年后,web开发者终于不再使用带有hack的浮动布局方式了。

下面是一个基于 Flexbox 布局的例子。注意为了让 Flexbox 生效我们需要在三列的外面额外包装一个 div:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Modern CSS</title>
  <link rel="stylesheet" href="index.css">
</head>
<body>
  <header>This is the header.</header>
  <div class="container">
    <main>
      <h1>This is the main content.</h1>
      <p>...</p>
    </main>
    <nav>
      <h4>This is the navigation section.</h4>
      <p>...</p>
    </nav>
    <aside>
      <h4>This is an aside section.</h4>
      <p>...</p>
    </aside>
  </div>
  <footer>This is the footer.</footer>
</body>
</html>

下面是 Flexbox 布局的 CSS 代码:

/* FLEXBOX-BASED LAYOUT */
body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.container {
  display: flex;
  flex: 1;
}
main {
  flex: 1;
  padding: 0 20px;
}
nav {
  flex: 0 0 180px;
  padding: 0 10px;
  order: -1;
}
aside {
  flex: 0 0 130px;
  padding: 0 10px;
}

这种方式和浮动布局相比更加紧凑了,虽然 flexbox 一些属性和值初看起来有些困惑,但是好歹不需要像浮动布局那样负边距的 hack 方案了,这是个巨大的进步。最终结果如下:

v2-3acd79844888f966161d58be2f3153ca_hd.jpg

Click here for a live example

效果好多了!所有的列高度都相同,并且占据了整个页面的高度。从某种意义上来说这似乎是完美的了,但是这个方式也有些小问题,其中一个就是浏览器的兼容性——主流的现代浏览器都支持flexbox,但是一些旧的浏览器不兼容。幸运的是浏览器厂商也正在尽最大努力终止对旧版本浏览器的支持,为web开发者提供更一致的开发体验。另一个问题是我们需要<div class="container">包裹HTML内容标签,如果能避免会更完美。理想状态下,任何CSS布局都不需要改变HTML标签的。

最大的缺点是CSS代码本身——flexbox虽然去掉了浮动的Hack,但是代码的可读性上变得更差了。你很难去理解flexbox的CSS,并且不知道页面上是如何去布局所有元素的。在写flexbox布局代码的时,有很多时候靠的是大量的猜测和尝试。

特别需要注意的是,flexbox被设计用来在单行或者单列中分割元素的——它不是设计用来给整个页面做布局的!尽管它能很好的实现(相对于浮动布局好很多)。另一种不同的规范是用来处理多行或者多列布局的,我们称之为CSS 网格。

基于 Grid的布局

CSS网格最早在2011年提出的(比flexbox提案晚不了多久),但是花了好长时间才在浏览器上普及起来。截止2018年初,大多数现代浏览器都已经支持CSS grid(这比一两年前有巨大的进步了)
下面我们看一下基于网格布局的例子,注意在这个例子中我们摆脱了flexbox布局中必须使用<div class="container">的限制,我们可以简单的使用原始的HTML,先看下CSS文件:

/* GRID-BASED LAYOUT */
body {
  display: grid;
  min-height: 100vh;
  grid-template-columns: 200px 1fr 150px;
  grid-template-rows: min-content 1fr min-content;
}
header {
  grid-row: 1;
  grid-column: 1 / 4;
}
nav {
  grid-row: 2;
  grid-column: 1 / 2;
  padding: 0 10px;
}
main {
  grid-row: 2;
  grid-column: 2 / 3;
  padding: 0 20px;
}
aside {
  grid-row: 2;
  grid-column: 3 / 4;
  padding: 0 10px;
}
footer {
  grid-row: 3;
  grid-column: 1 / 4;
}

虽然结果看起来和基于 flexbox 的布局一样,但是 CSS 在很大程度上得到了改进,它清晰地表达出了期望的布局方式。行和列的大小和形状在 body 选择器中定义,每一项 item 直接通过他们所在行和列的位置定义。

grid-column 这个属性你可能觉得不太好理解,它定义了列的起点和终点。这个地方让你觉得困惑的可能是明明有 3 列,却为什么定义的范围是1 到 4,通过下面的图片你就能理解了:

v2-5118403ab2f924c2b60d0b2e1b84dec3_hd.jpg

Click here to see a live example

第一列是从1 到 2,第二列是从2 到 3,第三列从3 到 4,所以头部的grid-column是从1 到4 占据整个页面,导航的grid-column是从1 到2 占据第一列等等

一旦你习惯了 grid 语法,你会觉得它是一种非常理想的 CSS 布局方式。唯一缺点就是浏览器支持,幸运的是过去一年中浏览器的支持又得到了进一步的提高。作为专为 CSS 设计的第一款真正的布局工具很难描绘它的重要性,从某种意义上来说,由于现有的工具需要太多的hack和变通方式去实现,因此web设计者过去对于布局的创意上一直很保守,CSS 网格的出现有可能会激发出一批从未有过的创意布局设计——想想还是挺激动人心的!

v2-1377282492cfb42352a695e899daac0a_hd.jpg

使用 CSS 预处理器扩展 CSS 语法

到目前为止,我们介绍了 CSS 的基本样式和布局,现在我们再来看下那些帮助 CSS 提升语言本身体验的工具,先从 CSS 预处理器开始吧。

CSS 预处理器允许你使用不同的语言来定义样式,最终会帮你转换为浏览器可以解释的 CSS,这一点在当今浏览器对新特性支持缓慢的情况下很有价值。第一个主流的 CSS 预处理器是2006年发布的 Sass,它提供了一个新的更简洁的语法(缩进代替大括号,没有分号等等),同时增加了一些 CSS 缺失的高级特性,像变量、工具方法还有计算。下面我们使用 Sass 变量实现下前面例子中带颜色的区域定义:

$dark-color: #4a4a4a
$light-color: #f9f9f9
$side-color: #eee
body
  color: $dark-color

header, footer
  background-color: $dark-color
  color: $light-color

main
  background: $light-color
nav, aside
  background: $side-color

注意我们用$定义了可复用的变量,省略了大括号和分号,语法看起来更加清晰了。简洁的语法让 Sass 看起来很棒,但变量这样的特性出现在当时来说意义更大,这为编写整洁可维护的CSS 代码开辟了新的可能性。
使用Sass你需要安装Ruby(Ruby),这门语言主要是让 Sass 编译成正常的 CSS,同时你需要安装Sass gem,之后你就可以通过命令行把你的 .sass 文件转成 .css 文件了,我们先看一个使用命令行的例子:

sass --watch index.sass index.css

这个命令定期把index.sass中的 Sass 代码转为 CSS 写入到index.css文件中(--watch参数设定后会实时监听 .sass 文件改动并执行编译,非常方便)

这个过程被称为构建步骤。这在2006年的时候是非常大的一个障碍,如果你对 Ruby 这样的编程语言熟悉的话,这个过程非常简单。但是当时很多前端开发者只用 HTML 和 CSS,他们不需要类似这样的工具。因此,为了使用 CSS 预编译的功能而让一个人学习整个生态系统是很大的一个要求了。

2009年的时候,Less CSS 预编译器发布。它也是 Ruby 写的,并且提供了类似于 Sass 的功能,关键不同点是它的语法设计上更接近 CSS。这意味着任何 CSS 代码都是合法的 Less 代码,同样我们看一个用 Less 语法的例子:

@dark-color: #4a4a4a;
@light-color: #f9f9f9;
@side-color: #eee;
body {
  color: @dark-color;
}

header, footer {
  background-color: @dark-color;
  color: @light-color;
}

main {
  background: @light-color;
}
nav, aside {
  background: @side-color;
}

语法上几乎是相同的(变量的定义使用@替代了$),但是 Less 和 CSS 一样带有大括号和分号,没有 Sass 例子的代码看起来漂亮。然而,和 CSS 相近的特性反而让开发者更容易接受它,在2012年,Less 使用了JavaScript(Node.js)重写了替换了 Ruby,性能上比 Ruby 编译更快了,并且很多在工作中使用了 Node.js 的人更容易上手了。

把这段代码转化为标准的 CSS,你需要安装 Node.jsLess,执行的命令行如下:

lessc index.less index.css

这个命令把index.less文件中的Lessz代码转化为标准的 CSS 代码写入到index.css文件中,注意 lessc 命令不能监听文件的变化(和 sass 不一样),这意味着你需要安装其他自动监听和编译的组件来实现该功能,增加了流程的复杂性。同样,对于程序员来说使用命令行的方式并不难,但是对于其他只想使用 CSS 预编译器的人来说还是个非常大的障碍。

汲取了 Less 的经验,Sass 开发者在2010年发布了一个新的语法叫 SCSS(与 Less 类似的一个 CSS 超集),同时发布了 LibSass,一个基于 C++ 扩展的 Ruby 引擎,让编译更快并且适配于多种语言。
另外一个 CSS 预处理器是2010年发布的 Stylus,使用 Node.js 编写,和 Sass 或者 Less 相比更注重于清晰的语法。通常主流的CSS预编译器就这三种(Sass,Less,Stylus),他们在功能方面非常相似,所以你不必担心选择哪一个会是错误的。

然而,有些人认为使用CSS预处理器开始变得越来越没必要,因为浏览器最终会慢慢实现这些功能(像变量和计算)。此外,还有一种称为 CSS 后处理器的方法,有可能会让 CSS 预处理器过时(显然这存在些争议),我们在后面会详细介绍下。

使用 CSS 后处理器的转换功能

CSS 后处理器使用 JavaScript 分析并转换你的 CSS 为合法 CSS,从这方面来看和 CSS 预处理器很相似,你可以认为是解决同一个问题的不同方式。关键的不同点是 CSS 预处理器使用特殊的语法来标记需要转换的地方,而 CSS 后处理器可以解析转换标准的 CSS,并不需要任何特殊的语法。举一个例子来说明下,我们用最初定义的 header 标签样式来看一下吧:

h1, h2, h3, h4, h5, h6 {
  **-ms-hyphens: auto;
  -moz-hyphens: auto;
  -webkit-hyphens: auto;**
  hyphens: auto;
}

粗体部分的属性成为厂商前缀,厂商前缀是浏览器厂商对 CSS 新功能的实验和测试使用的,在正式实现前提供给开发者使用 CSS 新属性的一种方式。-ms代表IE浏览器,-moz是火狐浏览器,-webkit是基于 webkit 内核的浏览器。

定义这些不同浏览器厂商的前缀属性是非常烦人的,尽量使用生成工具自动添加厂商前缀。我们可以使用 CSS 预处理器来完成这个功能,例如,我们可以用 SCSS 来实现:

@mixin hyphens($value) {
  -ms-hyphens: $value;
  -moz-hyphens: $value;
  -webkit-hyphens: $value;
  hyphens: $value;
}
h1, h2, h3, h4, h5, h6 {
  @include hyphens(auto);
}

这个地方使用了 Sass 的 mixin 功能,你可以定义一个 CSS 代码块然后在其他任何地方重用,当这个文件被编译成标准的 CSS 的时候,所有的@include语句都被替换成与之匹配的@mixin中的 CSS。总体来说,这个解决方案也不差,但是你仍然要为每个需要厂商前缀的 CSS 属性定义一个 mixin,这些 mixin 的定义将需要不断的维护,比如当浏览器支持了某个 CSS 属性后你就要在你的定义中移除掉该属性。

比起写 mixin 的方式,直接正常写 CSS 然后由工具自动识别添加需要厂商前缀的属性的方式显然更优雅些。CSS 后处理器就恰好能完成这样的功能。比如,如果你使用 PostCSSautoprefixer 插件,你就可以直接写正常的CSS并不需要指定浏览器厂商前缀,剩下的工作全交给后置处理器去处理:

h1, h2, h3, h4, h5, h6 {
  hyphens: auto;
}

当你使用CSS后处理器运行这段代码的时候hyphens: auto; 将被替换成包含所有浏览器厂商前缀的属性,这意味着你可以正常写CSS不用担心各种浏览器兼容性问题,岂不是很棒!
除了PostCSS的autoprefixer插件还有很多有意思的插件,cssnext 插件可以让你体验下一些实验性质的CSS新功能,CSS modules 可以自动改变 class 的名字避免名称冲突,stylelint 能检查出你 CSS 代码中一些定义错误和不符合规范的写法。这些工具在过去一两年里开始流行起来,给开发者提供了从未有过的工程化流程。

然而,进程的发展总是有代价的,安装和使用 CSS 后处理比 CSS 预处理器更复杂。你不仅要安装、执行命令行,还需要安装配置各个插件并且定义好各种复杂的规则(比如你的目标浏览器等)。很多开发者不再直接使用命令行运行 PostCSS 了,而是通过配置一些构建系统,像GruntGulpwebpack,他们可以帮助你管理前端开发工作中需要的各种构建工具。

值得注意的是对于 CSS 后处理器存在些争议,有人认为这个术语有些让人迷惑(一种说法是建议都应该叫 CSS 预处理器,还有一种说法是应该都简称 CSS 处理器,等等),有人认为有了 CSS 后处理器完全可以不需要 CSS 预处理器,有人则主张两者一起使用。不管怎么说,去了解下 CSS 后处理器的使用还是非常值得的。

v2-4dc8bd85499a0923324a40448235082d_hd.jpg

使用 CSS 设计模式

CSS 预处理器和 CSS 后处理器让 CSS 开发体验有了巨大的提升,但是单靠这些工具还不足以解决维护大型项目 CSS 代码的问题。为了解决这个问题,人们编写了一些关于如何写CSS的指导方针,通常被称为 CSS 规范。

在我们深入分析 CSS 规范前,首先要搞清楚是什么让 CSS 随着时间推移变得更加难维护,关键点是 CSS 是全局性的——你定义的每个样式都会全局应用到页面的每个部分,用一个命名约定来保证class名称的唯一性或者有特殊的规则来决定指定样式应用到指定元素。CSS 规范提供了一个有组织性的方式来避免大量代码时出现的这些问题,让我们按照时间顺序来看看主流的一些规范吧

OOCSS

OOCSS(面向对象的CSS)是在2009年首次提出的,它是围绕两个原则建立的规范。第一个原则是结构和样式分离,这意味着定义结构(布局)的 CSS 不应该和定义样式(颜色、字体等)的CSS混杂在一起,这样我们就可以很简单的为一个应用定义新的皮肤了;第二个原则是容器和内容分离,把元素看成是一个可重用的对象,关键核心点是一个对象不管用在页面的任何位置都应该看起来是相同的。

OOCSS 提供了成熟的指导规范,但是对于具体的执行规范并没有明确指出。后来出现的SMACSS 采用了它的核心概念,并且添加了更多的细节,使用起来更简单了。

SMACSS

SMACSS(可扩展模块化架构的 CSS)是在2011年出现的一种设计模式,它将 CSS 分为5个不同的类别——基本规范、布局规范、模块、状态规范和样式规范。SMACSS也有一些推荐的命名规则,对于布局规范使用l-或者layout- 作为前缀;对于状态规范,使用is-hidden 或者is-collapsed 作为前缀。

相比 OOCSS,SMACSS 有了更多细节上的规范,但是 CSS 规则该划分为哪一类别的规范中,这是个需要仔细考虑的问题。后来出现的 BEM 对这一方面进行了改进,让它更易使用了。

BEM

BEM (块, 元素, 修饰符)是在2010年出现的规范,它的思想主要是围绕把用户界面切分成独立的块。块是一个可重用的组件(举个例子像表单搜索,可以这样定义<form class="search-form"></form>),元素是块的一部分不能单独重用(比如表单搜索中的button,<button class="search-form__button">Search</button>),修饰符是定义了块或者元素外观、状态或者行为的实体(比如禁用搜索按钮,定义为<button class="search-form__button search-form__button--disabled">Search</button>)。

BEM 的规范很容易理解,对于新手来说命名规则上也很友好,缺点就是可能会导致class名字非常长,并且没有遵循传统的命名规范。后来出现的 Atomic CSS 又把这个非传统方式带到了一个新的高度。

Atomic CSS

Atomic CSS (也称为 功能性CSS)是2014年出现的一个规范,它的思想是基于可视化的方法创建小而功能单一化的 class。这种规范与OOCSS、SMACSS 和 BEM 完全相反——它并不是把页面上的元素看做是可重用的对象,Atomic CSS 忽略掉了这些对象,每一个元素使用了可重用的单一功能的 class 样式集合。因此像<button class="search-form__button">Search</button>就被替换成这样的写法了<button class="f6 br3 ph3 pv2 white bg-purple hover-bg-light-purple">Search</button>

如果你看到这个例子第一反应是被吓的退缩了,没关系你并不是唯一有这想法的人——很多人认为这种方式完全违背了 CSS 的最佳实践,但是,关于这个有争议的规范在不同场景下的应用也产出了一系列精彩的讨论。这篇文章很清晰的分析了传统的分离思想是CSS依赖于HTML创建(即使使用像BEM这类的规范),而Atomic的方式是HTML依赖于CSS创建,两者都没错,但是仔细想想你会发现 CSS 和 HTML 彻底分离的想法是实现不了的。

其他的 CSS 设计模式,像 CSS in JS 其实也包含了 CSS 和 HTML 相互依赖的思想,这也成为了一个饱受争议的设计规范之一。

CSS in JS

CSS in JS 是2014年推出的一种设计模式,它的核心思想是把 CSS 直接写到各自组件中,而不是单独的样式文件里。这种方式在React框架中引入的,最早是使用内联样式,后来又进化成了使用 JavaScript 生成 CSS 然后插入到页面的 style 标签中的方式。

CSS in JS 再一次违背了 CSS 中关于分离的最佳实践,主要原因是 web 随着时间推移发生了很大的变化。最初web大部分都是静态网站——这种情况下HTML内容和CSS表现分离是很有意义的,但现在大部分应用都是动态web构建——这种情况下可重用的组件更加有意义了。

CSS in JS设计的目标是定义边界清晰包含自己 HTML/CSS/JS 的独立组件,并且不受其他组件的影响。React是最早采用这种思想的框架,后续也影响到了其他框架像 Angular、Ember和 Vue.js。需要注意的是 CSS in JS 的模式相对来说比较新的,开发人员正在不断的尝试开发web应用组件时的一些CSS最佳实践。

五花八门的设计模式很容易让你不知所措,最重要的记住一点——没有银弹。

结论

简而言之这就是现代 CSS。我们介绍了 CSS 基本排版样式,浮动布局、flexbox 和 grid 布局,了解了 CSS 预处理器为 CSS 提供的新语法,比如变量和 mixins,还了解了 CSS 后处理器的转换功能,像给 CSS 添加厂商前缀,并且使用 CSS 的一些设计模式克服了全局CSS的一些问题。在这里我们没有时间去挖掘更多 CSS 其他功能了,CSS 覆盖面太广了——任何一个说它简单的人可能只是对它一知半解吧!

现代 CSS 的多变和快速发展多少让人感到有些沮丧,但是重要的是要记住web随着时间推移进化的历史背景,并且有一群聪明的人愿意为 CSS 向更好的方向的进化去创建一些工具和指导规范。作为一名开发者是一件幸运的事情,我希望这篇文章提供的信息能作为一个路线图帮助你更好的畅行在 CSS 路程中!

v2-e58f96cd00fcac59ceb3ceb6ec925f2d_hd.jpg

英文:Modern CSS Explained For Dinosaurs

极光JIGUANG
1.3k 声望1.3k 粉丝

极光(www.jiguang.cn)是中国领先的移动大数据服务商。其团队核心成员来自腾讯、摩根士丹利、豆瓣、Teradata和中国移动等公司。公司自2011年成立以来专注于为app开发者提供稳定高效的消息推送、统计分析、即时通...