你有没有在一个逐渐膨胀的 CSS 项目中感到混乱呢?保持样式风格统一和 HTML 的影响是比较困难的:尽管修改一个较小的问题,均可能建立更多丑陋的 hack,也可能 CSS 的小改变会影响 JavaScript 的功能。可是这些问题能在咱们的项目开始的时候静心规划,就能很大程度上避免这些问题。让咱们开始说 CSS 架构吧。css
一个好的 CSS 架构是具备良好的可扩展性。可扩展性是在任何项目开发中都是具备挑战性的,范围的扩大或者团队人数的增长,这些挑战在 CSS 中也不例外。层级和全局的特性使 CSS 很强大,反之在开发过程当中也是脆弱的。若是你写了一段时间 CSS,你会发现当改变一行 CSS 来修复一个功能的时候会破坏一批其余的 CSS 功能,这将让你很头痛。细心的规划能提供下列的好处:html
更少的样式git
更少的样式冲突github
更长的维护周期web
更快的提高新团队成员vim
团队成员之间更容易交流浏览器
更平稳的项目交接sass
Jonathan Snook 对 CSS 规则进行分类的概念在他的书中很受欢迎 Scalable and Modular Architecture for CSS-可扩展的模块化 CSS 架构(SMACSS)。咱们的结构按下面的类型进行分类可以帮助咱们以及咱们的团队更好的理解每个样式的用途。我使用 7 种分类来定义规则集合,大多数是基于 SMACSS 推荐的作法,确保每个风格都适合这些类别之一。架构
基本样式 (Base Styles)app
对象 (Objects)
组件 (Components)
状态 (State)
主题 (Themes)
工具集 (Utilities)
JavaScript 勾子 (JavaScript hooks)
理解这些分类和目的,将有助于你写出更高抽象层次的样式。
基本样式规则是建立在元素上。他们是你的网站想设置的全局默认样式。典型的,包括像:排版、box-sizing、你可能想统一全部浏览器元素的正常值。一个常见的错误,你并不想要过重的基本元素风格,并建立默认值。你真的想移除无序列表的标准强调样式或者只是在某些状况下移除它?
对象规则只关注结构和布局。不被容许修饰类的样式。对象类的概念是 Nicole Sullivan 推广的,为了重用相同结构和布局的页面模式。在你的设计中寻找页面结构的模式,并建立能够在网站的多个组件或部分使用的对象类。经过把这些样式映射为对象类,你就可能避免冗余,减小你的CSS的大小。网格系统,不管是手工编写的或采用的一个框架,都适合使用对象类型。
组件是分离的、自成一体的 UI 零件。他们是面包和黄油的原子设计,将组成你的大多数样式。一个组件能小到一个按钮,或大到一个切换。建立鲁棒性的组件的关键是使它们独立于页面的任何其余部分,并自成一体。你应该能把一个组件放到页面的任何位置,它都将保持它的结构和设计。
状态累是帮助修改一个组件的状态。定义手风琴的展开或收起,连接的有效或无效,元素的隐藏或显示(visible)。在 JavaScript 中常见的添加、删除状态 class。你只能更新一个状态 class 和容许样式像定义的样子,而不是用 JavaScript 去直接操做样式。
主题类只需改变一个组件,使用惟一的颜色、字体或其余装饰。主题类能用来修改整个页面或只是一个的组件。主题不是在每个项目中都必须的,但当你须要的时候再使用它们。
<blockquote class="c-pullquote t-light"> <p>A great quote from someone special.</p> </blockquote>
工具集类是单一目的,帮助咱们应用一个特殊样式规则。它们能用来修改间隙、增长字体大小、居中文本、添加一个浮动清除 (clearfix),隐藏等等。工具集能帮助你对布局进行微调,像添加组件之间的间隙或者清除浮动。它们也能够用来对现有组件进行微调,而不须要建立一个新的组件。
.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; }
<div class="promo u-sp"></div> <div class="promo u-sp"></div> <div class="promo"></div>
不管何时,解除你的 JavaScript 和样式的耦合。将类名既用于样式又用于 DOM 选择的 JavaScript 勾子,当 CSS 被重构的时候,JavaScript 的依赖就不清晰明了。相反,JavaScript 勾子类就是用来专一处理这类问题的。
<button class="btn btn--buy js-buy-now"></button>
当你对类进行命名的时候,确保你的名字足够长,可以清晰表达(.pullquote 而不是缩写的 .pq 来表达意思),可是有一些是不须要的(.nav 不用 .navigation)。类命名的可读性能帮助团队成员如今和未来对你表达背后的逻辑的理解有重要的影响。
在编写 CSS 的时候建立具备描述性的、有意义的名称是最棘手的问题,若是能仔细考虑将颇有帮助。本文有限不可以对命名的事情讨论得太深刻,可是能看一下咱们很是棒的文章,命名 CSS 真的很难-Ethan Muller,这篇文章对这个事情讲解得更详细。
BEM(Block Element Modifier)命名 CSS 组件的方式是很是流行、特别有帮助的规范。该规范来自于俄罗斯的搜索引擎-Yandex。这种命名方式很是简单:
[BLOCK]__[ELEMENT]-[MODIFIER]
你可能使用这种冗长的类名称很不习惯,但在你的项目中使用 BEM 将很快去掉这种担忧。下面是一个使用 BEM 来命名组件的例子:
<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>
BEM 命名有三个主要的好处:
可读性:大多数元素的类名使用清晰的描述,能使其余人更容易阅读你的 HTML 或者 CSS 文件。
自描述:使用分等级的类命名,能使它很是清晰的描述这个组件属于哪个基本组件。
特殊性:它可能在你的组件的每个元素添加一个类的方式有点过了,可是,经过这样作,你能保持你的每一个选择器都有特异性,让覆盖权重更加直接。
另外最好的实践就是当命名你的类名的时候,使用命名空间前缀来进行分类。这些前缀会在你的命名前添加一组字符,可是这个值能马上标记每个类的目的,在你看 HTML 或者样式的时候是很须要的。我使用下面这些命名空间:
对象类:.o-
组件:.c-
状态类:.is-
或者 .has-
主题:.t-
工具类:.u-
JavaScript 勾子:.js-
<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>
关于更多关于命名空间的信息,能够看 Harry Roberts's post on the subject
像其余代码同样,你的 CSS 项目使用一致的编码风格是很重要的。这包括空格,缩进,命名约定,注释,等你能阅读一些好的规范,好比:Google,Github 或者 Nicolas Gallagher。使用他们或者建立你本身更适合的规范。
对于较好的代码组织,您应该使用预处理工具(Sass,Less,Stylus)或者后处理器(PostCSS)去编译你的代码。他们有不少优势,包括一些功能,好比:变量、函数、混淆、导入以及嵌套。这些功能将能让你有更多的方式去组织 CSS 架构,比你只用 CSS 来作更容易。
使用导入,你能将你的样式分解到多个文件中。
@import "variables"; @import "mixins"; @import "normalize"; @import "typography"; @import "headings"; @import "headings"; @import "layout"; @import "carousel";
任何值须要屡次使用的时候能定义变量。给你的变量名添加前缀,能帮助识别他们的目的,也为了使代码完成更有用。
// Colors $c-warning: Red; $c-primary: Blue; $c-background: White;
一些变量是须要全局定义的,应该存储在单独的变量文件中,但其余变量只被用于单个的组件,这就应该在使用它们的文件中定义。在 SASS 中,变量能够包含在嵌套的局部范围内。
.alert { $background-color: Red; $foreground-color: Cream; background-color: $background-color; color: $foreground-color; }
注:其实这里准备来应该是 SCSS 语法,由于 SASS 语法是不须要花括号的。
因为 CSS 层级样式的性质,你的样式顺序多是一个问题。若是你不肯定样式导入的顺序,你将发现你本身始终在级联问题上是头疼的。
最近,Harry Roberts 发布了一篇 a sensible method for ordering your styles (一种使用的排序方法)他称为 ITCSS (Inverted Triangle CSS),目的在于防止命名冲突、特殊性的问题,很差的风格以及无心的回退(能够看他的 Slide in-depth slides)。这个概念很简单:以影响最小范围和最低特殊性的样式规则做为排序的开始,一直到最靠近选择元素的和最高特殊性的样式结尾。这意味着你的变量定义和基本元素规则将老是在最开始,然而你的工具类和 IE hack 将老是在最后。
Harry 定义了七组,适合咱们文件应该排序的分组:
设置(Settings):变量和其余设置
工具(Tools):自定义函数和混淆
经常使用的(Generic):Font-face,box-sizing,normalize 等等
元素(Elements):纯元素默认值,好比标题和连接
对象类(Objects):布局和结构类
组件(Componets):独立组件
(Trumps):工具类和其余规则,这意味着在其余一切都是放到最后的
@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";
本文只介绍了从深度和广度上大量的主题,可是我但愿它可以让你在组织和设计项目中的 CSS 的时候更多的思考。若是你想在之后深刻这个主题,这篇文章有大量的资源连接,以及关注更多在这个领域的思想领袖的资源。
Harry Roberts - 目前该领域最丰富的思想领袖之一。可以关注他的 Twitter,订阅他的博客,阅读他的 CSS Guidelines 文档。
Jonathan Snook - 他的 CSS 架构想法很受欢迎,以及他的纸质和电子书,Scalable and Modular Architecture for CSS
Nicole Sullivan - 介绍过 OOCSS(Object Oriented CSS) 的概念,可以翻阅文档 Github wiki
这篇文章主要是基于最近在相同主题的分享。能检出 slides for the presentation 或者观看下面的视频。
视频容易挂,这里我直接贴连接,你们能够直接点看在浏览器播放就好了。
https://player.vimeo.com/video/172444121?byline=0&portrait=0
原文出自:https://seesparkbox.com/foundry/thoughtful_css_architecture
博客原文地址:http://60sky.com/post/thoughtful-css-architecture.html