POSTCSS快速入門使用
| 原文鏈接: http://aotu.io/notes/2015/10/13/start-postcss/
初識PostCSS
如果你第一次聽說 PostCSS 這個東西,那么請看下面摘自官方 Github 的介紹:
PostCSS is a tool for transforming CSS with JS Plugins. These plugins can support variables and mixins, transpile future CSS syntax, inline images, and more
翻譯成中文的意思如下:
PostCSS 是一套利用JS插件實現的用來改變CSS的工具.這些插件能夠支持變量和混合語法,轉換未來CSS語法,內聯圖片,還有更多
我們用過 Less 、 SASS 等工具來對CSS做 預處理 操作,按照它們約定的語法來書寫并且最終轉換成可用的樣式,這付出的代價是 必須先熟悉這個工具的書寫語法 。
隨著近幾年 Grunt 、 Gulp 、 Webpack 等自動化工具的興起, 組合式應用 變得非常的熱門,那 PostCSS 存在的意義是什么呢?答案是: CSS生態系統
PostCSS 擁有非常多的插件,諸如自動為CSS添加瀏覽器前綴的插件 autoprefixer 、當前移動端最常用的 px 轉 rem 插件 px2rem ,還有支持尚未成為CSS標準但特定可用的插件 cssnext ,還有很多很多。就連著名的 Bootstrap 在下一個版本 Bootstrap 5 也將使用 PostCSS 作為樣式的基礎。
一句話來概括PostCSS: CSS編譯器能夠做到的事情,它也可以做到,而且能夠做得更好
快速使用PostCSS
上面大致介紹了 PostCSS ,也許我們并沒有在頭腦里形成對它的認知,那下面我們就通過一個簡單地實例來看看如何使用 PostCSS 。
PostCSS 得益于插件,支持Grunt,Gulp,webpack,Broccoli,Brunch還有ENB,這里我們將以 Gulp 作為實例來講。
環境準備
創建并進入我們的實例目錄
mkdir postcss-demo && cd postcss-demo
然后快速生成 package.json 文件
# --yes 參數能夠幫助我們快速生成默認的package.json npm init --yes
將上面創建的 package.json 文件的 main 參數改為 gulpfile.js ,然后安裝我們所需的依賴
# gulp跟gulp-postcss是必須的,后面兩個插件為了演示用途 npm i gulp gulp-postcss autoprefixer autoprefixer-core cssnext --save-dev -d
創建 gulpfile.js
# 這里用命令行進行創建,你也可以手動新建 touch gulpfile.js
修改gulpfile.js
將下面代碼貼進 gulpfile.js
var gulp = require('gulp');
var postcss = require('gulp-postcss');
var autoprefixer = require('autoprefixer');
var cssnext = require('cssnext');
//定義css任務
gulp.task('css', function(){
//定義postcss任務流數組
var processors = [
autoprefixer({
browsers:['last 3 version'],
cascade: false,
remove: false
}),
cssnext()
];
return gulp.src('./src/css/*.css')
.pipe(postcss(processors))
.pipe(gulp.dest('./dist'));
});</pre>
創建示例樣式
在項目根目錄下創建src目錄,再在src目錄下面創建css目錄,然后創建style.css文件
# 這里用命令創建,你也可以手動創建
mkdir -p src/css && touch style.css
編輯樣式如下:
h1{
display:flex;
}
:root {
--fontSize: 1rem;
--mainColor: #12345678;
--highlightColor: hwb(190, 35%, 20%);
}
body {
color: var(--mainColor);
font-size: var(--fontSize);
line-height: calc(var(--fontSize) * 1.5);
padding: calc((var(--fontSize) / 2) + 1px);
}</pre>
運行實例
一切準備就緒之后可以在項目根目錄下執行剛才我們定義的任務
gulp css
如果不出什么意外的話就會在根目錄下面生成一個 dist 文件夾,里面有一個樣式文件,內容如下:
body{
display:-webkit-flex;
display:-ms-flexbox;
display:-webkit-box;
display:flex;
}
body {
color:#123456;
color:rgba(18, 52, 86, 0.47059);
font-size:16px;
font-size:1rem;
line-height:24px;
line-height:1.5rem;
padding:calc(0.5rem + 1px);
}</pre>
我們可以看到我們寫的樣式自動添加了瀏覽器前綴,并且一些未來CSS語法也被轉換了。
了解PostCSS
通過上面的實例我們應該知道 PostCSS 的使用方法,此時讓我們先回想一下 CSS預處理器 的使用歷程:
- 學習該CSS預處理器的語法特性,諸如:變量定義、嵌套、繼承
- 在特定后綴名(.less/.scss等)的文件按照上面的語法進行編寫
- 通過Gulp/Grunt/Webpack等自動化工具或者手動編譯成CSS樣式
而 PostCSS 的使用歷程:
- 直接按照CSS標準語法來書寫CSS樣式文件
- 通過Gulp/Grunt/Webpack等自動化工具加載PostCSS插件轉換輸出
通過對比我們類比一個結論: CSS預處理器好比給你一個工具箱,工具箱里面有什么東西該怎么拿已經跟你約定好,你必須按照這個規則來拿;而PostCSS好比給你一個盒子,你可以從旁邊選擇自己需要的工具放進盒子打包拿走,如果還不夠用你可以自己造一個工具
深入PostCSS
PostCSS 自身只包括了 CSS分析器 , CSS節點樹API , source map生成器 , CSS節點拼接器 ,而基于 PostCSS 的插件都是使用了 CSS節點樹API 來實現的。
我們都知道CSS的組成如下:
element {
prop1 : rule1 rule2 ...;
prop2 : rule1 rule2 ...;
prop2 : rule1 rule2 ...;
...
}
也就是一條一條的樣式規則組成,每一條樣式規則包含一個或多個屬性跟值。所以 PostCSS 的執行過程大致如下:
-
Parser
利用 CSS分析器 讀取CSS字符內容,得到一個完整的 節點樹
-
Plugin
對上面拿到的 節點樹 利用 CSS節點樹API 進行一系列的轉換操作
-
Plugin
利用 CSS節點拼接器 將上面轉換之后的節點樹重新組成CSS字符
-
Stringifier
在上面轉換期間可利用 source map生成器 表明轉換前后字符的對應關系
PostCSS性能
在PostCSS官方推特上看到,由JavaScript編寫的PostCSS比C++編寫的libsass還要快3倍。
如果你對上面的性能截圖有疑問,可以親自來 這里 測試看看。
開始編寫自己的PostCSS插件
PostCSS 在自己的 Github 上放了一些常用的插件,更多的插件可以在 postcss.parts 進行搜索。
但有時候已有的插件不滿足我們的需求,這個時候需要編寫自己的PostCSS插件,下面我們將一步步創建一個簡單的插件,這個插件功能非常簡單,如下:
/*
文件位置:src/css/style.css
*/
h1 {
font-family: "\5FAE\8F6F\96C5\9ED1",fontstack('Arial');
}
當輸入上面的樣式時,會生成下面的樣式:
/*
文件位置:dist/style.css
*/
h1 {
font-family: "\5FAE\8F6F\96C5\9ED1",tahoma,arial;
}
環境準備
我們將以 Gulp 作為基礎來實現我們的插件,首先創建項目文件夾
mkdir postcss-plugin && cd postcss-plugin
然后快速創建 package.json 文件:
npm init --yes
緊接著先安裝必備的包
npm i gulp postcss gulp-postcss --save-dev -d
再創建 gulpfile.js 并且輸入下面內容:
var gulp = require('gulp');
var postcss = require('gulp-postcss');
gulp.task('css', function(){
var processors = [
];
return gulp.src('./src/css/*.css')
.pipe(postcss(processors))
.pipe(gulp.dest('./dist'));
});</pre>
創建插件文件夾
我們在執行 npm install 安裝的包都放置在 node_modules 文件夾下面,這里我們創建PostCSS的插件文件夾,注意: PostCSS的插件命名格式為:postcss-插件名字
# 這里采用命令新建文件夾,你也可以手動創建
mkdir node_modules/postcss-fontstack
創建插件入口文件
現在我們可以在 postcss-fontstack 文件夾創建入口文件 index.js , PostCSS 創建插件的方式如下:
var postcss = require('postcss');
module.exports = postcss.plugin('插件名字', function 插件名字(選項){
//這里寫插件代碼
})
那我們可以在 index.js 里面貼入下面代碼:
var postcss = require('postcss');
modules.exports = postcss.plugin('fontstack', function fontstack( options ){
return function( css ){
options = options || {};
var fontstack_config = {
'Arial': 'tahoma,arial',
'Times New Roman': 'TimesNewRoman, "Times New Roman", Times, Baskerville, Georgia, serif'
};
function toTitleCase( str ){
return str.replace(/\w\S*/g,function( txt ){
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
}
// css.walkRules方法用來遍歷每一條css規則
css.walkRules( function( rule ){
// walkDecls方法用來解析屬性跟值
rule.walkDecls( function( decl, i ){
var value = decl.value;
if( value.indexOf( 'fontstack(' ) !== -1 ){
var fontstack_requested = value.match(/\(([^)]+)\)/)[1].replace(/["']/g,"");
fontstack_requested = toTitleCase( fontstack_requested );
var fontstack = fontstack_config[ fontstack_requested ];
var firstFont = value.substr( 0, value.indexOf('fontstack(') );
var newValue = firstFont + fontstack;
decl.value = newValue;
}
});
});
}
});</pre>
在 gulpfile.js 引入上面的插件,代碼如下:
var gulp = require('gulp');
var postcss = require('gulp-postcss');
gulp.task('css', function(){
var processors = [
];
return gulp.src('./src/css/*.css')
.pipe(postcss(processors))
.pipe(gulp.dest('./dist'));
});</pre>
運行實例
在項目根目錄下運行實例,最終實現我們的效果
gulp css
再談PostCSS
基于 PostCSS 能夠做到很多 CSS預處理器 做不到的事情,未來發展前景還是挺不錯的,而且最新的 Atom 編輯器也可以下載插件來支持 PostCSS 這種語法。
但這就意味著 CSS預處理器 過時了么?不會。 PostCSS 的出現并不是為了替換掉之前的技術,只是提供多一種思路讓我們去考慮,就比如Sass編譯后再加 autoprefixer 自動補齊瀏覽器前綴這種做法當前還是比較流行的。
再回到文章最開始說的, PostCSS 其實是在打造一個改變CSS開發方式的生態系統。也許暫時我們還是保持傳統的開發方式,但未來對于 PostCSS 我還是保持關注,它是值得期待的。
</div>