PostCSS介紹
原文鏈接:http://www.smashingmagazine.com/2015/12/introduction-to-postcss/
轉自:http://www.zcfy.cc/article/81
CSS的發展與所有語言的發展一樣,都有一個迭代的過程。伴隨着每一個主要版本的發布,我們都可以獲得新的特性和語法幫忙我們更好的完成樣式。CSS3 介紹了很多新的特性,可以讓我們設計交互,之前我們都是通過javascript來實現交互。每一天都會有新工具出現,讓我們可以更靈活地表達樣式。
PostCSS就是最近才出現的這么一個工具PostCSS。PostCSS的目標是通過自定義插件和工具這樣的生態系統來改造CSS。與Sass和Less這些預編譯器相同的原則,PostCSS把擴展的語法和特性轉換成現代的瀏覽器友好的CSS。
如何實現?JavaScript。
JavaScript轉換我們的樣式比其他處理器快。使用Gulp或Grunt的task-runner工具,我們可以通過構建過程轉換樣式,就像Sass和Less的編譯。像React和AngularJS這樣的庫和框架,允許我們可以在JavaScript中直接寫CSS,為我們的樣式打開了一扇使用JavaScript轉換的大門。
PostCSS的歷史
PostCSS作為使用JavaScript處理CSS的方法被推出,它的開發者是Andrey Sitnik, Autoperfixer的作者。PostCSS本身只是一個API,當使用其龐大的插件生態系統時,可以為我們提供強大的處理能力。生成的Source maps可以方便我們的調試,抽象語法樹(AST)的存在可以幫忙我們理解代碼是如何被轉換的。
由於PostCSS使用Node.js框架,無論語言還是工具可以按需修改和定制。其他工具如Sass和LESS就會因為系統能力的限制,只可以使用編譯器可用的方法。
由於其使用的API,PostCSS允許我們為可能需要的任何功能,創建自定義的插件和工具。模塊化平台的設計使得工具中立,使得我們只需要關注項目需要的功能。PostCSS對語言格式不關心,接受不同預處理器的語法風格,像Sass和LESS,如果有必要的話。
模塊化的好處
大多數開發人員很少從頭開始一個項目。很多都是以Sass模板開始,在指定項目中使用Sass模板提供的variables,mixins,functions。我們為functions,mixins,表格系統,通用工具提代獨立的樣式表,從而使開發更容易。到了最后,我們最終會有10個或更多個樣式文件用來保證開發的條理性。
維護Sass或Less片斷的庫是一個艱巨的任務,會留下一下臃腫的項目。很多項目中沒有用到mixins和funcitons,只是做為"以防萬一"的代碼包含進來。PostCSS很容易安裝,即插即用的模塊,使有獨特需求的項目開發過程更靈活。
PostCSS把我們產品中的樣式表中用來創建funtions,utities和mixins的代碼移出來包裝成插件。現在對於每個項目,我們可以通過構建工具中包含對應插件就可以使用這些工具。
PostCSS FontPath插件就可以見證這種方式的優勢。在使用Sass時,我們可以在文件中包含進一個mixin來自定義網頁字體,因此我們創建了一個@font-face的標簽。
@mixin importfont($font-family,$font-filename,$font-weight:normal,$font-style:normal,$font-stretch:normal){
@font-face{
font-family:'#{$font-family}';
src:url('#{font-filename}.eot');
src:url('#{font-filename}.woff') format('woff'),
url('#{$font-filename}.ttf') format('truetype');
font-weight:$font-weight;
font-style:$font-style;
font-stretch:$font-stretch;
}
}
@include importfont('mission script','fonts/mission-script-webfont',300);
在我們的項目中使用PostCSS FontPath 插件,我們就不再需要像上面那樣包含Sass mixins了。在我們的CSS中寫入下面的代碼,PostCSS會通過Grunt或Gulp把它轉換成我們需要的。
@font-face{
font-family:'My Font';
font-path:'/path/to/font/file';
font-weight:normal;
font-style:normal;
}
在寫這篇文章時,PostCSS已經有超過100個社區插件,允許諸如未來的CSS語法,快捷鍵,工具和語言的擴展。PostCSS除了是一個'酷'的工具,它的用戶群里也有WordPress,谷歌和推特團隊這些重量級的用戶。
添加PostCSS到你的工作流
因為PostCSS是用JavaScript編寫的,我們可以在項目中使用像Gulp和Grunt這樣的Task runner來轉換CSS。下面的教程演示如何把PostCSS使用Gulp或Grunt合並到你的工作流。使用這兩種工具不是至關重要的,這只是個人喜好或哪一個更合適項目的問題。
注意:Gulp和Grunt完整版的工具放在GitHub可用 。你可以隨時使用它做為初始模板,並且可以根據需要擴展它。
使用GULP設置POSTCSS
如果你對Gulp不熟悉,我推薦你閱讀Callum Macrae寫的"基於Gulp構建"做個初步了解,並把這個工具跑起來。
在終端執行npm i gulp-postcss -D
命令,在你的項目中安裝PostCSS模塊。
在項目下的Gulpfile.js
中請求我們安裝的PostCSS模塊,然后在任務中使用它。在這里,一定要更新開發文件的路徑和輸出轉換文件的目錄。
var postcss = require('gulp-postcss');
gulp.task('styles',function(){
return gulp.src('path/to/dev/style.css')
.pipe(postcss([]))
.pipe(gulp.dest('path/to/prod'))
});
在命令行輸入gulp styles
執行該任務。
使用GRUNT設置POSTCSS
注意:如果你對Grunt不熟悉,我推薦你通過閱讀Mike Cunsolo寫的"Grunt入門和實踐"來熟悉Grunt的使用。
在終端執行npm i grunt-postcss -D
命令,在你的項目中安裝PostCSS模塊。
一旦在系統里安裝了該插件,你就可以像下面這樣,使用它在Gruntfile里創建一個任務了。一定記得更新cwd
和dest
的值來反映你的應用程序結構。
module.exports = function(grunt){
grunt.initConfig({
pkg:grunt.file.readJSON('package.json'),
styles:{
options:{
processors:[]
},
dist:{
files:[{
expand:true,
cwd:'dev/',
src:['**/*.css'],
dest:'prod/'
}]
}
}
});
// 加載post-css
grunt.loadNpmTasks("grunt-postcss");
};
在命令行輸入grunt styles
執行該任務。
安裝插件
使用PostCSS自己並不完全是強大的,它的強大依賴於插件。你可能已經注意到在上面Gulp和Grunt的實現中,任務聲明中有空的數組。在這些數組中我們可以引入社區開發的PostCSS插件。
核准的PostCSS插件列表可以在PostCSS GitHub頁 查看,這些插件像所有的NPM包一樣,可以通過命令行安裝。許多插件只能做為PostCSS的擴展,對於你使用的構建工具是不可知的。比如,我們將要安裝的PostCSS Focus 插件,它將為每一個hover狀態添加:focus
。
下面例子中使用的所有插件,我們需要使用命令行和NPM在我們的項目中安裝這些包文件。
POSTCSS插件安裝示例
npm i postcss-focus -D
插件可以直接傳遞到方法;然而,為了代碼的整潔,我們可以構造一個數組作為參數將其傳遞給方法。在這個數組里,我們包含必要的require
語句,該語句返回插件,接着立即調用返回的插件。如果你想深入了解這個概念,推薦閱讀Ryan Christiani寫的Functions as First-Class Citizens in JavaScript這篇文章。
require('postcss-focus')()
Grunt使用新創建的processorArray
后的代碼,如下:
var processorArray = [
require('postcss-plugin')()
];
// Snipped for brevity
styles:{
options:{
processors:processorArray
},
dist:{
src:'path/to/dev/style.css',
dest:'path/to/prod/style.css'
}
}
Gulp修改后的代碼如下:
var processorArray = [
require('postcss-plugin')()
];
gulp.task('styles',function(){
gulp.src('path/to/dev/style.css')
.pipe(postcss(processorArray))
.pipe(gulp.dest('path/to/prod'))
});
插件
一旦我們安裝一個插件和構建工具准備編譯代碼,我們就可以使用PostCSS和插件的功能。首先我們要做的是在開發目錄下新建一個.css
擴展的文件。
"等等!一個CSS文件?"沒錯,一個CSS文件。因為使用PostCSS轉換我們的CSS,我們不需要特定的語法,只需要使用傳統的CSS就可以。如果你熟悉預處理器,離開了.sass
,.scss
,.styl
或.less
文件回歸到.css
,你會覺得不自然。但是,事實上,它帶來的不是轉換而是轉變。
我們可以分別執行grunt styles
和gulp styles
使Task runner運行,利用我們新安裝的PostCSS插件來處理我們的樣式。我們的開發樣式文件將通過PostCSS插件被處理,然后輸出到我們指定的生產目錄。
以下是一些值得注意的插件,包括這些插件的安裝和使用說明,在你開始使用PostCSS時會有一些幫助。
自動加前綴
編寫兼容眾多瀏覽器和設備的樣式是一種痛苦,需要添加供應商前綴保持最新的屬性和值更是一種挑戰。所幸,AutoPrefixer 可以找出何時何地需要提供前綴。該插件可以讓我們在樣式中使用新的特性和屬性,為屬性和值添加前綴由它來完成。
這里是如何通過命令行安裝這個插件:
npm i autoprefixer -D
當我們在數組中添加一個插件時,我們需要提供一個對象,該對象提供項目支持的瀏覽器范圍的數組。可以提供的選項列表可以在Browserslist Github Account中查看。
我們在處理器中添加一個Autoprefixer插件
var processorsArray = [
// snipped for brevity
require('autoprefixer')({browsers:['last 2 versions','ie 6-8','Firefox > 20']})
]
根據設定的目標不同,樣式表中相應的CSS屬性和值上會自動加上適當的前綴。
這是開發的CSS:
.item{
display:flex;
flex-flow:row wrap;
}
這里是轉換后的輸出:
.item{
display:-webkit-flex;
display:-ms-flexbox;
display:-webkit-box;
display:flex;
-webkit-flex-flow:row wrap;
-ms-flex-flow:row wrap;
flex-flow:row wrap;
}
利用CSSNEXT使用未來語法
CSS4不久將要來到我們身邊,CSS4將帶來一些新的特性,如本地變量,自定義選擇器 和新的偽類鏈接 。在寫這篇文章時,這些新特性在所有瀏覽器都不支持,但是它們將在現代瀏覽器中實現規范得到了批准。
CSSNext 可以把任意的CSS4特征或屬性轉換成瀏覽器可以解析的CSS3屬性。這個工具可以單獨使用,也可以做為PostCSS的插件使用。我們接着把它也添加到processorsArray
,processorsArray
里已經包含了其他我們需要的PostCSS插件。
通過命令行安裝CSSNext插件,如下:
npm i cssnext -D
(譯者注:cssnext官網正式更名為postcss-cssnext,安裝時請使用npm i postcss-cssnext
,估計是避免與CSSNEXT混淆)
然后將它添加到你的處理器中:
var processorsArray = [
// snipped for brevity
require('cssnext')()
]
現在,在你的生產代碼中可以寫CSS4的特性,PostCSS會通過任務管理器轉換這些語法,從而被今天的瀏覽器支持。再用開發文件中的CSS替換這些轉換后的代碼即可。
這里是開發的CSS:
// 自定義變量
:root{
--linkColour:purple;
}
a{
color:var(--linkColour);
}
// 自定義媒體查詢范圍
@custom-media --only-medium-screen (width>=500px) and (width/
@import "partials/_base.css";
/* 混入(Mixins) */
@define-mixin square $dimension{
width:$dimension;
height:$dimension;
}
/* 嵌套,變量和混入 */
.button{
@mixin square 200px;
background:$green;
&:hover{
background:$blue;
}
}
這里是轉化后的輸出:
.square{
background:#0000ff;
border-radius:10px;
}
.button{
width:200px;
height:200px;
background:#00ff00;
}
.button:hover{
background:#0000ff;
}
如果你想探索CSSNext更多的功能,可以訪問playground 這個網站,在這個網站上你可以嘗試更多CSSNext支持的CSS4特性。
SASS語法
如果Sass是你的首選預處理語言,不用擔心:你可以在PostCSS中使用Sass的語法和Sass的工具。傳統的CSS不支持變量,嵌套和引用,使用插件比如PreCSS 就可以讓我們使用這些特性,這樣我們就可以在傳統的樣式文件中使用Sass的語法。
如果通過命令行將插件添加到構建里,參考上面的演示將該包添加到processorsArray數組里,這樣我們就可以立即使用Sass語法了。如果我們從Sass切換到了PostCSS,你需要把文件的擴展改成.css
,並且在你的Task runner中立即執行。
通過命令行安裝PreCSS,如下:
npm i precss -D
把這個插件添加到你的處理器中:
var processorsArray = [
// snipped for brevity
require('precss')()
];
這里是開發的CSS:
/* 變量 */
$blue:#0000ff;
$green:#00ff00;
$radius:10px;
.square{
background:$blue;
border-radius:$radius;
}
/* 引用 */
@import "partials/_base.css";
/* 混入(Mixins) */
@define-mixin square $dimension{
width:$dimension;
height:$dimension;
}
/* 嵌套,變量和混入 */
.button{
@mixin square 200px;
background:$green;
&:hover{
background:$blue;
}
}
這里是轉化后的輸出:
.square{
background:#0000ff;
border-radius:10px;
}
.button{
width:200px;
height:200px;
background:#00ff00;
}
.button:hover{
background:#0000ff;
}
利用社區插件擴展CSS
PostCSS的能力在於社區插件,插件可以幫忙我們更加有效的編寫代碼。這些插件給我們提供了編寫代碼更快捷的方式,或者至少可以使用更容易的方法來實現創造性的樣式。借助PostCSS API,這些插件允許我們在項目中可以自定義屬性,選擇器和值,便得我們可以更有效的編寫樣式,盡量少的使用搜索。
QUANTITY QUERIES
數量查詢功能非常強大。他們允許我們在CSS中計算元素數量 ,從而基於兄弟元素的數量應用樣式。在今天,你可以在CSS中使用數量查詢,因為數量查詢依賴一些先進的CSS選擇器,所以在寫這些選擇器時有點棘手。在線工具QQ的存在可以幫忙我們完成這樣的查詢,我們也可以在樣式中直接使用PostCSS自定義選擇器。
像其他插件的安裝一樣,使用命令行安裝Quantity Queries插件,如下:
npm i postcss-quantity-queries -D
並且在你的處理器中添加這個插件:
var processors = [
// Snipped for brevity
require('postcss-quantity-queries')()
];
一旦這個插件安裝好,你就可以只通過這個插件自定義選擇器和變量,基於匹配的元素應用樣式了。
這里是開發的CSS:
// "至少"數量的兄弟元素應用樣式
.container > .item:at-least(5){
background:blue;
}
// "最多"數量的兄弟元素應用樣式
.item > a:at-most(10){
color:green;
}
// "范圍"數量的兄弟元素應用樣式
.gallery > img:between(4,7){
width:25%;
}
// "精確提供項"的兄弟元素應用樣式
.profiles:exactly(4){
flex:1 0 50%;
}
這里是轉化后的輸出:
.container > .item:nth-last-child(n+5),
.container > .item:nth-last-child(n+5) ~ .item{
background:blue;
}
.item > a:nth-last-child(-n+10):first-child,
.item > a:nth-last-child(-n+10):first-child ~ a{
color:green;
}
.gallery > img:nth-last-child(n+4):nth-last-child(-n+7):first-child,
.gallery > img:nth-last-child(n+4):nth-last-child(-n+7):first-child ~ img{
width:25%;
}
.profiles:nth-last-child(4):first-child,
.profiles:nth-last-child(4):first-child ~.profiles{
flex:1 0 50%;
}
利用SHORT擴展簡寫屬性
我們在寫樣式時,偶爾會遇到一些屬性的語法讓你說,"應該能短一些"。所幸,Short插件可以幫助我們做到這一點:寫樣式更加有邏輯性。它讓我們可以為position
和size
寫簡寫屬性,就像background
和font
屬性可以凝聚成一個單一的聲明。
通過PostCSS API,簡寫聲明被轉換成瀏覽器易解析的樣式,允許一個簡潔開發樣式表和一個更有組織的生產樣式表。
使用命令行安裝Short:
npm i postcss-short -D
並且在你的處理器中添加這個插件:
var processors = [
require('postcss-short')()
];
text
屬性包括這些輸入屬性:color
,font-style
,font-variant
,font-weight
,font-stretch
,text-decoration
,text-align
,text-rendering
,text-transform
,white-space
,font-size
,line-height
,letter-spacing
,word-spaceing
和font-family
。
這里是開發的CSS:
p {
text:300 uppercase dimgrey center 1.6rem 1.7 .05em;
}
這里是轉化后輸出的CSS:
p{
color:dimgrey;
font-weight:300;
text-align:center;
text-transform:uppercase;
font-size:25px;
font-size:1.6rem;
line-height:1.7;
letter-spaceing:.05em;
}
position
屬性允許top
,left
,'right',bottom
值包含在一個聲明中。值的順序 是順時針方向。語法中取值從1到4,如果有一個值你想排除,只需使用*星號替換即可。
這里是開發的CSS:
section{
position: absolute 10px * *;
}
.topNav{
position: fixed 0 * * 0;
}
.modal{
position: fixed 40% 25%;
}
這里是轉化后輸出的CSS:
section{
position:absolute;
top:10px;
}
.topNav{
position: fixed;
top:0;
left:0;
}
.modal{
position:fixed;
top:40%;
right:25%;
bottom:40%;
left:25%;
}
這對我們的行業意味着什么?
今天使用PostCSS完全有可能獲得實惠。就像編譯Sass和Less,你可以把PostCSS合並到你的工作流中,通過修改Task runner來處理PostCSS。合並的插件像PreCSS允許你將現有的Sass項目移植到PostCSS,而不需要做任何的語法轉化。
本文撰寫之時,關於在什么地方寫CSS最好的討論正在持續。伴隨着React 庫越來越普及,在組件自身內部寫樣式,使用JavaScript直接轉換CSS進行編譯,這種思路正蓄勢待發。雖然這仍然是個討論,但使用PostCSS轉換樣式確實是一種方法。
另一個在行業內掀起波瀾的項目是CSS模塊, 樣式作用范圍在本地文件,需要使用時直接引用該文件。這個概念在JavaScript圈已經非常流行。隨着前端語言之間的界線越來越模糊,比如React和JSX ,CSS和JavaScript結合的能量不容忽視。
PostCSS通過自定義語法和屬性以嶄新方式擴展CSS,它的復雜性也將會為試圖熟悉這個語言的初學者帶來新的挑戰。如果在項目中使用PostCSS的是一位年輕的開發者,請多多鼓勵他深入了解CSS本身,以及理解PostCSS其實與Sass差不多,都是提高樣式編寫效率的工具而已。
今天采用PostCSS
在接下來的幾年里,我們使用CSS的方式將會在許多不同的方面發生改變。每個項目會有不同的需求,我們將不得不調整我們的開發方式。有了PostCSS這樣的模塊化生態系統,我們就可以根據項目需求選擇功能。
我鼓勵你去探索PostCSS的世界,並且探索它所有可用的插件。因為它是一個社區項目,只有人們去使用它並創建新的插件,這個生態系統才會成長壯大。探索更多的插件,可以訪問NPM的availabel packages,也可以在PostCSS Playground中測試插件的功能。