现代网页设计和开发过程正在迅速发展,响应式网站正迅速成为主流。像 Bootstrap 和 Foundation 这样的框架向我们展示了创建强大的组件系统的价值,它使在网络上构建事物变得更快、更好、更容易。
大约一年前,我加入了洛杉矶的网络托管和云服务公司 (mt) Media Temple,担任 UX 工程师。负责领导 (mt) 网站重新设计的 前端开发,我利用这个机会放慢脚步,重新审视我的前端开发方法。正是在那时,我意识到我之前构建大型网站的方式有点缺陷。我想分享我的一些学习过程,并阐明我在学习和构建设计系统时所采用的高级方法。

但设计系统到底是什么呢?
在 2013 年伦敦的 FOWA 大会上,Mark Otto 将设计系统描述为“构成产品的所有内容”(请参阅他的完整演讲:构建自己的 Bootstrap)。
所有内容?所有的内容。从排版、布局和网格、颜色、图标、组件和编码规范,到声音和语气、风格指南和文档,设计系统将所有这些内容整合在一起,使您的整个团队能够学习、构建和成长。
起初,我不确定我应该开始构建自定义内容,还是使用现有的框架,比如 Bootstrap。最终,出于以下几个原因,我决定放弃使用后者
- 我们已经拥有了自定义设计。当我加入 Media Temple 时,新网站的视觉设计已经接近完成。如果我使用一个框架,我将不得不对其进行大量的自定义,以使其符合我们的设计。
- 我想根据团队的偏好建立编码规范和结构。同样,我将不得不花大量时间重命名类或重新组织内容以满足我们的需求。
我将花费在剔除框架上的时间似乎并不值得。我觉得构建我们自己的框架从长远来看对我们来说将是有益的,更易于维护,并且作为奖励,它将是一次令人难以置信的学习体验。我也很幸运地拥有足够的时间来完成它,以及一支渴望参与其中的团队。
建立顶级目标
在重建遗留网站时,您将有机会改进很多方面。在我开始任何实际开发之前,我首先设定了一些顶级目标
- 组织:混乱的代码库可能会变成难以处理的噩梦。确保我们拥有经过深思熟虑的结构和方法非常重要。
- 可维护性:随着时间的推移,将会有新的开发人员加入进来修复错误并添加功能。我们需要制定适当的指南和规范,以便人们能够轻松地正确地完成工作。
- 响应式:随着移动/平板电脑流量的稳步增长,使体验与平台无关非常重要。
- 可扩展性:公司未来将会发展,它的网站也应该如此。创建促销页面和/或新产品页面不再是一项令人不快(并且几乎不可能完成)的任务。
我的“顿悟”时刻
带着这些顶级目标,我开始进行广泛的研究。我从阅读 关于 HTML 语义和前端架构 开始,并发现了构建灵活的 模块而不是页面 的好处。那是我“顿悟”的时刻。
以前,在构建大型网站时,我习惯于按页面模板划分工作。我会处理一组相关的模板,然后继续处理另一组。这种方法的问题在于,如果团队之间的沟通不畅,你最终会得到许多类似的——有时是完全相同的——模块和组件,以不同的方式标记和设置样式。如果你没有花费额外的时间进行重构,你的代码库将变成一个 一团糟。
我决定深入研究两个出色但不同的项目:InuitCSS(由 Harry Roberts 创建)和 Bootstrap(由 Mark Otto 和 Jacob Thornton 创建),我很快就意识到我需要采取的下一步是制定关于如何编写我们的 HTML、CSS 和 JavaScript 以及我们的整体前端方法的指南。
编码规范和指南
受 Idiomatic HTML、CSS 指南 和 Idiomatic JavaScript 的启发,我开始将这些指南改编成我们自己的编码指南。在此过程中,我发现并采用了一种有趣的名命方法,称为 BEM(块、元素、修饰符)。这本质上是一种巧妙的方式来命名你的 CSS 类,使其更有意义且更易于理解。
我们略微修改后的约定是
.block {}
– 代表主要组件。.block-elementName {}
– 帮助构成整体组件的子元素。.block--modifier {}
– 用于改变组件状态或外观的修饰符类。
以下是用这种方法创建的警报框示例
/* Main 'alert' component */
.alert {}
/* Sub-components that make up the 'alert' */
.alert-text {}
.alert-close {}
/* Modifiers for various styles of the 'alert' */
.alert--warning {}
.alert--error {}
.alert--success {}
.alert--info {}
我还确定了一组工具来帮助我们完成工作,包括 LESS(用于我们的 CSS 预处理 需求)和 Grunt(用于编译我们的 LESS 文件以及压缩、缩小和合并我们的代码)。
开发基础样式

类似于 InuitCSS 和 Bootstrap,我创建了一个名为 mt-global.less
的主样式表,它将导入所有站点样式并创建最终的 mt-global.css
文件。为了保持组织,我创建了几个文件夹
- core – 这将包含我们的自定义变量和 mixin。
- vendor – 用于使用的供应商实用程序,例如 LESSHat 和 REMixins。
- base – 用于所有底层基础样式,例如排版、颜色和结构。
我从 normalize.css 开始,根据需要对其进行调整,并继续设置标题、链接、列表、表单元素和表格等通用元素的样式。
识别和构建组件
基础样式到位后,是时候全面查看一下网站,并开始识别各个组件了。我开始基于设计中使用的网格构建自定义网格系统。从那里,我继续处理按钮、号召性用语链接、英雄单元和导航等常见元素。
在构建组件时,我开始寻找方法将通用样式抽象成可重复使用的对象,类似于 媒体对象。InuitCSS 在这里提供了很大帮助,因为它包含大量 有用的对象。所有这些样式都被放在名为 components 的文件夹中。
识别和构建模块
大多数组件准备好后,是时候使用这些构建块来创建每个页面的各个模块了。我创建了另一个名为 modules 的文件夹,并开始将它们组合在一起,从站点标题、页脚和英雄单元等全局模块开始。
建立模式

在我构建组件和模块时,我开始使用 样式指南样板 将它们插入样式指南。结果是,对于任何有兴趣了解如何为网站做出贡献的团队成员来说,这是一个单一参考点。一旦整个团队都能够访问样式指南,构建页面模板就变得轻而易举。这只是一个混合和匹配模块,并在必要时扩展或自定义它们的问题。
结论
构建设计系统是一个漫长而充满试错的过程。成熟的框架可以为你节省数周的开发时间,但如果你使用的是已经经历过多次发布的框架构建了你的 web 项目,维护它可能会很困难。你是否会在每次发布时都升级你的代码库?如果你的代码库已经被定制到无法更新的程度,该怎么办?
如果你有机会从头开始重建网站,构建一个自定义解决方案可以解决很多问题:它有助于建立一个定制的系统,让你的整个团队都能快速轻松地学习如何为你的项目做出贡献;它由你构建,专门为你的公司需求而设计;最重要的是,它是为未来而构建的。它不会被绑定到其他项目的演进和方向,可以根据你的公司节奏自由扩展。
研究。构建。学习。重复。
– John Polacek
最重要的是,这是一个令人难以置信的学习经历,也是我们团队的骄傲之源。我鼓励每个人研究关于设计系统和不断变化的网页设计过程的 大量资源。
我在几个项目中成功地使用了 BEM 变体,我觉得它使支持变得容易得多。我 **强烈** 建议使用
__
作为块
、元素
和子元素
之间的分隔符。它允许你使用标准的连字符命名方式来命名块和元素。我发现
foo-bar
和foo-bar__baz
比fooBar
和fooBar-baz
更容易阅读,但你的实际情况可能有所不同。也就是说,它需要一些时间来适应,而且很容易出错。刚接触 BEM 的开发人员经常忘记需要将
块
和块--修改
类都添加到元素中,或者会混淆修饰符,例如使用以下方式:正确的方法是使用
block--modified__element
这篇文章很有启发性。我最近从 Drupal 和修改预先存在的主题中转向,这里包含的信息对我帮助很大。
如果你使用的是这种“标志样式”的方式,当然,你必须在类属性中引用基本块__元素。
但是对于大型项目来说,通过 sass/less 包含或扩展类更容易,而不是让类属性混乱不堪。
这对我很合理,我认为这并不仅仅适用于大型项目。
另外,关于新的 MT 网站外观,我喜欢“子菜单”向上滚动然后固定在顶部的效果,很不错。
我仍然对网页设计比较陌生,但我非常希望能掌握这个概念。你的文章回答了我关于设计系统的一些问题,特别是从哪里开始。你发布了一些很棒的启发性链接。
我承认,设计系统这个想法让人觉得很吓人,但这有助于明确如何开发我自己的工作流程。不过,我有一个问题。你认为一个人的团队会从这种方法中受益吗?例如,构建个人网站/博客。
当然!在最坏的情况下,你会放弃这个想法,会使用像 Foundation 这样的框架,并且学到了很多关于设计系统的知识。无论哪种情况都是胜利。
此外,你每次使用它时都会对其进行完善,并且你的下一个项目会有一个很棒的样板!
我已经使用了很多很棒的框架,但我现在做了自己的样板,只包含必要的代码,我对我的项目的最终结果非常满意。它更容易维护,并且性能比我使用过的任何其他框架都要好得多(字节计数和实时性能)。
好的观点,Elton。感谢你的回复!
我不得不同意 Elton 的说法!:)
这确实是一个令人难以置信的学习经历,因为你是在进行自己的个人项目,所以你有更大的空间犯错、慢慢来、学习。
Ara,一如既往地鼓舞人心。重新设计做得太棒了!我从这篇文章中学到了很多东西,所以感谢 Chris 和 Ara 让它成为现实。干杯!
感谢你的好意,Sealth!
很棒的文章。我们都认为——很多时候——构建自己的“框架”是一个更好的主意。如果你专注于项目的真正需求,这并不难。将其他框架用作参考也是一件好事。
我认为重要的是要有一个编码约定(无论是什么 BEM、OCSS 还是其他任何东西),要井井有条,并且要考虑性能和可维护性。
很高兴看到有人不使用框架就成功了!继续努力!
干得好……不,没做好。我喜欢这种方法论、流程、系统等等,但那个新首页在大屏幕上是 1.8Mb,在小屏幕上是 2.4Mb。他们需要控制一下。
这是一个非常好的主题,你分享了很好的信息。非常感谢你与我们分享这些。
读起来很棒。有很多好的观点。
我最近在工作中也做了类似的事情。
这篇文章对我来说非常及时。最近几天,我一直都在考虑我对使用预先构建的框架进行大型网站设计项目的“立场”。我快要倾向于认为这是一个好主意,因为它们用自己的组件/模块解决了他们认为是模式的问题。问题是,这些问题是在他们自己的设计背景下解决的。他们的设计问题不一定与我大型项目的設計问题相同。但是,我真的很认同你仍然从这些优秀的框架中学习的方法。我也很喜欢这样一个想法,即最终,从头开始构建框架的团队会从看到他们工作的成果和对他们能够继续有效地维护和定制框架的能力充满信心而获得更多回报。
再次感谢,这篇文章非常及时。感谢 Chris 和 Ara!
很棒,**很棒** 的文章。
不过我有一个问题
我真的 **厌恶** BEM 子元素语法(
__
)。我认为它过于粗俗。因此,我对你的修改语法很惊讶,它使用单个“-”表示子元素。
但后来我想到了(这里就是我的问题):如何处理由两个单词组成的元素?驼峰式命名法和双下划线一样难看,所以你有什么建议吗?也许根本不要使用两个单词的元素?
当然,我说的“gare”是指“hate”。意大利自动更正。;)
嗨,Luca,
当我第一次学习 BEM 时,我也不喜欢 BEM 的双下划线语法。但我实际上喜欢驼峰式命名法,所以我们对两个单词的元素使用了这种命名法。
归根结底,这取决于你和你的团队的喜好。另一种方法可能是使用单个下划线来分隔两个单词的元素?
Harry Roberts 有关于 BEM 的一篇很棒的文章:http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/
他在文章中有一节专门讨论了 BEM 的“难看”之处,这真的让我大开眼界,让我能够稍微忽视这个问题。:)
我过去也区分过组件和模块。但这些类别往往很模糊。通常不清楚某个东西应该被认为是模块还是组件。你可以说任何被模块使用的東西都应该是一个组件,但这对我来说并不总是奏效。
另一个问题:您将基本布局样式放在哪里?例如,用于粘性页脚的包装元素,主元素(也可以被视为包含子模块的模块)
非常感谢您提供的有用文章。我一定会尝试将这些资源用于即将到来的任务。我们在工作中也遇到了类似的情况,我们使用了框架的早期版本,该框架在下一个版本中进行了相当大的重构。我们决定暂时保留。
这太不可思议了。在尝试过 OOCSS、BEM 和 SMACSS 后。我已经形成了与你们完全相同的模式,甚至包括你们使用 - 和 - 来构建修饰符和子元素的方式。我非常满意这种方法,它足够简单,不会妨碍你,并且仍然保持所有内容的良好结构。感谢这篇很棒的文章。
我很想在工作中这样做,但我一直得不到对这个想法的支持,尽管它非常需要。我们有多位设计师编码设计,然后将其交由其他人进行完善,因此,实际上非编码人员都在以不同的方式进行编码。我觉得这会节省很多时间和麻烦!
我不得不承认,类名中的双连字符让我有点害怕。除此之外,我完全按照那种方式来组织我的个人代码,一个语义项目及其子项目都以类似的名称命名。我再也不用回头去记一个类名了。;)
阿拉,很棒的文章。我实际上刚刚完成了公司前端的全面重新设计,我们的思维过程非常相似,真是太棒了。从相似的目标,到使用 LESS 预处理器,再到使用 BEM 方法概念化页面元素。不过,我选择使用 BEM 命名规范的略微变体,用双下划线作为修饰符的前缀
一种流行的做法是将外观与结构分离,您尝试过这种方法吗?就我个人而言,我认为将外观和结构样式都保留在同一个选择器中更方便(与需要在多个样式表/位置之间切换来设置同一个元素的样式相比)。相反,对于大多数可重用“外观”相关样式,我选择将它们抽象为 mixin 和变量。
我也尝试在 SASS 中将外观与结构分离。对我来说也不管用,我总是问自己,“这个属性是在结构中还是在外观中?”。这只是一瞬间的事,但最终并不值得。
我发现,在文件开头创建一组变量,管理结构(高度、填充等)和表示(颜色、边框等)更有用。在我看来,这样更简洁、更容易维护。
嗨,阿拉——这是一篇很棒的文章,谢谢!
包括你在内,你的团队规模有多大?
很棒的设计教程文章,谢谢!
非常有趣的文章。我喜欢“创建你自己的 Bootstrap”的标语。我总是从 Bootstrap 等资源中学习,但很少在项目中使用它们,因为我更喜欢将代码尽可能地保持无浪费。
恭喜你迈出了这一步,感谢你对你和你的团队取得的成就的积极总结。在过去的几年里,我一直都在发明这样的系统,要真正保持系统的模块化并防止它成为一个累赘,需要考虑很多因素。
我自己的“顿悟”时刻是一个缓慢的认识,即这是一个高度复杂的系统,需要来自不止我一个人的输入、认可和支持。研究现有的内容,并与其他人讨论你的想法和假设,这对于确保你所构建的东西真正有用,而不是仅仅是一个昂贵的摆设,而且没有重复已有的轮子,这一点非常重要。
很棒的东西。感谢你的启发。毫无疑问,这将归档在:“如果它很容易,每个人都会做。”
一些想法
1) 虽然我很感谢你们开发自己的框架的努力,但如果你把整个努力看作是一个集成的端到端系统,那么在我看来,在系统中所有向量之间保持模块化更有意义。一个具体的例子是人力资源切片和培训。也就是说,找到一个以 Bootstrap 为中心的员工会比找到一个了解你系统的人容易得多(即除了你招聘和培训的人之外,没有人知道)。你的系统可能是一个更好的捕鼠器,但好处是否超过了增加的摩擦?
2) 请注意,我理解存在特殊情况,但因为设计是在孤立/空白中完成的而构建了一个框架,在我看来也感觉有点“不合常理”。或者我喜欢问:说出一种成功的产品公司,它在没有考虑生产的情况下进行产品设计。例如,丰田公司当然不会设计一种产品(即汽车),然后问:“好吧,我们要如何建造它?在市场能够承受的价格范围内?”这是一个集成系统,而不是由一些唾液和胶带连接的一系列孤岛,对吧?
3) 这让我想到:阿拉(或克里斯)是否有机会利用这些概念和理想,写一篇文章/系列文章来讨论如何在代理机构环境中(最佳)应用它们?也就是说,一个团队(阅读:一些核心成员,一些轮换成员)为许多客户/品牌提供服务?必须做些什么,要注意什么,等等?如何构建一个核心工具箱,然后将其扩展和定制以用于各个项目和/或客户?