如何精简TrelloCSS架构

我们一直在潜移默化地改进Trello的CSS,现在来看,已经足够能用了,不过还可以做到更好。以下是我们在实践中碰到的CSS的关注点,大致分为以下几个部分:

  1. 工具
  2. 文件架构
  3. 模块
  4. JS呢?
  5. 样式
  6. 一些数字
  7. 其他糟粕
  8. 未来

小贴士:这篇文章建立在你已有网站并对CSS有一定认知的基础上。如果没有基础也没关系,稍微了解一下也是蛮有意思的。

1、工具

我们trello.com用的是LESS。它与vanilla CSS关系紧密,操作简便,所以我很信赖它。我不喜欢复杂的东西,也没那么多复杂的要求,面对CSS中那么多循环、guard、以及数学计算实在是无从下手(当然,我相信它们肯定很强大)。一般来说,我们用的最多的就是importdata-uri、变量、shallow嵌套、以及一些混写(主要用于浏览器兼容)。

我们没有选择Grunt或者Gulp,并不是因为有人觉得它们不够好,而是LESS已经足够好用了。

最新版本中,我们通过LESS把所有CSS文件导入到了一个单独的core.css文件中,然后用 CSSshrink 压缩,上传到了我们的CDN中。在这篇博客中,谈到了我们的整体设计、开发以及相关进展。虽然里面只是随便聊了一下,以后的文章里我还是会仔细讲讲。

2、文件架构

文件是怎样组合、架构的?让你看看我们的核心CSS是如何import的。这中间还有不少瑕疵和不稳定的缺陷,但真实的样子更有说服力。几个月前,我一直尽力把它们分解成多个部分,但总觉得不合适,之后就再没有这么做了。

我们尽可能把文件保持为一个个小的模块,以便以后有可能会对它们进行批量的删改,像我们处理meta页一样,方便快捷。meta页的CSS文件及其他包相互分离,但尽量保持小巧且自治。

3、模块

在给CSS命名的时候,我们没有用父子继承选择器的方式,如 .header img { … },我们换了个方式,用连字符分割继承关系给选择器命名,如.header-image { … }

我们选择的例子是这样的,这是一般的命名方式:

同样的语句,我们则是用这样的方式:

用我们的方式,降低了选择器的独有性,反而更有效率。为什么? 这跟浏览器解析顺序有关:浏览器阅读解析选择器的顺序是从右至左的,也就是说,最右边的选择器(也是最关键的选择器)最先被解析。你以为 .foo div 这样的写法很守规矩,因为只有几个.foo,但实际上浏览器必须要首先遍历成千上万个 div ,再筛选出父级为 .foos 的。你可以在 提升CSS渲染性能小技巧 中了解更多相关内容。

花了一周的时间让Trello处于飞速运转的状态,那时候我也在不同的代码中使用了这种命名方式。更换后,性能上确实有很大的不同,特别是在加载有大量卡片(意味着会有很多的DOM元素)的页面时,这种优势更明显。对于小站点而言,可能不会带来多大的差别,但也值得你们试试看。

还有,我觉得这种命名方式,让CSS更稳定、可读。选择器关联性一旦变得明显,那么对它们进行查找或删改也就变得易如反掌了。

4.、那JavaScript呢?

我敢打赌,你的站点肯定用到了JS。我们当然也是,但我们把样式和行为分离开,用 js- 前缀来为行为类命名,例如:

怎么回事? .js- 前缀类可以让其他人在使用JS事件时修改模板用,“嗨,你得经过我的同意才能打开菜单哦~”,这个class说,“模板兄,别担心~我不会搞乱你的菜单的”。

请确保你使用的类不会跟其他类冲突, .js-open-content-menu 的功用可比 .js-menu 清楚多了(后者看上去就是命名者在偷懒)。记住,样式表里千万不要用样式来命名类,比如 .header-nav-button ,JS里或者行为类中,像 .js-open-header-menu 这样。 老司机告诉你:有时候我们需要使用样式来关联JS中的状态,这个问题我之后能帮你解决,但如果我看到有人把 .js- 前缀样式放进了样式表?千万别,即使你 跨越半个世界我都会找到你。

5、样式

编写CSS的方式有成千上万种,但即使是有效的语句,也有可能是糟糕的表达方式。如果你愿意花一点点时间,来改善格式中的瑕疵,工作起来将会轻松许多。看看这个例子:

有些原则性的要求我希望我们团队一直有遵守:

  • 参数之间换单行,声明之间换双行;
  • 参数在声明时需要空一格,如 参数: 值; 而不是 参数:值;
  • 内嵌的规则需要缩进,一方面可以方便查看关联性,另一方面可以快速识别和跳过无关段落;
  • 参数请以字母顺序排列。我尝试过用语义的方式排序,如 定位-尺寸-排字-色彩 等,但还是觉得字母顺序最好用;
  • 空格用双格,别用4个空格也不用tab;
  • 给class命名时,请用连字符,别用下划线或驼峰法;
  • 可以用0的时候就别用0px,数值尽可能简单,例如:可以写成 padding: 15px 0; 就别写成 padding: 15px 0px 15px 0px;
  • 当你需要使用浏览器前缀解决兼容问题时,请把标准设置声明放在所有浏览器声明之后,比如: -webkit-transition: all 100ms; transition: all 100ms; 。把标准设置放在最末端,意味着新版浏览器可以在标准基础上优化,而旧版浏览器也能找到自己合适的设置,大家都能以最好的效果显示渲染;
  • 用HSL(a)取代十六进制/RGB(a)色彩模式来标识颜色。如果需要对颜色进行调整,用的是十六进制或者RGB(a)模式的话,那么一点点颜色的区别,整个值可能会完全不同,我都猜不到调整的色彩值大概是怎样的。而用HSL就很方便,浓一点淡一点都很容易调节,我还可以大致形容这个色彩的感觉——“嗯,这是蓝色,这是它的饱和度和明度”,而不是“嗯,这种颜色有点偏红,也有点偏绿,还有点偏蓝”;
  • 注释是个好东西。如果你的问题在网上有答案,完全可以在注释里添加个链接进去,方便其他人了解具体情况;

当然,这都是偏好设置,你不用全部采纳,但无论如何,你的团队应该有一套自己的开发原则,并且请严格遵守它。

6、一些数字

  • 文件大小: core.css 原文件大小为202kb,压缩后为43.3kb。即使压缩了看上去还是很大,但是这个文件不止是单个页面使用,所以还可以接受。值得注意的是,我们仍然推荐使用icon font,嵌入CSS中。
  • LESS行数:14,236。 这可是所有LESS代码的行数总和,我是通过执行 find static/css/ -name '*.css' | xargs wc -l 看到的,即使行数已经有有这么多了,我们还是鼓励需要的时候就换行;
  • CSS文件数:44。 在core.css的最后,我们把这些CSS文件import进去了,以模块的方式展示。有些文件可能会比较大(其实我们应该把大的那些拆分成小的文件) ,最大的是 board.css 有1105行LESS代码,确实过长了。
  • 选择器数:2,426。 GitHub 有大约7000个选择器, Bootstrap有1900个,Twitter有8900个,纽约时报有2100个,SoundCloud则有1100个……. 这些数据都可以通过 cssstats.com 查询到。

7、其他糟粕

  • 我们首先避免body类的使用。该类会产生过多的子选择器,导致浏览器性能低下,并且很容易被黑客利用,我们在逐渐地让其消失;
  • 对于小图片(比如小于10kb的),我们尽量不让它占据请求通道,而是用LESS的data-uri解析,把它嵌入到CSS中。这样做以前,我们通常是用CDN内图片的url地址或者字体资源的方式来调用;
  • 我们没有主动支持IE9,这样就可以有更多的组件可以选择(比如flexbox);
  • 总有一天,我们会走向用行内SVG替代字体和图标的道路的,不过只要我们不支持IE9,转换起来就没什么大问题,只是会比较麻烦而已;
  • 我们没有用 normalize.css ,也没有用任何框架或外部支持部件。Our meta pages use normalize.css and most of HTML5 Boilerplate as a starting point.
  • 我们没有使用CSS检查器检查过代码,LESS编译器总是很快就出错,一点点偏差就会大声提醒。其中的原因,大概是因为,我经常犯 “displaY” 这样的小错误吧。
  • Autoprefixer (自动前缀器)听上去很厉害的感觉,我们暂时没有使用,以后可能会试试看。

8、未来……

我们的命名规则有个负面的影响——以很长的选择器名结尾,难以从语义上分析。修改器以及那些状态类(比如 .global-header-dark 这种)很容易跟伪子类搞混(像 .global-header-logo 这种)。有种比较广泛的规则叫BEM,即“Block, Element, Modifier”(区块、元素、修改器),就是强调了这点。详情请查看 CSS代码杂志 ,这篇解释得很清楚了。

@fat at Medium 也出现过同样的问题。他总结了一些类似BEM的命名法则,比BEM更可行一点。划了一些重点在这里:

  • .js- 前缀类名用于依赖于JS选择器的元素;
  • .u- 前缀类名用于单一功用的元素,如 .u-underline.u-capitalize 等。
  • 使用连字符和驼峰法命名时请规定一定的意义——比如分割元件、子级元件、修改器等;
  • .is- 前缀类用于状态类的元素(一般都是由JS控制),如 .is-disabled
  • 变量名请遵守: [属性]-[值]–[元件]
  • 混写元素只能以 .m- 为前缀;

整个Medium的使用指南都列在这里了,全是干货。我们已经习惯跟js-类和仅填充用的混写打交道了,以后也会尝试使用 .is-.u-.m- 、以及 –modifier ,看上去也很容易理解。谢啦,@fat!

最近,我对Glen Maddern总结的CSS属性模块 也深觉启发,很想知道那些选择器的性能效果会是如何,我会持续关注的。

现阶段的CSS就是这样了。如果你看了我们详细的CSS文件(其实我不建议),你就知道我们并没有完全遵守那些条条框框。那些规矩总是会变的,并且也有不少瑕疵,随着时间的不断发展,我们总能找到不合理的地方、再加以改进。

打赏支持我整理更多优质资源,谢谢!

打赏编辑

打赏支持我整理更多优质资源,谢谢!

任选一种支付方式

2 1 收藏

资源整理者简介:凝枫

非典型性程序员,爱做一些和写程序毫不相干的事 个人主页 · 贡献了46个资源 · 1


直接登录

推荐关注

按分类快速查找

关于资源导航
  • 伯乐在线资源导航收录优秀的工具资源。内容覆盖开发、设计、产品和管理等IT互联网行业相关的领域。目前已经收录 1439 项工具资源。
    推送伯乐头条热点内容微信号:jobbole 分享干货的技术类微信号:iProgrammer