Mark Otto和lan Feather分別分享了GitHub和Lonely Planet這兩個網站中如何應用CSS,我覺得我也應該參與到這個有趣的活動之中,談談我們在CodePen中是怎麼應用CSS的。
概覽
- 前處理器使用了SCSS
- 我們使用Autoprefixer
- 我們使用Rails Asset Pipeline
- 實際載入的那些可解釋為CSS的SCSS檔案其實就是一個包含各模組的目錄
- 我們有一個統一樣式,主要原因是這樣看起來一致性更好
- 我們不使用任何特別的“CSS架構”,只使用類
- 每一個網頁中不超過2-3個CSS檔案
- 媒體查詢我們使用可以關掉的
@mixin
- 我們鼓勵註釋
- 一些統計資料
- 在本文中“我們”這個詞大多數只代表我一個
- 未來展望和期待
前處理器
人們對於前處理器褒貶不一,但是我覺得如果做一個比較大的網站專案,沒有前處理器是非常困難的。若你認為我這是在過度依賴工具,會讓我效率變低,那麼請允許我嘲笑你。 我更喜歡SCSS是因為我喜歡它的社群,同時我也認為它更好。但實話說,所有這些主流的前處理器(Sass,LESS,Stylus)都基本可以滿足我的需求。這裡是一些我覺得有用的特性(按照實用性遞減排序):
- @import
- @mixin
- Nesting(巢狀)
- Variables(變數)
@extend
- Math(數學運算)
- Loops(迴圈)
- 長時間用它們工作,幫助我理解那些炫酷的小例子
不用前處理器我無法想象要花多大的精力才能取代這些特性。
在CSS屬性中加與瀏覽器相關的字首
因為有Autoprefixer這個工具,我在工作中幾乎不需要記CSS中屬性或者值。我特別喜歡它對 flexbox (伸縮佈局盒) 回退的處理方式。 我以前用Compass比較多,但我發現95%的情況下都是用它處理CSS3的@mixin
。我更喜歡“所見即所得”這種方式,而不是隻為標字首而到處放@include
。不用Compass 之後我比較懷念的一個功能是生成SVG漸變,但對於僅在IE9才需要的功能來說它也顯得過於重型了,所以總體上我也沒什麼大損失。
Rails
我是Rails Asset Pipeline的粉絲,它實在太好用了。 舉個例子: 我把句話放在檢視中:
1 |
<%= stylesheet_link_tag "about/about" %> |
然後它會產生一個我需要的CSS檔案:
1 |
<link href="http://assets.codepen.io/assets/about/about-a05e4bd3a5ca76c3fb17f2353fedbd99.css" media="screen" rel="stylesheet" type="text/css" /> |
我們在資源裡把終止時間寫得離現在遠一點。
我們每一次部署的時候,它都會通過重新生成隨機數來重新快取,所以這是一個非常棒的快取機制。 我們在CodePen中只是對JavaScript使用Sprockets。有了它我們可以這麼幹:
1 2 |
//= require common/whatever.js //= require_tree ./../hearting/ |
你也可以在CSS這麼做,但何必自尋煩惱呢,因為: 1. Sass能夠實現這個功能 2. 如果你用Sass實現這個功能,那依賴性表現更好。像$variables
和@mixin
都能夠在檔案之間應用了。 我們並不會把CSS
檔案上傳到Git
倉庫中,這樣對Git
很好,所有的資源都在部署的時候進行解釋編譯。
檔案組織結構
被載入的CSS檔案會有一份對應的SCSS,這個SCSS檔案中沒有任何實際的CSS程式碼,而是用來描述CSS檔案中的內容。舉個例子,這是我們現在的global.scss:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// 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"; // 第三方元件 // (目前沒有) |
我試著堅持這樣做,但每當我向一個本應被全部匯入的檔案中新增程式碼時,老是會丟擲一堆異常。我應該弄個通告檔案然後寫上:
1 |
@import "shame"; // 注意有點條理啊,裡面這幾個魂淡。 |
程式碼的組織結構
我寫程式碼時一定會遵循的規範:【譯者注:作者在原文中說是一種強迫症,表示這些規範是他一定會遵循的】
- 屬性和巢狀有2個空格的縮排
- 在選擇器(selectors)之後或”{“前面加一個空格
- 一行一個屬性宣告
- 在”:”(冒號)後面加一個空格
- 尾部的”}”符號另起一行,並與選擇器同等縮排
0
作為長度的時候不加單位- 名稱中使用連字元”-”而不用下劃線”_”
我寫程式碼時大多會遵循的規範:
兩個聯絡密切的類中間不加空行:
1 2 3 4 5 6 |
.thing { } .related-thing { } |
有一點聯絡的兩個類之間加一個空行:
1 2 3 4 5 6 7 |
.thing { } .another-thing { } |
沒什麼聯絡的內容留兩空行:
1 2 3 4 5 6 7 |
.thing { } .totally-different-thing { } |
我不太關心的規範:
- 屬性的順序。相關的屬性(如 height/width)一般會放一起,但不會特別在意這個。
- 註釋方式。兩種都可以用
在實際的工作中,我甚至也不會嚴格按照自己的規範寫。
模式
我寫的程式碼幾乎會給所有的元素一個類,我不知道這是不是遵循了SMACSS,OOCSS,BEM等等,不是很在意這些。 這並不意味著我從不寫巢狀(比如建立組合選擇器),或者說我對巢狀的層數要求苛刻,只是我一般不會寫太深的巢狀。 我一般會這樣寫:
1 2 3 4 5 6 |
.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做
媒體查詢。有時我會想“這個寬度或更大”,有時會想“這個寬度或更小”(就是媒體查詢的邏輯呀!)。這樣寫出來有點囉嗦:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
@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),它們也用不上。
註釋
我的註釋風格十分自由。在大多數情況下我從來不會修改它,如果在之後我讀這些註釋發現我不懂它什麼意思了,或者它和程式碼描述得驢頭不對馬嘴了,我就會刪掉它。
1 2 3 |
.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
但是從來不會出現我找不到我要找的檔案這種情況。原因如下:
- 在Sublime編輯器中尋找一個專案裡的檔案很容易
- 它們有良好的組織和命名,我只需要用
command –t
便可以直接跳到我要找的檔案
- SCSS檔案裡一共有13,345行程式碼。
find stylesheets/ -name '*.scss' | xargs wc –l
global.css
大小:11.8kpage.css
(除了編輯器,幾乎所有頁面都有用到)大小:5.5keditor.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?
- 我現在並沒有建立一個真正意義上的模版庫。但是考慮到這個網站也是用到了模板,所以我覺得建一個視覺模板庫也是一個好主意。這樣在很多地方都可以直接拿來用,更加方便也更加模組化。