编写CSS容易。 
编写可维护的CSS难。

这句话你之前可能听过100次了。 
原因是CSS中的一切都默认为全局的。如果你是一个C程序员你就知道全局变量不好。如果你是任何一种程序员,你都知道隔离和可组合的模块是构建可维护系统的关键。

为了试图帮助人们构建可维护的CSS,已经有很多CSS指南了:SMACSSOOCSSBEMITCSSACSSCCSS,Atomic DesignMaintanable CSSrscss, 并且可能还有 更多.

那么,CSS的问题是什么?

span {

 font-size: 11px;

}

.header-right {

 font-size: 22px;

 text-align: right;

}

用一个如上的CSS定义,样式立马变成全局的,它会影响所有应用样式的页面。没有封装。没有隔离的模块。

在一个标准的编程语言里,你只会为了要实现的特定功能引入一些模块,例如:

# Python modules

import requests

from Flask import url_for

// Node modules

var express = require(‘express’)

这样,你准确地知道什么会影响你的代码,并且只有你显式引入的内容才会影响到你当前正在实现的功能。

而在CSS中是反过来的。我每写一行CSS代码,可能会影响到项目里的所有部分,并且会无意间改变其他页面的外观。我的样式不仅仅是泄露;它们蜂拥而出,遍布应用程序的每个角落。

对基本的样式设定如印刷格式,只是设定输入字段的样式,或者本来就是全局的样式来说,这是可以理解的,也是合乎情理的。基本上HTML和CSS就是为此而生的。这些工具是为出版物制作的。为了理解这些语言背后的思想,我经常设想在给书排版:你不会想让每一页看起来都不一样——是的,你想要简单一致的样式贯穿整本书,没有太多垃圾。这就是为什么像s之类的标签是合理的,并且样式是全局的,会一直存在。

然而,世界变了,web也变了。我们不再制作网页——我们构建web应用程序。HTML和CSS为之建立的出版物隐喻,不再适用于当今建立在web之上的大部分事物。

这确实需要一种 指定样式的新方式,也许还要一种构建web的新方式。但是就目前来说,我们还无法摆脱CSS和HTML,这意味着我们不得不用一种产出可管理和可维护的应用程序的方式小心地使用这些工具。

Peergrade.io 处理CSS的方式

法则一:(给类名)加上前缀

在Peergrade.io我们在所有类名中用了前缀 .pg 。在CSS代码库里不使用前缀是自找麻烦。原因就是不加前缀的类名最终将会跟引入的样式冲突。假设你需要一个datepicker ——你肯定不愿意从头开发一个(至少我不愿意),因此你引入了一个。现在你的样式里到处都是.prev.next, 和 .separator这样的类名,可能会跟你自己的类名冲突——如果你不加前缀的话。

很长一段时间 Font Awesome没有在他们的类名上加前缀,这意味着你经常跟他们的.icon-* 类名发生冲突(他们现在用了前缀 .fa)。我们也难过地发现 Bootstrap 也没有选择加前缀——但我们依然 ❤ 你, Mark Otto

法则二:避免使用CSS选择器嵌套

在Peergrade.io我们使用 Sass。使用 Sass 你很快进入一种Sass结构跟HTML结构相匹配的模式,例如:

#user-profile-page

 .profile-description

   h3

   ul

     li

       a

这么做之后你会发现,尽管感觉不错,但它非常脆弱。在你写它的时候你可能认为在.profile-description里只会有一个列表,但一两个月后你发现不得不需要另外一个列表,页面结构很快超出你的设想。

并且,像这样的样式定义会应用到父元素内部的任何元素上——而不仅仅是你写在Sass里的那个层级。

对CSS选择器嵌套你所做的是用 微妙 和 脆弱的方式绑定CSS和HTML结构。

法则三:采用BEM命名来开发组件

在构建可隔离组件时,尽可能采用BEM命名方案给类命名。我们没有遵循完整的BEM指南——只是命名方案,这就是说类名应该是这种形式:

.block__element--modifier

为此我们这样组织我们的 Sass:

.pg-deadline

 &__date

   // becomes `.pg-deadline__date`

   color: $color-gray

 &__header

   // becomes `.pg-deadline__header`

   font-weight: 700

   &--highlight

     // becomes `.pg-deadline__header--highlight`

     color: $color-green

这里你看到的是我们用Sass嵌套为我们创建BEM类名。有点反直觉的是,这会产生完全扁平的css结构——没有嵌套——只有顶层的类名定义。

作为法则二的一个例外,我们允许 .block–modifier 形式的类名。

.pg-deadline--editable

 .pg-deadline__header

   background-color: $color-blue

 .pg-deadline__date

   color: $color-black

在这个特殊的例子中,我们允许 1层CSS选择器嵌套。这就允许我们只要指定区块的修饰符——也就是正在编辑的内容—— 不用在区块内的所有子元素上重复修饰符(BEM中的E)。

为了更好地理解类似BEM的命名方式,前往查看Harry Roberts的CSS指南的类BEM命名部分。(需要提到的是,我们发现Harry实际上建立了一套跟我们类似的命名方案。)

展望

似乎还没有人真正找到处理CSS的最佳方式,看着Hack News上精选的这篇文章,我对CSS的现状多少有点失望,本来我们可以做得更好。

结论就是:我们相信已经找到了CSS的可持续基础——当然还有改进的空间。这个计划就是经常对照检查我们的指南,看看事情是不是朝我们预期的方向发展,并且在必要的时候修订。

END

掘金是一个高质量的技术社区,从 ECMAScript 6 到 Vue.js,网站性能优化到开源类库,让你不错过 Web 开发的每一个技术干货。

161010、在大型项目中组织CSS的更多相关文章

  1. 160901、在大型项目中组织CSS

    编写CSS容易. 编写可维护的CSS难. 这句话你之前可能听过100次了. 原因是CSS中的一切都默认为全局的.如果你是一个C程序员你就知道全局变量不好.如果你是任何一种程序员,你都知道隔离和可组合的 ...

  2. SLAM+语音机器人DIY系列:(二)ROS入门——8.理解roslaunch在大型项目中的作用

    摘要 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便.我们的机器人“miiboo”中的大部分程序也采用ROS进行开发,所以本文就重点对ROS ...

  3. 记一次项目中的css样式复用

    本文同步至微信公众号:http://mp.weixin.qq.com/s?__biz=MzAxMzgwNDU3Mg==&mid=401616238&idx=1&sn=3c6e9 ...

  4. Egret的第三方库制作,以及在大型项目中的应用

    目录: 一 创建第三方库 二 TypeScript库 三 JavaScript库 四 第三方库制作在大型RPG中的实际应用 参考: 第三方库的使用方法 目标: 本文目的是将现有游戏的框架制作成第三方库 ...

  5. jfinal想用到中大型项目中的项目经验分享

    jfinal 用在大项目中更加方便实用,节省无数的开发时间,代码量相对 SSH 减少 75% 至 90%,对于项目结构来说,简单提以下几点: 1:先分大模块,大模块内部可以根据划分的model分成子包 ...

  6. 【Atom】在一个中/大型项目中,那些好用而强大的atom功能

      作为一个学生党,一开始使用atom时候并没有意识到atom一些小功能的巨大作用,直到自己实习参与了项目,才知道这些功能在一个项目中是能极大提高工作效率的开发利器   下面是一位不愿意透露其姓名的彭 ...

  7. Selenium的PageFactory在大型项目中的应用

    出路出路,走出去了,总是会有路的:困难苦难,困在家里就是难. 因为最近遇到的技术问题一直没找到可行的解决办法,一直在翻看selenium的源代码,之前写测试代码的时候就是拿来即用,写什么功能啊,就按手 ...

  8. Selenium的PageFactory & PageObject 在大型项目中的应用

    因为最近遇到的技术问题一直没找到可行的解决办法,一直在翻看selenium的源代码,之前写测试代码的时候就是拿来即用,写什么功能啊,就按手动的操作步骤去转换,近日看到一个文章,又去wiki上查了查,觉 ...

  9. 去除web项目中的css、js缓存

    <link rel="stylesheet" type="text/css" href="~/Content/Home.css?param=Ma ...

随机推荐

  1. Javascript return false的作用(转)

    大多数情况下,为事件处理函数返回false,可以防止默认的事件行为.例如,默认情况下点击一个<a>元素,页面会跳转到该元素href属性指定的页.return false 就相当于终止符,r ...

  2. MetInfo标签函数及参数

    参数标签直接在页面中调用标签代码即可: 函数标签需要在页面PHP嵌入代码中通过参数定义转换方可使用,如$metlang=methtml_lang('-'),点击函数标签代码可查看函数标签详细使用方法: ...

  3. iOS使用代码截图

    /** * 截图代码 * * @param view 需要截图的view * @param rect 需要截取的区域 * * @return 返回截取的对象 */ + (UIImage *)viewS ...

  4. IIS URL Rewrite redirect from one Domain to another

    IIS URL Rewrite enables Web administrators to create powerful rules to implement URLs that are easie ...

  5. HTML是什么

    HTML(Hyper Text Mark-up Language )即超文本标记语言,是 WWW 的描述语言,由 Tim Berners-lee提出.设计 HTML 语言的目的是为了能把存放在一台电脑 ...

  6. pip报ssl错误解决

     InsecurePlatformWarning: A true SSLContext object is not available.   # yum -y install openssl-deve ...

  7. scala学习笔记(1)

    下载和安装Scala 前往http://www.scala-lang.org/downloads下载Scala在各个平台的安装包,安装后即可在运行scala编译器和交互式命令行环境(interacti ...

  8. UIBarButtonItem变弹簧

    UIBarButtonItem * spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystem ...

  9. XML工程配置文件的读写

    TinyXML是一个开源的解析XML的解析库,能够用于C++,能够在Windows或Linux中编译,使用TinyXML进行C++ XML解析,使用简单,容易上手.这个解析库的模型通过解析XML文件, ...

  10. zoj The 12th Zhejiang Provincial Collegiate Programming Contest Team Formation

    http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5494 The 12th Zhejiang Provincial ...