PostCSS及其常用插件介紹

前幾天,PostCSS 6.0 分佈了。

PostCSS 處理了很多你不必處理的乏味工作。它很巧妙的不同於預處理器,提供了可選的且更簡潔的編程語言,來編譯成 CSS,如 Sass、Less 與 Stylus。得出這個結論的部分原因是:

  • 它的名字。PostCSS 既能在預處理器將源代碼編譯成 CSS 之前也能在其之後對文件執行操作。
  • PostCSS 能替代你的預處理器。現在有很多插件實現了一些設計,如變量、 嵌套、mixins 以及 extends。

然而,雖然你可以構建自己的預處理器,但除非你想限制功能並加快編譯速度,你沒有別的該這麼做的理由。就我個人而言,爲增強 CSS,我使用 Sass,再加以 PostCSS 輔佐。沒什麼波瀾,可能是對於大多數前端使用者來說沒什麼大的影響,因爲通常大家都是使用其插件。

CSS 預處理器 和 CSS 後處理器

在說 PostCSS 之前,先了解一下 pre-processor 。

pre-processor(預處理器)

在寫CSS的時候,經常會碰到這樣的問題,比如說“變量”:

    h1{
        color:red;
    }
    .title{
        color:red;
    }
    .classA{
        color:red;
    }

如果有一天,我想要把顏色改用藍色怎麼辦?你需要:查找 -> red ->替換 -> blue 。

先這種簡單的 CSS 中,可能這並不繁瑣,但是對於大型應用來說,可能是要摔鍵盤了。還有更多的問題,比如代碼複用,嵌套,Mixins(混入)等等…

於是 Sass / Less就出現了,他們都是 CSS 的預處理器(pre-processor),看個簡單的範例:

    $font-stack: Helvetica, sans-serif;
    $primary-color: #333;
     
    body {
      font: 100% $font-stack;
      color: $primary-color;
    }

這裏用了變量功能,以後想要修改 CSS 直接改變量內容就好,不用在每一個地方都改了。像 Sass 這些預處理器,你要學一些新的語法,學一些新的表示方式,你就可以用這些新的語法寫好一些看起來很像 CSS 但不是 CSS 的東西,然後把它編譯成 CSS 。

post-processor(後處理器)

瞭解什麼是 pre-processor 以後,來看看什麼是 post-processor 。

post-processor(後處理器)最常見的例子就是這個了 CSS Prefixer 。

在寫 CSS 的時候,會針對瀏覽器加上一些前綴,但是每次都這樣寫實在是很麻煩,官方範例,原本 CSS 是這樣的:

    .my-class, #my-id {
        border-radius: 1em;
        transition: all 1s ease;
        box-shadow: #123456 0 0 10px;
    }

使用 CSS Prefixer 添加前綴後,

    .my-class, #my-id {
        -moz-border-radius: 1em;
        -webkit-border-radius: 1em;
        border-radius: 1em;
        -moz-transition: all 1s ease;
        -o-transition: all 1s ease;
        -webkit-transition: all 1s ease;
        transition: all 1s ease;
        -moz-box-shadow: #123456 0 0 10px;
        -webkit-box-shadow: #123456 0 0 10px;
        box-shadow: #123456 0 0 10px
        }

很簡單,全幫你加好了,這就是後處理器(post-processor)

簡單來說,預處理器( pre-processor )是你把一些長得很像 CSS 但不是 CSS 的東西丟給它,處理過後會給你編譯過後的CSS,
而 CSS 再經過後處理器 ( post-processor ),透過一些規則幫它加上一些東西,最後產出完整的CSS文件!

或許你有一個疑問,預處理器( pre-processor )不是也可以完成這種工作嗎?

sass代碼:

    @mixin border-radius($radius) {
      -webkit-border-radius: $radius;
         -moz-border-radius: $radius;
          -ms-border-radius: $radius;
              border-radius: $radius;
    }
     
    .box { @include border-radius(10px); }

確實,在 Sass 裏面,用 mixin 也可以達成加上前綴這樣的目的。

那爲什麼要用 post-processor ?

後處理器有幾個優點:

1.你可以寫自己的插件:如果你選了 Sass ,你就必須接受 Sass 的一切,接受他的語法,要用就要用一整套 Sass,你不能只選擇你要的某些功能,但是如果你用了 PostCSS ,你可以選擇你自己想要的功能。更加確切的說,平時工作你基本不會直接去使用 PostCSS ,它的功能基本都是插件去完成的。 PostCSS 只是提供了一個環境。舉例來說,加上前綴就是一個功能,或是讓你可以用變量也是一個功能,你可以自己選擇你想要的功能加入,而不是一用就要用一整套完整的方案,當然,你也可以用javascript寫自己的plugin,解析 CSS 語法並且加入一些自己想要的東西。

2.用標準的 CSS 語法:前面有提過預處理器跟後處理器的差別,一個是寫好 Sass(或其他的)丟進去,一個是把 CSS 加上一些東西之類丟出來,有些人相信將來的某一天,所有瀏覽器都會支援標準的 CSS ,例如說你不必再加上 -webkit- 之類的prefix
到了那一天,如果你是用 PostCSS ,你可以不做任何動作,直接拿原有的 CSS 就好,但如果你用的是 Sass 就沒有辦法這樣
像是http://www.myth.io/ 這套,就提倡用「未來的 CSS 標準」寫 CSS ,在現代先用後處理器的方式去產生可以跑的 CSS ,但是在未來的某一天,把那些 plugin 去除以後,你的 CSS 還是可以正常地跑出結果。

PostCSS 介紹

PostCSS 本身是一個功能比較單一的工具。它提供了一種方式用 JavaScript 代碼來處理 CSS。它負責把 CSS 代碼解析成抽象語法樹結構(Abstract Syntax Tree,AST),再交由插件來進行處理。插件基於 CSS 代碼的 AST 所能進行的操作是多種多樣的,比如可以支持變量和混入(mixin),增加瀏覽器相關的聲明前綴,或是把使用將來的 CSS 規範的樣式規則轉譯(transpile)成當前的 CSS 規範支持的格式。從這個角度來說,PostCSS 的強大之處在於其不斷髮展的插件體系。目前 PostCSS 已經有 200 多個功能各異的插件。開發人員也可以根據項目的需要,開發出自己的 PostCSS 插件。

PostCSS 從其誕生之時就帶來了社區對其類別劃分的爭議。這主要是由於其名稱中的 post,很容易讓人聯想到 PostCSS 是用來做 CSS 後處理(post-processor)的,從而與已有的 CSS 預處理(pre-processor)語言,如 SASS 和 LESS 等進行類比。實際上,PostCSS 的主要功能只有兩個:第一個就是前面提到的把 CSS 解析成 JavaScript 可以操作的 AST,第二個就是調用插件來處理 AST 並得到結果。因此,不能簡單的把 PostCSS 歸類成 CSS 預處理或後處理工具。PostCSS 所能執行的任務非常多,同時涵蓋了傳統意義上的預處理和後處理。PostCSS 是一個全新的工具,給前端開發人員帶來了不一樣的處理 CSS 的方式。

使用 PostCSS

PostCSS 一般不單獨使用,而是與已有的構建工具進行集成。PostCSS 與主流的構建工具,如 Webpack、Grunt 和 Gulp 都可以進行集成。完成集成之後,選擇滿足功能需求的 PostCSS 插件並進行配置。下面將具體介紹如何在 Webpack、Grunt 和 Gulp 中使用 PostCSS 的 Autoprefixer 插件。

Gulp

爲了在 Gulp 中使用 PostCSS,你需要建立你的項目並安裝兩個模塊:

CommandLine 代碼:

    npm init
    npm install --save-dev gulp gulp-postcss

然後,你可以繼續添加你需要的插件,如: autoprefixer 與 cssnano。

CommandLine 代碼:

npm install --save-dev autoprefixer cssnano

你可以創建一個 gulpfile.js 文件。它定義了一個任務,加載 CSS 源文件然後通過 PostCSS 管道。插件以及任意所需的其它選項以一個數組傳給 PostCSS。最終,CSS 文件被輸出至目標文件。

Gulp.js 代碼:

    // Gulp.js 配置
    var gulp = require('gulp'),
        postcss = require('gulp-postcss');
     
    // 應用 PostCSS 插件
    gulp.task('css', function() {
      return gulp.src('src/main.css')
        .pipe(postcss([
          require('autoprefixer')({}),
          require('cssnano')
        ]))
        .pipe(gulp.dest('dest/main.css'));
    });

在控制檯,可使用下面的命令運行該任務:

CommandLine 代碼:

gulp css

現在我們只差一份方便的 PostCSS 插件列表了。

Webpack

Webpack 中使用 postcss-loader 來執行插件處理。在代碼清單 1 中,postcss-loader 用來對.css 文件進行處理,並添加在 style-loader 和 css-loader 之後。通過一個額外的 postcss 方法來返回所需要使用的 PostCSS 插件。require(‘autoprefixer’) 的作用是加載 Autoprefixer 插件。

清單 1. 在 Webpack 中使用 PostCSS 插件

Webpack 代碼:

    var path = require('path');
     
    module.exports = {
     context: path.join(__dirname, 'app'),
     entry: './app',
     output: {
       path: path.join(__dirname, 'dist'),
       filename: 'bundle.js'
     },
     module: {
       loaders: [
         {
           test:   /\.css$/,
           loader: "style-loader!css-loader!postcss-loader"
         }
       ]
     },
     postcss: function () {
       return [require('autoprefixer')];
     }
    }

Grunt

Grunt 中使用 grunt-postcss 來集成 PostCSS。Grunt 中需要使用 grunt.loadNpmTasks 方法來加載插件,如代碼清單 3 所示。

清單 3. 在 Grunt 中使用 PostCSS 插件

Grunt 代碼:

    module.exports = function(grunt) {
     grunt.initConfig({
       postcss: {
         options: {
           processors: [
             require('autoprefixer')()
           ]
         },
         dist: {
           src: 'app/**/*.css',
           expand: true,
           dest: 'dist'
         }
       }
     });
      grunt.loadNpmTasks('grunt-postcss');
    }

PostCSS 常用插件

Autoprefixer

Autoprefixer 是一個流行的 PostCSS 插件,其作用是爲 CSS 中的屬性添加瀏覽器特定的前綴。由於 CSS 規範的制定和完善一般需要花費比較長的時間,瀏覽器廠商在實現某個 CSS 新功能時,會使用特定的瀏覽器前綴來作爲正式規範版本之前的實驗性實現。比如 Webkit 核心的瀏覽器使用-webkit-,微軟的 IE 使用-ms-。爲了兼容不同瀏覽器的不同版本,在編寫 CSS 樣式規則聲明時通常需要添加額外的帶前綴的屬性。這是一項繁瑣而無趣的工作。Autoprefixer 可以自動的完成這項工作。Autoprefixer 可以根據需要指定支持的瀏覽器類型和版本,自動添加所需的帶前綴的屬性聲明。開發人員在編寫 CSS 時只需要使用 CSS 規範中的標準屬性名即可。

安裝 Autoprefixer。

CommandLine 代碼:

npm install --save-dev autoprefixer

代碼清單 4 中給出了使用 CSS 彈性盒模型的 display 屬性聲明。

清單 4. 標準的 CSS 彈性盒模型的 display 屬性聲明

CSS 代碼:

    #content {
     display: flex;
    }

在經過 Autoprefixer 處理之後得到的 CSS 如代碼清單 5 所示。

清單 5. 使用 Autoprefixer 處理之後的 CSS

CSS 代碼:

    #content {
     display: -webkit-box;
     display: -webkit-flex;
     display: -ms-flexbox;
     display: flex;
    }

Autoprefixer 使用 Can I Use 網站提供的數據來確定所要添加的不同瀏覽器的前綴。隨着瀏覽器版本的升級,瀏覽器在新版本中可能已經提供了對標準屬性的支持,從而不再需要添加額外的前綴。Autoprefixer 可以配置需要支持的瀏覽器。如“last 2 versions”表示主流瀏覽器的最近兩個版本,“ie 6-8”表示 IE 6 到 8,“> 1%”表示全球使用率大於 1%的瀏覽器版本。代碼清單 6 中給出了配置 Autoprefixer 插件的示例。

清單 6. 配置 Autoprefixer 插件

JavaScript 代碼:

    require('autoprefixer')({
     browsers: ['last 2 versions']
    })

Autoprefixer 除了添加所需要的屬性名稱前綴之外,還可以移除 CSS 代碼中冗餘的屬性名稱前綴。遺留 CSS 代碼中可能包含由開發人員手動添加的舊版本的瀏覽器所支持的帶前綴的屬性名稱。Autoprefixer 默認情況下會移除這些冗餘的前綴。可以通過配置對象中的 remove 屬性來配置該行爲。

cssnext

cssnext 插件允許開發人員在當前的項目中使用 CSS 將來版本中可能會加入的新特性。cssnext 負責把這些新特性轉譯成當前瀏覽器中可以使用的語法。從實現角度來說,cssnext 是一系列與 CSS 將來版本相關的 PostCSS 插件的組合。比如,cssnext 中已經包含了對 Autoprefixer 的使用,因此使用了 cssnext 就不再需要使用 Autoprefixer。

自定義屬性和變量

CSS 的層疊變量的自定義屬性規範(CSS Custom Properties for Cascading Variables)允許在 CSS 中定義屬性並在樣式規則中作爲變量來使用它們。自定義屬性的名稱以“–”開頭。當聲明瞭自定義屬性之後,可以在樣式規則中使用“var()”函數來引用,如代碼清單 7 所示。

清單 7. CSS 自定義屬性和變量

CSS 代碼:

    :root {
     --text-color: black;
    }
     
    body {
     color: var(--text-color);
    }

在經過 cssnext 轉換之後的 CSS 代碼如代碼清單 8 所示。

清單 8. 轉換之後的 CSS 代碼

CSS 代碼:

    body {
     color: black;
    }

自定義選擇器

CSS 擴展規範(CSS Extensions)中允許創建自定義選擇器,比如可以對所有的標題元素(h1 到 h6)創建一個自定義選擇器並應用樣式。通過“@custom-selector”來定義自定義選擇器。在代碼清單 9 中,“–heading”是自定義選擇器的名稱,其等同於選擇器聲明“h1, h2, h3, h4, h5, h6”。

清單 9. 自定義選擇器

CSS 代碼:

    @custom-selector :--heading h1, h2, h3, h4, h5, h6;
     
    :--heading {
     font-weight: bold;
    }

經過 cssnext 處理之後的 CSS 如代碼清單 10 所示。

清單 10. 轉換之後的 CSS 代碼

CSS 代碼:

    h1,
    h2,
    h3,
    h4,
    h5,
    h6 {
     font-weight: bold;
    }

樣式規則嵌套

樣式規則嵌套是一個非常實用的功能,可以減少重複的選擇器聲明。這也是 SASS 和 LESS 等 CSS 預處理器流行的一個重要原因。CSS 嵌套模塊規範(CSS Nesting Module)中定義了標準的樣式規則嵌套方式。可以通過 cssnext 把標準的樣式嵌套格式轉換成當前的格式。CSS 嵌套規範中定義了兩種嵌套方式:第一種方式要求嵌套的樣式聲明使用“&”作爲前綴,“&”只能作爲聲明的起始位置;第二種方式的樣式聲明使用“@nest”作爲前綴,並且“&”可以出現在任意位置。代碼清單 11 中給出了兩種不同聲明方式的示例。

清單 11. 樣式規則嵌套

CSS 代碼:

    .message {
     font-weight: normal;
     & .header {
       font-weight: bold;
     }
      @nest .body & {
       color: black;
     }
    }

經過 cssnext 轉換之後的 CSS 代碼如代碼清單 12 所示。

清單 12. 轉換之後的 CSS 代碼

CSS 代碼:

    .message {
     font-weight: normal
    }
     
    .message .header {
     font-weight: bold;
    }
     
    .body .message {
     color: black;
    }

CSS 模塊化

在編寫 CSS 代碼時會遇到的一個很重要的問題是 CSS 代碼的組織方式。當項目中包含的 CSS 樣式非常多時,該問題尤其突出。這主要是由於不同 CSS 文件中的樣式聲明可能產生名稱衝突。現在的 Web 開發大多采用組件化的組織方式,即把應用劃分成多個不同的組件。每個組件都可以有自己的 CSS 樣式聲明。比如,兩個組件的 CSS 中可能都定義了對於 CSS 類 title 的樣式規則。當這兩個組件被放在同一個頁面上時,衝突的 CSS 類名稱可能造成樣式的錯亂。對於此類 CSS 類名衝突問題,一般的做法是避免全局名稱空間中的樣式聲明,而是每個組件有自己的名稱空間。BEM 通過特殊的命名 CSS 類名的方式來解決名稱衝突的問題。兩個不同組件中的標題的 CSS 類名可能爲 component1__title 和 component2__title。

CSS 模塊(CSS modules)並不要求使用 BEM 那樣複雜的命名規範。每個組件可以自由選擇最合適的簡單 CSS 類名。組件的 CSS 類名在使用時會被轉換成帶唯一標識符的形式。這樣就避免了名稱衝突。在組件開發中可以繼續使用簡單的 CSS 類名,而不用擔心名稱衝突問題。代碼清單 13 中給出了使用 CSS 模塊規範的 CSS 代碼。樣式規則之前的“:global”表示這是一個全局樣式聲明。其他的樣式聲明是局部的。

清單 13. 使用 CSS 模塊規範的 CSS 代碼

CSS 代碼:

    :global .title {
     font-size: 20px;
    }
     
    .content {
     font-weight: bold;
    }

經過轉換之後的 CSS 樣式聲明如代碼清單 14 所示。全局的 CSS 類名 title 保存不變,局部的 CSS 類名 content 被轉換成_content_6xmce_5。這樣就確保了不會與其他組件中名稱爲 content 的類名衝突。

清單 14. 轉換之後的 CSS 代碼

CSS 代碼:

    .title {
     font-size: 20px;
    }
     
    ._content_6xmce_5 {
     font-weight: bold;
    }

由於在組件的 HTML 代碼中引用的 CSS 類名和最終生成的類名並不相同,因此需要一箇中間的過程來進行類名的轉換。對於 React 來說,可以使用 react-css-modules 插件;在其他情況下,可以使用 PostHTML 對 HTML 進行處理。postcss-modules 插件把 CSS 模塊中的 CSS 類名的對應關係保存在一個 JavaScript 對象中,可以被 PostHTML 中的 posthtml-css-modules 插件來使用。

在代碼清單 15 中,在使用 postcss-modules 插件時提供了一個方法 getJSON。當 CSS 模塊的轉換完成時,該方法會被調用。該方法的參數 json 參數表示的是轉換結果的 JavaScript 對象。該對象被以 JavaScript 文件的形式保存到 cssModules 目錄下,並添加了模塊導出的邏輯。

清單 15. 保存 CSS 模塊的輸出文件

JavaScript 代碼:

require('postcss-modules')({
   getJSON: function(cssFileName, json) {
     var cssName = path.basename(cssFileName, '.css');
     var jsonFileName = path.resolve(dist, 'cssModules', cssName + '.js');
     mkdirp.sync(path.dirname(jsonFileName));
     fs.writeFileSync(jsonFileName, "module.exports = " + JSON.stringify(json) + ";");
   }
 })

代碼清單 16 中給出了使用 Gulp 的 gulp-posthtml 來處理 HTML 文件的任務。posthtml-css-modules 可以處理一個目錄下的多個 CSS 模塊輸出文件。

清單 16. 使用 PostHTML 處理 HTML 裏支持 CSS 模塊

JavaScript 代碼:

    gulp.task('posthtml', function() {
     var posthtml = require('gulp-posthtml');
     return gulp.src('app/**/*.html')
       .pipe(posthtml([ require('posthtml-css-modules')(path.join(dist, 'cssModules')) ]))
       .pipe(gulp.dest('dist/'));
    });

在 HTML 文件中使用“css-module”屬性來指定對應的 CSS 類名。在代碼清單 17 中,名稱“header.content”的 header 表示的是 CSS 文件名,而 content 是該文件中定義的 CSS 類名。

清單 17. 使用 CSS 模塊的 HTML 文件

HTML 代碼:

<div css-module="header.content">Hello world</div>

在經過處理之後,得到的 HTML 內容如代碼清單 18 所示。

清單 18. 轉換之後的 HTML 文件

HTML 代碼:

<div class="_content_6xmce_5">Hello world</div>

資源文件處理

在 CSS 中經常會需要引用外部資源,如圖片和字體等。在 CSS 代碼中處理這些資源時會遇到一些常見的問題,比如圖片的路徑問題,內聯圖片內容,生成圖片 Sprites 等。對於這些問題,都有專門的 PostCSS 插件來提供所需的功能。

postcss-assets 插件用來處理圖片和 SVG。在 CSS 聲明中引用圖片時,可以使用 resolve 加上圖片路徑的形式,如“resolve(‘logo.png’)”。在插件處理時,會按照一定的順序在指定的目錄中查找該文件,如果找到,會用圖片的真實路徑來替換。可以通過選項 loadPaths 來指定查找的路徑,basePath 來指定項目的根目錄。在 CSS 聲明中,可以使用 width、height 和 size 方法來獲取到圖片的寬度、高度和尺寸。當需要內聯一個圖片時,可以使用 inline 方法。inline 會把圖片轉換成 Base64 編碼的 data url 的格式,這樣可以減少對圖片的 HTTP 請求。代碼清單 19 給出了使用示例。

清單 19. Postcss-assets 插件使用示例

JavaScript 代碼:

    require('postcss-assets')({
       loadPaths: ['assets/images']
    })

代碼清單 20 中給出了使用 resolve 的 CSS 樣式聲明。

清單 20. 使用 resolve 的 CSS 樣式聲明

CSS 代碼:

    .logo {
     background-image: resolve('logo.png');
    }

代碼清單 21 中給出了 cssnext 處理之後的 CSS 代碼。

清單 21. 轉換之後的 CSS 代碼

CSS 代碼:

    .logo {
     background-image: url('/assets/images/logo.png');
    }

PostCSS Assets

PostCSS Assets 提供了很多實用的圖像處理函數:

CommandLine 代碼:

    npm install --save-dev postcss-assets

它的選項包括:

  • 歸約 URL: 通過給定文件名,PostCSS Assets 會使用根路徑或完全合法的 URL 來替換 resolve(image)。
  • 處理尺寸: PostCSS Assets 會使用一個等價的像素值來替換 width(image), height(image) 或 size(image)。
  • 內聯圖像: PostCSS Assets 會使用 Base64 編碼的字符串替換 inline(image)。
  • 清除緩存: PostCSS Assets 會給圖像引用添加一個隨機的查詢字符串來確認加載的是最新的文件。

Rucksack

Rucksack 提供了很多函數,它的開發者宣稱,它們會使 CSS 開發再次有趣起來。

CommandLine 代碼:

    npm install --save-dev rucksack-css

它的選項包括:

  • 響應式的字體排版,僅需一個簡單的 font-size: responsive 聲明,就能夠自動調整字體大小與行高。
  • 大量僞選擇器,如 li:at-least(4),選擇了任意含至少 4 個條目的列表。
  • 屬性別名,如在你的 CSS 中使用 bg 代替 background,
  • 大量預定義的緩動函數。

Stylelint

Stylelint 基於 140 個規則報錯,這些規則被設計用來捕獲常見錯誤,實現樣式協議並強制最佳實踐。有很多選項可用來依你的喜好配置 Stylelint —— Pavels Jelisejevs 的文章使用 PostCSS 提升你的 CSS 質量帶你走過搭建過程。

CSS MQPacker

MQPacker 在必要時會將你的媒體查詢成一個規則:

CommandLine 代碼:

    npm install --save-dev css-mqpacker

預處理器如 Sass 能在一個聲明裏使用媒體查詢,很簡單,如:

CSS 代碼:

    .widget1 {
      width: 100%;
     
      @media (min-width: 30em) {
        width: 50%;
      }
     
      @media (min-width: 60em) {
        width: 25%;
      }
    }
     
    .widget2 {
      width: 100px;
     
      @media (min-width: 30em) {
        width: 200px;
      }
    }

這會編譯成:

CSS 代碼:

    .widget1 { width: 100%; }
     
    @media (min-width: 30em) {
      .widget1 { width: 50%; }
    }
     
    @media (min-width: 60em) {
      .widget1 { width: 25%; }
    }
     
    .widget2 { width: 100px; }
     
    @media (min-width: 30em) {
      .widget2 { width: 200px; }
    }

爲了減小文件大小以及(儘可能)提升解析時間,MQPacker 會將多個聲明打包到一個 @media 規則中,也就是

CSS 代碼:

    .widget1 { width: 100%; }
    .widget2 { width: 100px; }
     
    @media (min-width: 30em) {
      .widget1 { width: 50%; }
      .widget2 { width: 200px; }
    }
     
    @media (min-width: 60em) {
      .widget1 { width: 25%; }
    }

可靠情報:確保你的代碼中第一個媒體查詢聲明按照你所想的順序定義了所有可能的選項,即使沒有實際的不同。這能保證 MQPacker 會以正確的順序定義規則。

MQPacker 也提供了選項來排序媒體查詢與輸出 sourcemap。

cssnano

cssnano 會壓縮你的 CSS 文件來確保在開發環境中下載量儘可能的小。通過下面的命令安裝它:

CommandLine 代碼:

    npm install --save-dev cssnano

這個插件通過移除註釋、空白、重複規則、過時的瀏覽器前綴以及做出其他的優化來工作,一般能減少至少 50% 的大小。還有很多其它選擇,但 cssnano 是其中最好的一個。使用它!

PostCSS Sprites

Postcss-sprites 將掃描你CSS中使用的所有圖像,自動生成優化的 Sprites 圖像和 CSS Sprites 代碼

CSS 代碼:

    .rss{
      background: url(../img/icons/social-rss.png);
    }
     
    .twitter{
      background: url(../img/icons/social-twitter.png);
    }
     
    /* 將成爲 */
    .rss{ background-image: url(../img/sprite.png); background-position: 0 0; width: 30px; height: 30px;
    }
     
    .twitter{ background-image: url(../img/sprite.png); background-position: -30px 0; width: 30px; height: 30px;
    }

當然,可以配置如何使用它們,並且告訴他忽略某些圖像。

JavaScript 代碼:

    require('postcss-sprites')({
      stylesheetPath: './css',
      spritePath: './img/sprite.png',
      retina: true,
      outputDimensions: true,
      filterBy: function(image){
        return /icons/gi.test(image.url)
      }
    }),

其他插件

還有其他實用的 PostCSS 插件可以在開發中使用。如 postcss-stylelint 用來檢查 CSS 中可能存在的格式問題。cssnano 用來壓縮 CSS 代碼。postcss-font-magician 用來生成 CSS 中的 @font-face 聲明。precss 允許在 CSS 中使用類似 SASS 的語法。

開發 PostCSS 插件

雖然 PostCSS 已經有 200 多個插件,但在開發中仍然可能存在已有插件不能滿足需求的情況。這個時候可以開發自己的 PostCSS 插件。開發插件是一件很容易的事情。每個插件本質只是一個 JavaScript 方法,用來對由 PostCSS 解析的 CSS AST 進行處理。

每個 PostCSS 插件都是一個 NodeJS 的模塊。使用 postcss 的 plugin 方法來定義一個新的插件。插件需要一個名稱,一般以“postcss-”作爲前綴。插件還需要一個進行初始化的方法。該方法的參數是插件所支持的配置選項,而返回值則是另外一個方法,用來進行實際的處理。該處理方法會接受兩個參數,css 代表的是表示 CSS AST 的對象,而 result 代表的是處理結果。代碼清單 22 中給出了一個簡單的 PostCSS 插件。該插件使用 css 對象的 walkDecls 方法來遍歷所有的“color”屬性聲明,並對“color”屬性值進行檢查。如果屬性值爲 black,就使用 result 對象的 warn 方法添加一個警告消息。

如果那還不夠的話,你還可以用 JavaScript 開發你自己的 PostCSS 插件。PostCSS 文檔講解了 如何寫一個插件 並提供了一份參考 API

清單 22. PostCSS 插件示例

JavaScript 代碼:

    var postcss = require('postcss');
     
    module.exports = postcss.plugin('postcss-checkcolor', function(options) {
     return function(css, result) {
       css.walkDecls('color', function(decl) {
         if (decl.value == 'black') {
           result.warn('No black color.', {decl: decl});
         }
       });
     };
    })

代碼清單22中的插件的功能比較簡單。PostCSS 插件一般通過不同的方法來對當前的 CSS 樣式規則進行修改。如通過 insertBefore 和 insertAfter 方法來插入新的規則。

小結

對於 CSS 的處理一直都是 Web 開發中的一個複雜問題,其中一部分來源於 CSS 規範,一部分來源於不同瀏覽器實現帶來的兼容性問題。PostCSS 爲處理 CSS 提供了一種新的思路。通過 PostCSS 強大的插件體系,可以對 CSS 進行各種不同的轉換和處理,從而儘可能的把繁瑣複雜的工作交由程序去處理,而把開發人員解放出來。本文對 PostCSS 及其常用插件進行了詳細介紹,希望可以幫助開發人員提高開發效率。

postcss.parts 上提供了可搜索的 PostCSS 使用文檔, PostCSS 使用文檔 也提供了建議的選項列表。幾乎任何你能想到的 CSS 工作都能找到插件,但注意存在的交叉與重複的問題 —— 例如,cssnext 也包括 Autoprefixer。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章