转载

知名前端站点 CodePen 的 CSS 技术细节

Mark Otto和lan Feather分别分享了GitHub和Lonely Planet这两个网站中如何应用CSS,我觉得我也应该参与到这个有趣的活动之中,谈谈我们在CodePen中是怎么应用CSS的。

概览

  • 预处理器使用了 SCSS
  • 我们使用 Autoprefixer
  • 我们使用 Rails Asset Pipeline
  • 实际加载的那些可解释为 CSSSCSS 文件其实就是一个包含各模块的目录
  • 我们有一个统一样式,主要原因是这样看起来一致性更好
  • 我们不使用任何特别的“ CSS 架构”,只使用类
  • 每一个网页中不超过2-3个CSS文件
  • 媒体查询我们使用可以关掉的 @mixin
  • 我们鼓励注释
  • 一些统计数据
  • 在本文中“我们”这个词大多数只代表我一个
  • 未来展望和期待

预处理器

人们对于预处理器褒贬不一,但是我觉得如果做一个比较大的网站项目,没有预处理器是非常困难的。若你认为我这是在过度依赖工具,会让我效率变低,那么请允许我嘲笑你。 我更喜欢 SCSS 是因为我喜欢它的社区,同时我也认为它 更好 。但实话说,所有这些主流的预处理器( SassLESSStylus )都基本可以满足我的需求。这里是一些我觉得有用的特性(按照实用性递减排序):

  1. @import
  2. @mixin
  3. Nesting(嵌套)
  4. Variables(变量)
  5. @extend
  6. Math(数学运算)
  7. Loops(循环)
  8. 长时间用它们工作,帮助我理解那些炫酷的小例子

不用预处理器我无法想象要花多大的精力才能取代这些特性。

在CSS属性中加与浏览器相关的前缀

因为有 Autoprefixer 这个工具,我在工作中几乎不需要记 CSS 中属性或者值。我特别喜欢它对 flexbox (伸缩布局盒) 回退的处理方式。 我以前用 Compass 比较多,但我发现95%的情况下都是用它处理 CSS3@mixin 。我更喜欢“所见即所得”这种方式,而不是只为标前缀而到处放 @include 。不用Compass 之后我比较怀念的一个功能是生成SVG渐变,但对于仅在IE9才需要的功能来说它也显得过于重型了,所以总体上我也没什么大损失。

Rails

我是 Rails Asset Pipeline 的粉丝,它实在太好用了。 举个例子: 我把句话放在视图中:

<%= stylesheet_link_tag "about/about" %>

然后它会产生一个我需要的 CSS 文件:

<link href="http://assets.codepen.io/assets/about/about-a05e4bd3a5ca76c3fb17f2353fedbd99.css" media="screen" rel="stylesheet" type="text/css" />

我们在资源里把终止时间写得离现在远一点。

知名前端站点 CodePen 的 CSS 技术细节

我们每一次部署的时候,它都会通过重新生成随机数来重新缓存,所以这是一个非常棒的缓存机制。 我们在 CodePen 中只是对 JavaScript 使用 Sprockets 。有了它我们可以这么干:

//= require common/whatever.js //= require_tree ./../hearting/

你也可以在 CSS 这么做,但何必自寻烦恼呢,因为: 1. Sass 能够实现这个功能 2. 如果你用 Sass 实现这个功能,那依赖性表现更好。像 $variables@mixin 都能够在文件之间应用了。 我们并不会把 CSS 文件上传到 Git 仓库中,这样对 Git 很好,所有的资源都在部署的时候进行解释编译。

文件组织结构

被加载的 CSS 文件会有一份对应的SCSS,这个SCSS文件中没有任何实际的CSS代码,而是用来描述CSS文件中的内容。举个例子,这是我们现在的 global.scss

// General Dependencies @import "global/colors"; @import "global/bits";  // Base @import "global/reset"; @import "global/layout";  // Areas @import "global/header"; @import "global/footer";  // Patterns @import "global/typography"; @import "global/forms"; @import "global/toolbox"; @import "global/buttons"; @import "global/modals"; @import "global/messages"; @import "global/badges";  // 第三方组件 // (目前没有)

我试着坚持这样做,但每当我向一个本应被全部导入的文件中添加代码时,老是会抛出一堆异常。我应该弄个通告文件然后写上:

@import "shame"; // 注意有点条理啊,里面这几个魂淡。

代码的组织结构

我写代码时一定会遵循的规范:【译者注:作者在原文中说是一种强迫症,表示这些规范是他一定会遵循的】

  • 属性和嵌套有2个空格的缩进
  • 在选择器(selectors)之后或”{“前面加一个空格
  • 一行一个属性声明
  • 在”:”(冒号)后面加一个空格
  • 尾部的”}”符号另起一行,并与选择器同等缩进
  •  作为长度的时候不加单位
  • 名称中使用连字符”-”而不用下划线”_”

我写代码时大多会遵循的规范:

两个联系密切的类中间不加空行:

.thing {  } .related-thing {  }

有一点联系的两个类之间加一个空行:

.thing {  }  .another-thing {  }

没什么联系的内容留两空行:

.thing {  }  .totally-different-thing {  }

我不太关心的规范:

  • 属性的顺序。相关的属性(如 height/width)一般会放一起,但不会特别在意这个。
  • 注释方式。两种都可以用

在实际的工作中,我甚至也不会严格按照 自己的规范 写。

模式

我写的代码几乎会给所有的元素一个类,我不知道这是不是遵循了 SMACSSOOCSSBEM等等 ,不是很在意这些。 这并不意味着我从不写嵌套(比如创建组合选择器),或者说我对嵌套的层数要求苛刻,只是我一般不会写太深的嵌套。 我一般会这样写:

.box {    h2 {     &:after {     }   } }

但是我会想:要不要给 h2 一个类呢?应不应该给这种头类型创造一个可以重用的样式呢?然后我会停止这么想了,因为我意识到如果这个样式出现得足够频繁,那么我能在之后很容易更改掉,换成可重用的方式。

总体的原则就是降低特异性。无论你代码重用做得多好,还是经常会有需要重写的情况,所以特异性越少,重用就会变得更容易。不仅如此,以这种方式重写,你甚至能够在不用 id 选择器或者 !important 的时候进行重写。

一般来说, Rem 是我选择字体大小时候的单位, px 是其他元素的大小单位。

请求文件

我尽力在每个页面上请求2个或3个 CSS 文件:

  • global.css
  • page.css (如果不是编辑器的页面)
  • section.css (如果需要)

思想是尽量让请求数少一些,但是又不是极端地把所有东西塞到一个文件里。我感觉在 CodePen 上,有太多页面特定的样式,如果把这些都放到一个文件里,那么 global.css 这个文件就会变得非常大。我从来没有这么尝试过,也许有一天尝试一下也会很有趣。我会为它新建个分支叫: squiCSSh_it_real_good(高压版CSS)

媒体查询( Media Queries

我使用 @mixin做 媒体查询。有时我会想“这个宽度或更大”,有时会想“这个宽度或更小”(就是媒体查询的逻辑呀!)。这样写出来有点啰嗦:

@mixin breakpoint($point) {   @if ($MQs == true) {     @if $point == baby-bear {       @media (max-width: 500px) { @content; }     }     @if $point == mama-bear {       @media (max-width: 700px) { @content; }     }     @if $point == papa-bear {       @media (max-width: 800px) { @content; }     }     @if $point == super-bear {       @media (max-width: 1280px) { @content; }     }      @if $point == reverso-baby-bear {       @media (min-width: 501px) { @content; }     }     @if $point == reverso-mama-bear {       @media (min-width: 701px) { @content; }     }     @if $point == reverso-papa-bear {       @media (min-width: 801px) { @content; }     }     @if $point == reverso-super-bear {       @media (min-width: 1281px) { @content; }     }      @if $point == exclusive-baby-bear {       @media (max-width: 500px) { @content; }     }     @if $point == exclusive-mama-bear {       @media (min-width: 501px) and (max-width: 800px) { @content; }     }     @if $point == exclusive-papa-bear {       @media (min-width: 801px) and (max-width: 1280px) { @content; }     }      @if $point == iOS {       @media (min-device-width: 768px) and (max-device-width: 1024px), (max-device-width: 480px) {          @content;        }     }   } }

我只是喜欢它的命名规范,平时一般都不会用上,只是想让自己在需要的的时候知道怎么做。

注意在上面代码第二行处 @if ($MQs == true) { ,我在所有包含内容列表的 SCSS 文件中设置了开关变量。这是因为在有的页面是自适应的,有的不是,但它们经常会用到同一个组件。如果这个页面设计初衷不是自适应的(一些只是为了在电脑桌面环境中应用的页面,比如说我们设计的一个拖放工具,还不能在触摸设备上使用),或者这个页面在移动设备使用环境下会重定向到专门的版本上。在这些页面的 CSS 文件中不需要含有媒体查询( Media Queries ),它们也用不上。

注释

我的注释风格十分自由。在大多数情况下我从来不会修改它,如果在之后我读这些注释发现我不懂它什么意思了,或者它和代码描述得驴头不对马嘴了,我就会删掉它。

.drag-from-pen-grid {   padding-bottom: 52px; /* adding this to make room for pagination. A little magic-numbery... */ }

统计数据

  • CodePen 一共大概有160个独立的 SCSS 文件, find /stylesheets ! -name "*.scss" | wc -l 但是从来不会出现我找不到我要找的文件这种情况。原因如下:
  1. Sublime 编辑器中寻找一个项目里的文件很容易
  2. 它们有良好的组织和命名,我只需要用 command –t 便可以直接跳到我要找的文件
  • SCSS 文件里一共有13,345行代码。 find stylesheets/ -name '*.scss' | xargs wc –l
  • global.css 大小:11.8k
  • page.css (除了编辑器,几乎所有页面都有用到)大小:5.5k
  • editor.css 大小:6.2k

CSS 文件并不是我们决定性能的关键因素。我们的字体大小是它的4倍, JavaScript 文件大小是它的10倍。

关于我

我们三个人对大部分的网站建设工作都共同参与,但是有些部分的工作是我们三个各自承担的,我就是单独负责 CSS 这一块。 我不得不提的是,虽然我自认为我的工作模式是一个很棒的模式,但是也有可能它只适合我用,在别人看来好像有点奇怪。 我有一个需要改正的地方是把要做的事情( TODO’s )写在问题追踪里而不是写在代码里。我并没有工具能够提醒我在代码中写下的要做的事情( TODO’s ),所以这些事情经常被我忘了。 我希望未来我们能够有更多的队友,然后我会寻找一个能够让大家都适应的工作模式。

未来展望

  • 我并没有使用自动检查代码错误的工具,但是在未来我可能会用到。我们在 JavaScript 中使用自动检查代码错误的工具了,而且发现它确实很有好处。
  • 我现在还没有使用 sourcemaps 【译者注:详见http://www.w3cplus.com/preprocessor/sass-3.3-source-maps.html】,主要因为我认为它现在还不支持 Sass/Chrome
  • 我现在并没有创建一个真正意义上的模版库。但是考虑到这个网站也是用到了模板,所以我觉得建一个视觉模板库也是一个好主意。这样在很多地方都可以直接拿来用,更加方便也更加模块化。
正文到此结束
Loading...