编写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. C#中数组、ArrayList和List三者的区别

    在C#中数组,ArrayList,List都能够存储一组对象,那么这三者到底有什么样的区别呢. 数组 数组在C#中最早出现的.在内存中是连续存储的,所以它的索引速度非常快,而且赋值与修改元素也很简单. ...

  2. 公众平台调整SSL安全策略,开发者升级的方法

    公众平台调整SSL安全策略,请开发者注意升级 近一段时间HTTPS加密协议SSL曝出高危漏洞,可能导致网络中传输的数据被黑客监听,对用户信息.网络账号密码等安全构成威胁.为保证用户信息以及通信安全,微 ...

  3. Step by Step

    数据库设计Step by Step篇目整理及下载地址 系列篇目 1. 数据库设计 Step by Step (1)——扬帆启航 2. 数据库设计 Step by Step (2)——数据库生命周期 3 ...

  4. 一个前端html模板处理引擎(javascript) - pure

    做后台开发(java/python)的同学开发web应用,对于前端页面生成技术并不陌生,像jsp,freemark等.开发UGC类型的互联网站,因为要SEO友好,所以一般都会在后台用模板引擎直接生成好 ...

  5. 【转】解决:fatal error C1083: 无法打开预编译头文件

    http://blog.csdn.net/aafengyuan/article/details/7988584 是这样的,我创建了一个空项目,并通过"项目属性>C/C++>预编译 ...

  6. 一个小玩意 PHP实现微信红包金额拆分试玩

    <meta charset="utf-8"> <?php // 新年红包金额拆分试玩 class CBonus { public $bonus;//红包 publ ...

  7. [Call Vibrator] How to Enable Outgoing Call Vibration without ROOT

    Call Vibrator requires the radio log of phone to detect when outgoing call is answered. But since An ...

  8. Java命令参数说明大全

    Java 在运行已编译完成的类时,是通过 java 虚拟机来装载和执行的,java 虚拟机通过操作系统命令 JAVA_HOME\bin\java –option 来启动,-option 为虚拟机参数, ...

  9. GTA项目 三, 使用 bootstrap table展示界面,使得data和UI分离

    /** bootstrap-table - v1.5.0 - 2014-12-12* https://github.com/wenzhixin/bootstrap-table* Copyright ( ...

  10. Leetcode: Number of Islands II && Summary of Union Find

    A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand oper ...