编写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 开发的每一个技术干货。长按图片二维码识别或者各大应用市场搜索「掘金」,技术干货尽在掌握中。

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

  1. 161010、在大型项目中组织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. oracle dump event

    一.Memory Dumps 1).Global Area ALTER SESSION SET EVENTS 'immediate trace name global_area level n'; 1 ...

  2. 破解Mysql数据库密码

    破解Mysql数据库密码 点我,点我,破解mysql数据库密码:

  3. RedHat6.6更新Centos6yum源

    RedHat6.6更新Centos6yum源 一.    删除自带的RedHat6.6yum源 1-       rpm -qa|grep yum|xargs rpm -e --nodeps(不检查依 ...

  4. 30天,APP创业从0到1【7.26苏州站】

    活动概况 时间:2015年7月26日13:30-16:30 地点:创客巢(苏州吴中区玉山路646号金枫广告产业园B栋4楼) 主办:APICloud.融云.鱼多多 网址:www.apicloud.com ...

  5. 关于OC语法的公开和私有的讨论

    关于OC语法的公开和私有的讨论 OC语法中,类的.h文件向外面暴露类的功能/方法接口,其中定义的属性/方法/协议/类别/类扩展都属于公开的,但实例变量要看限定词(@protected/@public/ ...

  6. navicat premium 导出表结构

    1.右键 点击public,然后选择 数据传输 2.选择数据库对象,目标选择文件,选择文件的路径,然后开始

  7. gradient color

    http://www.cnblogs.com/YouXianMing/p/3793913.html layer 不能自动autolay, 只能在viewDidLayout里面设置宽度 - (void) ...

  8. Java String.split()

    在java.lang包中有String.split()方法,返回是一个数组 我在应用中用到一些,给大家总结一下,仅供大家参考: 1.如果用“.”作为分隔的话,必须是如下写法,String.split( ...

  9. Highcharts选项配置详细说明文档(zz)

    http://www.helloweba.com/view-blog-156.html Highcharts提供大量的选项配置参数,您可以轻松定制符合用户要求的图表,目前官网只提供英文版的开发配置说明 ...

  10. nyist 599 奋斗的小蜗牛

    http://acm.nyist.net/JudgeOnline/problem.php?pid=599 奋斗的小蜗牛 时间限制:1000 ms  |  内存限制:65535 KB 难度:1   描述 ...