提到css預編譯器(css preprocessor),你可能想到Sass[]以及[Stylus][]。而本文要介紹的PostCSS,正是一個這樣的工具:css預編譯器能夠作到的事,它一樣能夠作到。css
「你說的我都懂,那爲何要用它?」node
若是Sass等預編譯器是新定義了一種模板語言,而後將其轉化爲css的話,[PostCSS][]則是更純粹地對css自己作轉換。web
回想一下你是如何學習使用css預編譯器的:瞭解到有這樣一種能夠轉化爲css的語言,它有不少特性,變量、嵌套、繼承等等,每一種特性都經過必定語法實現。大概就像是遞給你一個已經封裝好的工具箱(量產型?),你能夠在裏面找有用的東西。npm
那PostCSS是怎樣呢?PostCSS就像只遞給你一個盒子,但告訴你你能夠從旁邊的陳列櫃取走本身想要的工具放進盒子打包帶走。若是你以爲陳列櫃裏的不夠好,PostCSS還能夠幫你打造你本身的工具。因此,使用PostCSS,你能夠僅取所需。gulp
這就是PostCSS的模塊化(modular)風格。它做爲一個css轉換工具,自身很小,其全部的轉換功能都是插件,所以能夠個性化配置。數組
PostCSS自身只包括css分析器,css節點樹API,source map生成器以及css節點樹拼接器。瀏覽器
css的組成單元是一條一條的樣式規則(rule),每一條樣式規則又包含一個或多個屬性&值的定義。因此,PostCSS的執行過程是,先css分析器讀取css字符內容,獲得一個完整的節點樹,接下來,對該節點樹進行一系列轉換操做(基於節點樹API的插件),最後,由css節點樹拼接器將轉換後的節點樹從新組成css字符。期間可生成source map代表轉換先後的字符對應關係:sass
比較有意思的是,PostCSS的插件其實都是JavaScript函數,它們使用PostCSS的節點樹API,對css節點樹進行不一樣的轉換。框架
全部插件均可以在[PostCSS的主頁][]中查詢到,這裏只選取一小部分示意一下。編輯器
PostCSS最有名的插件是Autoprefixer[]及你設定的瀏覽器支持範圍,所以至關可靠。下面是一個示例(以我設定的瀏覽器支持範圍):
.container{ display: flex; }
編譯後:
.container{ display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; }
在剛開始使用PostCSS時,我就想到要用PostCSS實現我在Sass中最經常使用的特性。因此,我找到了postcss-nested
和postcss-mixins
。將它們結合起來後,就能夠作到這樣:
@define-mixin clearfix{ &:after{ display: table; clear: both; content: " "; } } .column-container{ color: #333; @mixin clearfix; }
編譯後:
.column-container{ color: #333; } .column-container:after{ display: table; clear: both; content: " "; }
到這裏,你是否已經有了「預編譯器能夠作到的它也能夠作到」的感受呢?
我我的推薦結合Gulp[]的用法。
gulp-postcss
及插件都是[npm][],首先,使用npm install
將它們分別安裝到項目目錄中(會位於node_modules
)。而後,編輯glupfile.js
,將PostCSS註冊爲Gulp的一個任務。如下是一個結合使用了Autoprefixer
、postcss-simple-vars
、postcss-mixins
、postcss-nested
4個插件,且生成source map文件的例子:
var gulp = require("gulp"); var postcss = require("gulp-postcss"); var autoprefixer = require('autoprefixer-core'); var postcssSimpleVars = require("postcss-simple-vars"); var postcssMixins = require("postcss-mixins"); var postcssNested = require("postcss-nested"); var sourcemaps = require("gulp-sourcemaps"); // Css process. gulp.task("postcss", function(){ var processors = [ postcssMixins, postcssSimpleVars, postcssNested, autoprefixer({ browsers: ["Android 4.1", "iOS 7.1", "Chrome > 31", "ff > 31", "ie >= 10"] })]; return gulp.src(["./stylesheets/src/*.css"]) .pipe(sourcemaps.init()) .pipe(postcss(processors)) .pipe(sourcemaps.write(".")) .pipe(gulp.dest("./stylesheets/dest")); });
在上面這段代碼中,processors
是一個數組,定義了用到的PostCSS插件。PostCSS會按照定義順序依次執行插件,所以,在結合多個插件使用時,請注意它們的位置。
此外,你能夠很容易地建立你本身的轉換(還記得前面說過PostCSS的插件都是JavaScript函數吧?)。例如,下面是一個自定義的轉換方法,它將css代碼中的帶有rem
單位的值,更改成px
的值。
var custom = function(css, opts){ css.eachDecl(function(decl){ decl.value = decl.value.replace(/\d+rem/, function(str){ return 16 * parseFloat(str) + "px"; }); }); };
而後,你將這個方法直接添加到processors
中(就像postcssMixins
那些那樣)就可使用。若是原來有值是3rem
,將變成48px
。
以上只是一個簡單的轉換,若是要正式作一個插件,請參考[PostCSS插件指南][]。
PostCSS宣稱,由JavaScript編寫的PostCSS比C++編寫的[libsass][](Sass本來是Ruby編寫的,但後來出了C++的引擎,也就是libsass,它更快)還要快3倍。這裏的具體數字我以爲不用多關心,能夠感覺到「PostCSS的運行速度很快」就足夠了。
實際運行起來大概這樣:
基於PostCSS,能夠作到許多現有的css預編譯器作不到的事。例如,插件系列[cssnext][]可讓你使用CSS4+的語法(增長了變量等許多特性),它會幫你轉化爲目前可用的CSS3。
PostCSS有一個問題,那就是它是零散的,因此我沒法找到一個編輯器能正確地解析並高亮準備使用PostCSS的css代碼。例如在WebStorm中我把它當作普通的css文件,結果就會收到不少紅色的錯誤提示。
固然不會。就像其餘流行的框架和工具那樣,css預編譯器是已經驗證過的可用工具,咱們徹底能夠根據須要選用。
Sass等css預編譯器的特色是成熟可靠。一方面,它們已是流行的模板語言,有完善的文檔和周邊支持,相對穩定,新加入團隊的人也能比較容易地理解。另外一方面,集成的風格有它的方便之處,就像你可能會懶得去組裝一個模型,但能找到專業的人替你完成。
PostCSS的特色則是模塊化。從長遠來看,PostCSS能夠作到更多類型的css轉換。而可定製的風格很是適合追求個性的人(更快捷,並且能夠本身作出頗有趣的插件)。
此外,css預編譯器和PostCSS能夠協同使用。有一個流行的用法就是Sass編譯後再接PostCSS的Autoprefixer
(畢竟這是PostCSS的招牌插件)。
PostCSS的風格能夠說是在打造一個改變css開發方式的生態系統。因此若是說到將來,仍是挺期待的。
(從新編輯自個人博客,原文地址:http://acgtofe.com/posts/2015/05/modular-transforming-with-postcss)