終於,CSS麻瓜也走到這一步!

專案進入網頁排版配置微調階段,陸續加進各式CSS巧門,例如: 依視窗寬度自動隱藏多語系按鈕圖檔切換、依父容器Class切換顯示效果... 東西愈加愈多的下場是style.css愈來愈肥,充斥錯綜複雜的樣式語法,更要命的是因技巧生硬搞出一堆複製貼上、寫死的尺寸數字,依照寫C#、JavaScript的習慣,搞到如此複雜又難以維護,讓人如坐針氈~

每天打開醜陋的CSS修修改改,終於搞到自己都受不了,想起之前聽過的Sass/SCSS,透過巢狀結構、變數、運算、函式等技巧降低CSS的複雜度,將樣式設定內容結構化及模組化,可大幅減輕維護的痛苦。是該練等升級,學習使用高檔CSS兵器的時候了。

網路上有不少Sass/SCSS的介紹,在此不多贅述,提供幾篇我參考的文章:

要在Visual Studio裡編輯SCSS,暫時還需要套件協助,而好消息是 -- 已進入RC階段的VS2013 Update2將內建Sass/SCSS編輯功能,近期內會正式發佈。我的Visual Studio 2013有裝Web Essential,本身支援基本的Sass/SCSS語法高亮標示(Syntax Highlight)、編譯及結果預覽功能,編輯維護SCSS不成問題,先頂著用並期待VS2013 Update2上市吧!
(如需進階編輯支援,也可考慮Web Workbench套件。參考: 在 Visual Studio 撰寫 Sass(SCSS) 讓您快樂似神仙 by Bruce)

將Web Essentials的SASS選項調整如下,設定每次存檔時編譯產生css檔,並在編輯視窗旁顯示結果預覽(新手必備):

在專案中加入*.scss檔案,編輯儲存後會自動產生對應的.css檔案。

編輯.scss時,存檔後右半邊可檢視轉換出來的.css內容。

Sass/SCSS語法並不複雜,已經熟悉CSS的開發者可以很快上手。只花了半天就把原本複雜交錯的style.css整理成style.scss,原本的複製貼上改寫成@mixin + @include,幾處寫死的尺寸數字也改為運算式,未來要調整就簡單多了,至於進一步優化,留待未來慢慢重構。(說穿了是現在等級不到、技能還沒點足 orz)

跟所有前端工程師一樣,體驗過SCSS後只會有一個感想: "回不去了!"。未來面對較複雜的網站Style,我應該都會選擇使用SCSS,撰寫起來簡潔許多,更重要的是能大量減少"Copy & Paste",日後修改容易,也較不易漏改出錯。

最後,分享這次利用SCSS重構原有Style的幾則應用。(如果大家發現有改善空間,歡迎回饋給我!)

依瀏覽器寬度自動隱藏

原寫法:

#barX {
    display: none;
}
@media only screen and (min-width: 1024px) {
    .user #barX {
        display: block;
    }
}
@media only screen and (min-width: 1000px) {
    .vip #barX {
        display: block;
    }
}
#barY {
    display: none;
}
@media only screen and (min-width: 824px) {
    .user #barY {
        display: block;
    }
}
@media only screen and (min-width: 800px) {
    .vip #barY {
        display: block;
    }
}

SCSS版:

@mixin show-when-width($prefix, $minWidth) {
    @media only screen and (min-width: $minWidth) {
        #{$prefix} & { display: block; }
    }
}
$w1: 1024px;
$w2: 1000px;
#barX {
    display: none;
    @include show-when-width(".user", $w1);
    @include show-when-width(".vip", $w2);
}
#barY {
    display: none;
    @include show-when-width(".user", $w1 - 200px);
    @include show-when-width(".vip", $w2 - 200px);
}

多語系按鈕背景圖切換

原寫法:

.tw .send-btn {
    background: url(img/tw/send-button.png);
}
.cn .send-btn {
    background: url(img/cn/send-button.png);
}
.en .send-btn {
    background: url(img/en/send-button.png);
}
.tw .cancel-btn {
    background: url(img/tw/cancel-button.png);
}
.cn .cancel-btn {
    background: url(img/cn/cancel-button.png);
}
.en .cancel-btn {
    background: url(img/en/cancel-button.png);
}
.tw .preview-btn {
    background: url(img/tw/preview-button.png);
}
.cn .preview-btn {
    background: url(img/cn/preview-button.png);
}
.en .preview-btn {
    background: url(img/en/preview-button.png);
}

SCSS版:

@mixin multilang-bgimg($img) {
    .tw & { background: url(img/tw/#{$img}); }
    .cn & { background: url(img/cn/#{$img}); }
    .en & { background: url(img/en/#{$img}); }
}
.send-btn {
    @include multilang-bgimg("send-button.png");
}
.cancel-btn {
    @include multilang-bgimg("cancel-button.png");
}
.preview-btn {
    @include multilang-bgimg("preview-button.png");
}

特定模式時隱藏

原寫法:

#btn1 {
    width: 200px;
}
.vip #btn1 {
    display: none;
}
#btn2 {
    width: 120px;
}
.vip #btn2 {
    display: none;
}

SCSS版:

@mixin hide-for-vip {
    .vip & { display: none; }
}
#btn1 {
    width: 200px;
    @include hide-for-vip;
}
#btn2 {
    width: 120px;
    @include hide-for-vip;
}

批次產生樣式

原寫法:

.vip .mod-a .boo {
    display: none;
}
.vip .mod-b .boo {
    display: none;
}
.vip .mod-f .boo {
    display: none;
}
.vip .mod-g .boo {
    display: none;
}
.vip .mod-m .boo {
    display: none;
}

SCSS版:

@each $mod in mod-a, mod-b, mod-f, mod-g, mod-m {
    .#{$mod} .boo {
        @include hide-for-vip;
    }
}


Comments

Be the first to post a comment

Post a comment