f2etw / book

2014 f2e gitbook
9 stars 0 forks source link

容易忽略的Front-end Best Practice #10

Open daniel-huang opened 9 years ago

daniel-huang commented 9 years ago

容易忽略的Front-end Best Practice

這篇文章主要分享一些個人認為容易忽略的前端最佳實踐方式。一方面可作為新手的提醒,也可以作為老手們的備忘。

減少無謂的HTML階層

相信大家都曾經經歷過以下的狀況:

<div class="button">
    <span class="foo bar">
        <a href="#">Link</a>
    </span>
</div>

沒有特別目的卻把HTML用上面複雜的方式表達一個簡單的結構。如上例子,是要表達一個作為Button的Link,複雜的層級不僅難以閱讀,更添加CSS撰寫的複雜度,建議採用如下方式:

<a href="#" class="button">Link</a>


Class Naming

承接前述,CSS的 class 命名建議採用該element「是什麼」,而不是「看起來像什麼」。

建議將以下的A方式用B方式為佳: A:

.red-button {color: red;}
.blue-button {color: blue;}

B:

.button {color: orange;}


CSS優先權

通常初學CSS的時候,總是會對於寫了某個樣式而蓋了某個樣式苦惱,不知道誰蓋掉了誰,又是怎麼改掉的,「稍微」進階解法錯誤方法就用 !important 暴力蓋過,導致到處充斥著 !important 的窘境。

其實,最常見的暴力法是寫 inline style,然而不管哪種方式,暴力的結果就是導致維護性變得非常差。

但只要搞清楚清楚 CSS selector, element, class, id, style 之間的權重關係,就能迎刃而解。 這個網站用漫畫的方式解說 CSS Specificity

類型上總結地講,!important > inline style > id selector > class selector 或 pseudo class selector 或 attribute selector > element。

減少沒有用到的CSS以增進效能

經常使用plugin、library來開發網站的時候,最容易寫了許多個 <link><script> 去引入css和js,如此,不僅讓request增加以外,也造成一大堆unused css。

檢閱網站的unused css數目,可透過Chrome開發者工具 -> Audits -> Run

Responsive圖片的未來發展

圖片大小該什麼時候用什麼size,總會困擾到一些人。HTML5 <picture> tag 將解決這個麻煩事。 以下為範例:

<picture>
    <source srcset="smaller.jpg, smaller_retina.jpg 2x" media="(max-width: 768px)">
    <source srcset="default.jpg, default_retina.jpg 2x">
    <img srcset="default.jpg, default_retina.jpg 2x" alt="My default image">
</picture>

目前並非所有主流的瀏覽器均支援 <picture> ,但可以使用Picturefill來解決browser support的問題。詳細請參考其網站介紹。

透過Sass整合BEM的CSS架構方法

(BEM)[https://bem.info/] 為Block-Element-Modifier的簡寫。 Block

Element

Modifier

命名原則 (MindBEMding)

.block {...}
.block__element {...}
.block--modifier {...}
.block__element--modifier {...}

與Sass的整合 (v3.4) 先定義分隔符號:

$elementSeparator: '__'; 
$modifierSeparator: '--';

再撰寫建構用的function:

@function selectorToString($selector) {
    $selector: inspect($selector); //cast to string
    $selector: str-slice($selector, 2, -2); //remove bracket
    @return $selector;
}

@function containsModifier($selector) {
    $selector: selectorToString($selector);
    @if str-index($selector, $modifierSeparator) {
        @return true;
    }
    @else { 
        @return false;
    }
}

@function getBlock($selector) {
    $selector: selectorToString($selector);
    $modifierStart: str-index($selector, $modifierSeparator) — 1;
    @return str-slice($selector, 0, $modifierStart);
}

最後撰寫Mixin:

@mixin b($block) {
   .#{$block} {
       @content; 
   }
}

@mixin m($modifier) {
    @at-root {
        #{&}#{$modifierSeparator+$modifier} {
            @content;
        }
    }
}

@mixin e($element) {
    $selector: &;
    $block: getBlock($selector);
    @if containsModifier($selector) {
        @at-root {
            #{$selector} {
                #{$block+$elementSeparator+$element} {
                    @content;
                }
            }
       }
    }
    @else {
        @at-root {
            #{$selector+$elementSeparator+$element} {
                @content;
            }
        }
    }
}

實際結果:

@include b(block) {
   background: red;
   @include m(modifier) {
       background: blue;
       @include e(element) { 
           background: yellow;
       }
   }
}

將產生如下結果:

.block {
    background: red;
}
.block--modifier {
    background: blue;
}
.block--modifier .block__element {
    background: yellow;
}
DerekHung commented 9 years ago

非常感謝您的投稿!在近日內會公布此次徵稿活動的結果,敬請期待:D