思考 CSS 架构

QuyenGiffen 7年前
   <p>你有没有在一个逐渐膨胀的 CSS 项目中感到混乱呢?保持样式风格统一和 HTML 的影响是比较困难的:尽管修改一个较小的问题,都可能创建更多丑陋的 hack,也可能 CSS 的小改变会影响 JavaScript 的功能。但是这些问题能在我们的项目开始的时候静心规划,就能很大程度上避免这些问题。让我们开始说 CSS 架构吧。</p>    <h2><strong>思考一个好的架构</strong></h2>    <p>一个好的 CSS 架构是具有良好的可扩展性。可扩展性是在任何项目开发中都是具有挑战性的,范围的扩大或者团队人数的增加,这些挑战在 CSS 中也不例外。层级和全局的特性使 CSS 很强大,反之在开发过程中也是脆弱的。如果你写了一段时间 CSS,你会发现当改变一行 CSS 来修复一个功能的时候会破坏一批其他的 CSS 功能,这将让你很头痛。细心的规划能提供下列的好处:</p>    <ul>     <li> <p>更少的样式</p> </li>     <li> <p>更少的样式冲突</p> </li>     <li> <p>更长的维护周期</p> </li>     <li> <p>更快的提升新团队成员</p> </li>     <li> <p>团队成员之间更容易交流</p> </li>     <li> <p>更平稳的项目交接</p> </li>    </ul>    <h2><strong>CSS 规则的类型</strong></h2>    <p>Jonathan Snook 对 CSS 规则进行分类的概念在他的书中很受欢迎 Scalable and Modular Architecture for CSS -可扩展的模块化 CSS 架构(SMACSS)。我们的结构按下面的类型进行分类能够帮助我们以及我们的团队更好的理解每一个样式的用途。我使用 7 种分类来定义规则集合,大多数是基于 SMACSS 推荐的做法,确保每一个风格都适合这些类别之一。</p>    <ul>     <li> <p>基本样式 (Base Styles)</p> </li>     <li> <p>对象 (Objects)</p> </li>     <li> <p>组件 (Components)</p> </li>     <li> <p>状态 (State)</p> </li>     <li> <p>主题 (Themes)</p> </li>     <li> <p>工具集 (Utilities)</p> </li>     <li> <p>JavaScript 勾子 (JavaScript hooks)</p> </li>    </ul>    <p>理解这些分类和目的,将有助于你写出更高抽象层次的样式。</p>    <h2><strong>基本样式 (Base Styles)</strong></h2>    <p>基本样式规则是创建在元素上。他们是你的网站想设置的全局默认样式。典型的,包括像:排版、 box-sizing 、你可能想统一所有浏览器元素的 正常值 。一个常见的错误,你并不想要太重的基本元素风格,并创建默认值。你真的想移除无序列表的标准强调样式或者只是在某些情况下移除它?</p>    <h2><strong>对象 (Objects)</strong></h2>    <p>对象规则只关注结构和布局。不被允许修饰类的样式。对象类的概念是 <a href="/misc/goto?guid=4959723506744910201" rel="nofollow,noindex">Nicole Sullivan</a> 推广的,为了重用相同结构和布局的页面模式。在你的设计中寻找页面结构的模式,并创建可以在网站的多个组件或部分使用的对象类。通过把这些样式映射为对象类,你就可能避免冗余,减少你的CSS的大小。网格系统,无论是手工编写的或采用的一个框架,都适合使用对象类型。</p>    <h2><strong>组件 (Components)</strong></h2>    <p>组件是分离的、自成一体的 UI 零件。他们是面包和黄油的原子设计,将组成你的大多数样式。一个组件能小到一个按钮,或大到一个切换。创建鲁棒性的组件的关键是使它们独立于页面的任何其他部分,并自成一体。你应该能把一个组件放到页面的任何位置,它都将保持它的结构和设计。</p>    <h2><strong>状态 (State)</strong></h2>    <p>状态累是帮助修改一个组件的状态。定义手风琴的展开或收起,链接的有效或无效,元素的隐藏或显示(visible)。在 JavaScript 中常见的添加、删除状态 class。你只能更新一个状态 class 和允许样式像定义的样子,而不是用 JavaScript 去直接操作样式。</p>    <h2><strong>主题 (Themes)</strong></h2>    <p>主题类只需改变一个组件,使用唯一的颜色、字体或其他装饰。主题类能用来修改整个页面或只是一个的组件。主题不是在每一个项目中都必须的,但当你需要的时候再使用它们。</p>    <pre>  <code class="language-css"><blockquote class="c-pullquote t-light">      <p>A great quote from someone special.</p>  </blockquote></code></pre>    <h2><strong>工具集 (Utilities)</strong></h2>    <p>工具集类是单一目的,帮助我们应用一个特殊样式规则。它们能用来修改间隙、增加字体大小、居中文本、添加一个浮动清除 (clearfix),隐藏等等。工具集能帮助你对布局进行微调,像添加组件之间的间隙或者清除浮动。它们也可以用来对现有组件进行微调,而不需要创建一个新的组件。</p>    <pre>  <code class="language-css">.u-sp {      margin-bottom: 1em !important;  }    .u-clearfix:after {      content: " ";      display: block;      clear: both;      visibility: hidden;      height: 0;      font-size: 0;  }    .u-txt-center {      text-align: center !important;  }    .u-txt-larger {      font-size: 130% !important;  }</code></pre>    <pre>  <code class="language-css"><div class="promo u-sp"></div>  <div class="promo u-sp"></div>  <div class="promo"></div></code></pre>    <h2><strong>JavaScript Hooks</strong></h2>    <p>无论什么时候,解除你的 JavaScript 和样式的耦合。将类名既用于样式又用于 DOM 选择的 JavaScript 勾子,当 CSS 被重构的时候,JavaScript 的依赖就不清晰明了。相反,JavaScript 勾子类就是用来专注处理这类问题的。</p>    <pre>  <code class="language-css"><button class="btn btn--buy js-buy-now"></button></code></pre>    <h2><strong>类的命名</strong></h2>    <p>当你对类进行命名的时候,确保你的名字足够长,能够清晰表达(.pullquote 而不是缩写的 .pq 来表达意思),但是有一些是不需要的(.nav 不用 .navigation)。类命名的可读性能帮助团队成员现在和将来对你表达背后的逻辑的理解有重要的影响。</p>    <p>在编写 CSS 的时候创建具有描述性的、有意义的名称是最棘手的问题,如果能仔细考虑将很有帮助。本文有限不能够对命名的事情讨论得太深入,但是能看一下我们非常棒的文章, 命名 CSS 真的很难 - Ethan Muller ,这篇文章对这个事情讲解得更详细。</p>    <h2><strong>BEM 的命名规范</strong></h2>    <p>BEM (Block Element Modifier)命名 CSS 组件的方式是非常流行、特别有帮助的规范。该规范来自于俄罗斯的搜索引擎-Yandex。这种命名方式非常简单:</p>    <p>[BLOCK]__[ELEMENT]-[MODIFIER]</p>    <p>你可能使用这种冗长的类名称很不习惯,但在你的项目中使用 BEM 将很快去掉这种担心。下面是一个使用 BEM 来命名组件的例子:</p>    <pre>  <code class="language-css"><div class="alert alert--warning">      <h1 class="alert__title">          <span class="alert__icon"></span>          Alert Title      </h1>      <p class="alert__description">The password you entered is invalid.</p>  </div></code></pre>    <p>BEM 命名有三个主要的好处:</p>    <ul>     <li> <p>可读性:大多数元素的类名使用清晰的描述,能使其他人更容易阅读你的 HTML 或者 CSS 文件。</p> </li>     <li> <p>自描述:使用分等级的类命名,能使它非常清晰的描述这个组件属于哪一个基本组件。</p> </li>     <li> <p>特殊性:它可能在你的组件的每一个元素添加一个类的方式有点过了,但是,通过这样做,你能保持你的每个选择器都有特异性,让覆盖权重更加直接。</p> </li>    </ul>    <h2><strong>命名空间</strong></h2>    <p>另外最好的实践就是当命名你的类名的时候,使用命名空间前缀来进行分类。这些前缀会在你的命名前添加一组字符,但是这个值能立刻标记每一个类的目的,在你看 HTML 或者样式的时候是很需要的。我使用下面这些命名空间:</p>    <ul>     <li> <p>对象类: .o-</p> </li>     <li> <p>组件: .c-</p> </li>     <li> <p>状态类: .is- 或者 .has-</p> </li>     <li> <p>主题: .t-</p> </li>     <li> <p>工具类: .u-</p> </li>     <li> <p>JavaScript 勾子: .js-</p> </li>    </ul>    <pre>  <code class="language-css"><footer class="c-footer">      <div class="o-container-wide">          <a class="c-footer__logo" href="/">The Assist</a>          <div class="c-social c-social--follow">              <div class="c-social__label u-txt-center">Join the conversation</div>              <ul class="c-social__list">                  <li class="c-social__item"></li>                  <li class="c-social__item is-active"></li>                  <li class="c-social__item"></li>              </ul>          </div>          <p class="c-footer__credit"></p>      </div>  </footer></code></pre>    <p>关于更多关于命名空间的信息,可以看 Harry Roberts's post on the subject</p>    <h2><strong>代码风格</strong></h2>    <p>像其他代码一样,你的 CSS 项目使用一致的编码风格是很重要的。这包括空格,缩进,命名约定,注释,等你能阅读一些好的规范,比如: Google , Github 或者 Nicolas Gallagher 。使用他们或者创建你自己更适合的规范。</p>    <h2><strong>组织代码</strong></h2>    <p>对于较好的代码组织,您应该使用预处理工具( Sass , Less , Stylus )或者后处理器( PostCSS )去编译你的代码。他们有很多优点,包括一些功能,比如:变量、函数、混淆、导入以及嵌套。这些功能将能让你有更多的方式去组织 CSS 架构,比你只用 CSS 来做更容易。</p>    <p>使用导入,你能将你的样式分解到多个文件中。</p>    <pre>  <code class="language-css">@import "variables";  @import "mixins";  @import "normalize";  @import "typography";  @import "headings";  @import "headings";  @import "layout";  @import "carousel";</code></pre>    <p>任何值需要多次使用的时候能定义变量。给你的变量名添加前缀,能帮助识别他们的目的,也为了使代码完成更有用。</p>    <pre>  <code class="language-css">// Colors  $c-warning: Red;  $c-primary: Blue;  $c-background: White;</code></pre>    <p>一些变量是需要全局定义的,应该存储在单独的变量文件中,但其他变量只被用于单个的组件,这就应该在使用它们的文件中定义。在 SASS 中,变量可以包含在嵌套的局部范围内。</p>    <pre>  <code class="language-css">.alert {      $background-color: Red;      $foreground-color: Cream;      background-color: $background-color;      color: $foreground-color;  }</code></pre>    <p>注:其实这里准备来应该是 SCSS 语法,因为 SASS 语法是不需要花括号的。</p>    <h2><strong>源代码顺序</strong></h2>    <p>由于 CSS 层级样式的性质,你的样式顺序可能是一个问题。如果你不确定样式导入的顺序,你将发现你自己始终在级联问题上是头疼的。</p>    <p>最近,Harry Roberts 发布了一篇 a sensible method for ordering your styles (一种使用的排序方法)他称为 ITCSS (Inverted Triangle CSS),目的在于防止命名冲突、特殊性的问题,不好的风格以及无意的回退(可以看他的 Slide in-depth slides )。这个概念很简单:以影响最小范围和最低特殊性的样式规则作为排序的开始,一直到最靠近选择元素的和最高特殊性的样式结尾。这意味着你的变量定义和基本元素规则将总是在最开始,然而你的工具类和 IE hack 将总是在最后。</p>    <p>Harry 定义了七组,适合我们文件应该排序的分组:</p>    <ul>     <li> <p>设置(Settings):变量和其他设置</p> </li>     <li> <p>工具(Tools):自定义函数和混淆</p> </li>     <li> <p>常用的(Generic):Font-face,box-sizing,normalize 等等</p> </li>     <li> <p>元素(Elements):纯元素默认值,比如标题和链接</p> </li>     <li> <p>对象类(Objects):布局和结构类</p> </li>     <li> <p>组件(Componets):独立组件</p> </li>     <li> <p>(Trumps):工具类和其他规则,这意味着在其他一切都是放到最后的</p> </li>    </ul>    <pre>  <code class="language-css">@import "settings.global";  @import "settings.colors";  @import "tools.functions";  @import "tools.mixins";  @import "generic.box-sizing";  @import "generic.normalize";  @import "elements.headings";  @import "elements.links";  @import "objects.wrappers";  @import "objects.grid";  @import "components.nav";  @import "components.buttons";  @import "components.promos";  @import "trumps.utilities";  @import "trumps.ie8";</code></pre>    <h2><strong>更深的挖掘</strong></h2>    <p>本文只介绍了从深度和广度上大量的主题,但是我希望它能够让你在组织和设计项目中的 CSS 的时候更多的思考。如果你想在以后深入这个主题,这篇文章有大量的资源链接,以及关注更多在这个领域的思想领袖的资源。</p>    <p> </p>    <p> </p>    <p>来自:http://www.zcfy.cc/article/thoughtful-css-architecture-1574.html</p>    <p> </p>