[译] 探索 SMACSS:可扩展的模块化 CSS 框架

当咱们在从事大项目或团队开发工做时,咱们常常会发现咱们写的代码,凌乱、难以阅读而且难以扩展。尤为是当一段时候后咱们回头再看本身的代码,必须回想起当初本身写的时候的思路才能看懂。css

所以,人们建立了许多 CSS 框架来对 CSS 代码进行样式化,使其更具可读性。好比说,SMACSS,即 Scalable(可扩展)Modular Architecture(模块化)CSS,就旨在实现这一点。我采用的是 Johnathan Snook 定的那套 CSS 框架指南。html

SMACSS 的架构方法与 Bootstrap 或 Foundation 等 CSS 框架略有不一样。相反,它是一组规则,更是一套模板或指南。所以,让咱们来深刻探究下这些 CSS 设计模式,看怎么用它们来让咱们的代码更好、更整洁、更易读、更具模块化。前端

每一个 SMACSS 项目结构分为 5 种规则:android

  1. Base(基础)
  2. Layout(布局)
  3. Modules(模块)
  4. State(状态)
  5. Theme(主题)

Base(基础规则)

在 SMACSS 中,基础样式定义了元素全局的默认样式。若是你用了样式重置代码,那会让你的样式表如今不一样浏览器上保持一致,即使这些浏览器内部定义的默认 CSS 有所不一样。ios

在基础规则中,你应该只包含基本元素选择器或者那些伪类选择器,不该包含类选择器或者 ID 选择器。(你应该在理由至关充分时才将类或 ID 放进去,可能也就只有一种状况了:你用了第三方插件的节点又想对特色节点的默认样式进行覆盖。)git

这是一个基础规则的文件单元的例子:github

html {
    margin: 0;
    font-family: sans-serif;
}

a {
    color: #000;
}

button {
    color: #ababab;
    border: 1px solid #f2f2f2;
}
复制代码

它应该包含计划在整个网站上使用的默认的大小、边距、颜色、边框和其余默认值。你的排版和表单元素应该在每一个页面上具备统一的样式,给人感受它们是统一的设计和主题。web

无论你用不用 SMACSS,我都强烈建议避免使用 !important,也不要使用深嵌套,关于为何我会在这篇帖子的后面进行深刻讨论。此外,若是你的项目使用了 CSS 重置代码,那你应该把它放在这一部分(我更喜欢使用 Sass,这样我就能够在 SASS 文件顶部方便地将重置代码引入进来,而不须要将其复制或者在每一个页面的 <header> 元素单独引用)。后端

相关资源: Theming with Sass: An SCSS Tutorial设计模式

Layout(布局规则)

布局将会把页面分红几个主要部分 — 不是导航或折叠面板等部分,而是真正的顶级划分。

Example SMACSS layout styles: header, sidebar, content/main, and footer

SMACSS 布局规则包括顶部栏、侧边栏、正文、页脚等主要部分。

这些布局包括多个 CSS 模块例如 boxes、cards、unordered lists 和 galleries 等,但我会将这些模块放到下一节再详作讨论。让咱们经过一个网页例子来看看怎么对页面进行布局划分:

An example web page that can be organized into header, main, and footer layout styles using SMACSS

这些布局包含一些模块,好比顶部栏的连接和 logo,正文的盒子结构和文章,页脚的连接和版权。对于上面的布局,咱们一般会设置 ID 选择器,由于他们在页面上是单独惟一的。

你还应该使用字母 l 为布局规则添加前缀,以区分其余的模块样式。一般你要设置一些和布局相关的东西,好比边框,对齐,外边距等。页面那些大布局的背景也能够考虑写进去,即便它看起来不那么像是一种布局样式。

这是一个布局规则的例子:

#header {  
    background: #fcfcfc;
}

#header .l-right {
    float: right;
}

#header .l-align-center {
    text-align: center;
}
复制代码

你也能够将上面这些工具样式用在对齐上,比方说你想给 header 子节点或节点文本进行对齐定位,那你只需简单地将合适的类名用在节点上。

另外一个例子,你能够在布局框中使用一些默认的外边距,例如 .l-margin20px 的页边距。而后,不管您想要填充某个 container、element、card 或者 box ,只需将 l-margin 类添加到其中便可。不过你要用一些可复用的写法:

.l-full-width {
    width: 100%;
}
复制代码

不是像这样内部耦合的东西:

.l-width-25 {
    width: 25px;
}
复制代码

我想花点时间谈谈 SMACSS 中的命名规则。若是您从未在 CSS 中据说过命名空间的概念,那它基本上就是将名称添加到另外一个元素的开头,以帮助区分它与其余任何元素。可咱们为何要这么作呢?

我不知道你是否遇到过下面的问题。你写 CSS 代码时发现页面上有一个标签,因而你给它加了一些样式,并命名为 .lable 类。以后你又遇到一个元素,也想将其命名为 .label 类,但样式与前面的不一样。因而两个不一样的东西拥有相同的名称,这就是一次命名冲突。

命名空间可帮助你解决此问题。最终,它们在同一级别上被称为相同的东西,但因为应用了不一样的前缀,因而属于不一样的命名空间,也就能够表示两种不一样的样式

.box--label {
    color: blue;
}

.card--label {
    color: red;
}
复制代码

Module(模块规则)

正如我前面提到的,SMACSS 是页面上可重用的小代码块,是单一布局的一部分。这部分 CSS 咱们想要存储到单独的文件夹中,由于咱们在一个网页会有不少这样的模块代码。而且随着项目的增加,咱们能够经过文件夹结构来拆分,好比说,模块/页面的结构

An example file/folder hierarchy using SMACSS and Sass

因而在前面例子中,假如咱们(在页面上)有一篇文章,它能够做为一个独立的模块。如何在这里构建 CSS 呢?咱们应该有一个 .article 的类,它有 titletext 的子元素。所以,为了让它们保存在同一模块,咱们须要在子元素上使用前缀:

.article {
    background: #f32;
}

.article--title {
    font-size: 16px;
}

.article--text {
    font-size: 12px;
}
复制代码

你必定注意到咱们在模块前缀后面使用两个连字符。这是由于有时模块名称有两个单词或者它们的前缀相似 big-article。咱们须要两个连字符来描述子元素的位置。好比你能够试着比较 big-article-titlebig-article--titlebig-article--text

此外,若是特定模块占用了大部分页面,您能够将模块嵌套在模块中:

<div class="box">
    <div class="box--label">This is box label</div>
    <ul class="box--list list">
        <li class="list--li">Box list element</li>
    </ul>
</div>
复制代码

在这个简单的例子中,你能够看到 box 是一个模块 list 是在它里面的另外一个模块。使用 list--lilist 模块的子项而不是 box 的。这里的关键概念是每一个 CSS 规则最多有两个选择器,但在大多数状况下只有一个选择器是带前缀的。

这样,咱们能够避免重复规则,而且在具备相同名称的子元素上具备额外的选择器,从而提升速度。它也有助于咱们避免使用不须要的 !important 规则,这些规则是结构不合理的 CSS 项目的标志。

好的例子(注意单选择器):

.red--box {
    background: #fafcfe;
}

.red-box--list {
    color: #000;
}
复制代码

很差的例子(注意选择器内的重复和重叠):

.red .box {
    background: #fafcfe;
}

.red .box .list {
    color: #000;
}

.box ul {
    color: #fafafa;
}
复制代码

State(状态规则)

在 SMACSS 中状态规则是描述咱们的模块在不一样状态下显示外观的一种方式。因此说这一部分是关于交互性的:咱们须要有不一样的行为去描述元素的隐藏、扩展或修改。例如,jQuery 折叠面板控件就须要定义状态,来表示节点内容什么时候可见什么时候不可见。它有助于咱们在特定时刻定义元素的样式。

若是状态规则与布局规则应用于同一元素上,此时咱们要添加额外的规则来覆盖前面的规则(若是有的话)。状态规则优先,由于它是规则链中的最后一个规则。

与布局规则同样,咱们建议在状态规则使用前缀。这有助于咱们识别它们并给予它们优先权。这里咱们使用 is 前缀,如 is-hiddenis-selected

<header id="header">
    <ul class="nav">
        <li class="nav--item is-selected">Contact</li>
        <li class="nav--item">About</li>
    </ul>
</header>
复制代码
.nav--item.is-selected {
    color: #fff;
}
复制代码

在这里,!important 是可使用的,由于状态规则常常被用于 JavaScript 的修改而不是渲染时。例如,你须要一个元素在网页加载时是隐藏的,而在点击按钮时显示,可是默认类是像下面这样写的:

.box .element {
    display: none;
}
复制代码

所以若是你只是添加了下面代码:

.is-shown {
    display: block;
}
复制代码

即便你经过 JavaScript 添加了 .is-shown 以后它仍是隐藏的,这是由于第一条规则是是二级深度的,将后一条规则覆盖。

所以你能够改成这样定义状态类:

.is-shown {
    display: block !important;
}
复制代码

这就是咱们如何区分状态规则和布局规则,布局规则仅用于页面的初始加载。这样不只能够达到目的,还能够保持最少选择器的优点。

Theme(主题规则)

这个应该是最显而易见的规则,由于它定义了颜色、形状、边框、阴影还有其余等等。这些大多数都是在网站上重复使用的元素。咱们没必要在每次使用它们的时候都从新定义它们一下,相反,咱们但愿定义一个独特的类而后使用时只需添加上便可。

.button-large {
    width: 60px;
    height: 60px;
}
复制代码
<button class="button-large">Like</button>
复制代码

不要将 SMACSS 主题规则和基础规则混淆,基础规则定义了默认外观,相似于重置浏览器的默认设置,而主题规则定义了一组最终外观的样式,惟一的颜色方案。

当网站具备多套样式或者须要在不一样状态下使用不一样主题时,主题规则很是有用,由于当用户经过页面上的某些事件例如,主题切换按钮,触发时,主题规则能够很方便地更改和切换。至少,他们将全部主题风格保存在一个地方,以便你能够轻松地更改它们并使它们保持良好的组织结构。

CSS 组织方法

我已经介绍了这个 CSS 架构思想的关键概念。若是你想了解更多,请访问 SMACSS 的官方网站并进行深刻的学习。

你也可使用更高级的方法例如 OOCSS 和 BEM。后者几乎包含了全部前端工做流程和技术。可是一些人会以为 BEM 的选择器太长过重,使用起来太复杂。若是你须要更简单易懂,并容易将其归入你的工做流程 — 以及为你和你的团队定义基本规则的东西 — SMACSS 很是适合。

这不只让团队新成员很容易的理解之前开发者的工做,还帮助他们快速上手项目,并无任何代码风格上的差别。 SMACSS 只是一个 CSS 框架,它完成了它所描述的工做,很少也很多。

了解基础知识

CSS 有几种不一样的类型?

有三种不一样的类型。内联 CSS 直接放在 HTML 元素的样式属性上。内部 CSS 位于 HTML header 内部 style 标签内。外部 CSS 是独立的文件并经过 HTML 来索引到,避免网站在不一样网页内编写重复的代码。

“CSS 模板”是什么意思?

CSS 模板一般是用来定义特定的布局以便咱们在不一样网页甚至不一样网站上使用它们。可是除了布局,它们有时也用来为特定元素例如模态框和按钮甚至它们的组合而定义的一组规则。其余一些则用来定义 HTML 元素的默认样式。

为何 CSS 如此重要?

CSS 在现代网页中绝对是必须的。没有它,网页只是空白页面上的一堆纯文本和图片。它不只给网页提供样式,还组织布局和提供动画效果 — 所以它对互交性也很重要。

使用 CSS 有什么优势?

一个主要的优势是将全部的样式放在一块儿而不是让它们分散在整个网站的每个元素上。它为咱们提供了更多的格式选项,有助于优化页面加载时间和增长代码的复用性。

为何可扩展性如此重要?

通常来讲,随着项目增加,可扩展性带来的可伸缩性和可维护性很是重要。特别是在CSS中,若是咱们编写的代码不具有可扩展性和模块化,它会迅速失去控制,变得难以理解和工做,特别是对于新手而言。 所以咱们须要 SMACSS。

若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索