I'm Kero

Planning, Fast and Slow.

CSS 命名的基本規則

我發現很多補習班似乎都不重視教導 CSS class naming 的重要性。簡單的說,會寫 CSS 很容易,但寫好 CSS 不是那麼容易的事,好的命名習慣重視語義化和統一性,和其他程式語言的 naming 一樣有利於大大提高維護性和可用性。

(以下以 SASS 語法 為例)

Think in Objects

讓沒有學過物件導向程式設計的網頁設計師去 think in objects 是有點勉強,不過統籌和最大效益化勞動成果是每個人都要去思考的。寫完一套 CSS,裡面的 CLASS 以後還能用到嗎?構成的方法需要特別注意。比如要寫一個 button,與其這樣寫:

#article .article-content .link {
    background: linear-gradient(#eee, #ccc);
    color: #333;
    padding: 4px 10px 5px;
    &:hover {
        background: linear-gradient(#fff, #ddd);
        color: #111;
    }
}

顯然把它視為可重複利用的 object 來寫更好。

.button {
    background: linear-gradient(#eee, #ccc);
    color: #333;
    padding: 4px 10px 5px;
    &:hover {
        background: linear-gradient(#fff, #ddd);
        color: #111;
    }
}

Parent-child Relationships

很多新手開發者在命名的時候不知是斤斤計較那幾個字、希望盡可能簡短還是如何,常常寫出 .aaa .xxx .qqq 這種東西,後續不要說別人來接手了,原作者自己都頭大。因為在維護工作上無跡可尋!

有時即使賦予了 class 語義,卻吝於表示層級。例如:

.post {
    margin: 2em;

    .title {
        font-size: 2em;
        font-weight: normal;
    }
}

其實寫成如下的命名會更好:

.post {
    margin: 2em 0;
}
.post-title {
    font-size: 2em;
    font-weight: normal;
}

一是令結構一目了然,二是可達成深度最小化 (minimizing depth) 的目的。深度最小化後使 CSS 不至於太臃腫,以後也方便做 override 的處理。

Plural Parent Pattern

複數形態的命名容易被忽略但其實也是蠻重要的小細節。例如一個 tab 群組,你可以用 .tab-group 也可以用 .tabs 來命名,
選擇哪種沒有標準答案,重點是設計者看的時候會很清楚它所代表的意思。

.tabs {
    border-bottom: 1px solid silver;
    text-align: center;
}

Using Modifiers

像連結或 tab 的 .is-selected, .active, .on 這種基本的,設計者通常有意識到,不過其實 modifier 的應用範圍可以很廣,適用於大多數 "只有細小差異、可沿用既有 class" 的情況。比如說:

.textbox {
    font: 13px sans-serif;
    border: 1px solid #ccc;
    border-top: 1px solid #999;
    border-radius: 2px;
    padding: 2px 4px;

    &:focus { outline: none; border: 1px solid #69e; }

    &.large { font-size: 18px; }
    &.small { font-size: 11px; padding: 1px 2px; }
}

在使用這套 css 的時候,我可以方便地運用 div class="textbox large" 或 div class="textbox small" 去控制它的字型和 padding 樣式,其他則維持一致。

寫到這裡,你或許意識到,一些常用的樣式可以寫成 global modifier 以備隨時取用。

.clearfix { @include clearfix; }

.is-hidden { display: none !important; }
.is-invisible { visibility: none !important; }

.block { display: block !important; }
.inline { display: inline !important; }
.inline-block { display: inline-block !important; }

.left { float: left !important; }
.right { float: right !important; }

.text-left { text-align: left !important; }
.text-center { text-align: center !important; }
.text-right { text-align: right !important; }

.mt0 { margin-top: 0 !important; }
.mt1 { margin-top: 1em !important; }
.mb0 { margin-bottom: 0 !important; }
.mb1 { margin-bottom: 1em !important; }

Nouns and Adjectives

最後,回歸到命名傳統這個主題,基本上脫離不了名詞和形容詞。

可重複利用的模組 CLASS 通常是名詞

.noun {} //ex: .button, .menu, .block

表達父子層級結構的時候,它通常是名詞的組合

.noun-moun {} //ex: .post-title

次級 class 會是形容詞加上名詞,例如

.adjective-noun {} //ex: .dropdown-button

然後 Modifier 通常永遠是形容詞

.is-state {} //ex: .is-seletedd, .is-hidden
.adjective {} //ex: .left, .right, .inline

File Structure the SASS Way

寫 SASS 習慣分成 N 個小片段 (partials) 以利維護,這裡提供一個範例

partials/
    |-- _alerts.scss
    |-- _buttons.scss
    |-- _checkboxes.scss
    |-- _choices.scss
    |-- _countdowns.scss
    |-- _footer.scss
    |-- _forms.scss
    |-- _icons.scss
    |-- _menus.scss
    |-- _messages.scss
    |-- _modifiers.scss
    |-- _panes.scss
    |-- _ratings.scss
    |-- _results.scss
    |-- _selectboxes.scss
    |-- _tableviews.scss
    |-- _textboxes.scss
    |-- _throbbers.scss
    |-- _typography.scss

當然有其他組織方法更適合你的專案,有待編寫的過程中慢慢摸索和證實。