PostCSS 簡介

Krystal 8年前發布 | 18K 次閱讀 CSS 前端技術

PostCSS 簡介

CSS 的開發和所有編程語言一樣,是一個迭代的過程。每一次主版本的發布都為我們帶來新的功能和語法,讓我們更好的編寫樣式。CSS 3 支持交互,這之前只能通過 Javascript 來實現。每天都會有新的工具讓我們更簡單、更靈活的實現樣式。

PostCSS 就是最近被推薦的一個樣式處理工具。PostCSS 旨在通過自定義的插件和工具生態體系來重新定義 CSS。與類似 Sass 和 LESS 這樣的預處理機制類似,它可以把擴展的語法和功能轉換成現代的瀏覽器友好的 CSS 代碼。

How you ask? JavaScript.

JavaScript 能做到比其他處理方式更快的轉換我們的樣式。通過 Gulp 或 者Grunt 這樣的 task-runner 工具,我們可以在 build 過程中對樣式進行轉換,這與 Sass 和 LESS 的編譯過程非常類似。React 和 AngularJS 這樣的庫和框架還允許我們在 JavaScript 中直接編寫 CSS 代碼,這為使用 JavaScript 來轉換樣式打開了一扇大門。

PostCSS 的歷史

PostCSS 是 Autoprefixer 的開發者 Andrey Sitnik 開發的,最初是一個通過 JavaScript 來處理 CSS 的方法。PostCSS 本身只是一個 API,不過加上龐大的插件生態體系,作用就非常強大了。為了提供有用的調試功能,PostCSS 還生成了源碼的 map,而且還提供了抽象語法樹(AST)來幫助我們理解代碼是如何被轉換的。

PostCSS 使用的是 Node.js 框架,編程語言和工具的能力使得對 PostCSS 的修改和自定義都很簡單。Sass 和 LESS 則受限于編譯器自身鎖提供的能力。

作為一個 API,PostCSS 讓我們能夠創建任何需要的插件和工具。這種模塊化的平臺設計使得這個工具比較專一,更專注于功能需求。PostCSS 對語言格式不做限制,如果需要也可以使用 Sass 和 LESS 的語法格式。

模塊化的好處

大部分開發者都不是完全從頭開始一個項目的。不少人會使用一個 Sass 模板項目,包含了一些變量、mixin 和函數。我們將使用單獨的樣式文件包含那些函數、mixin、網格體系和通用的工具,這樣可以讓開發更輕松一些。最終我們會有 10 個或更多的樣式文件把一切都組織起來。

維護一個 Sass 或 LESS 代碼片段的庫是非常繁瑣的,也會讓項目變得非常臃腫。很多項目都有未使用的 mixin 和函數,包括那些“以防萬一”的很少使用的代碼。PostCSS 支持易安裝、即插即用的模塊,這對于那些需要特定功能的項目來說,開發過程變得非常靈活。

PostCSS 把項目中所有需要創建函數、工具和 mixin 的代碼提取出來封裝成插件。這樣,對于每一個項目,我們都可以在項目里通過包含插件的方式來引入需要的功能。

這種優勢的一個例子是 PostCSS FontPath 插件。用 Sass 時,我們不能在文件中包含 mixin 來支持 web 字體,所以不得不創建一個 @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 mixin。我們只需要在 CSS 里寫下面的代碼,PostCSS 會通過 Grunt 或 Gulp 轉換成我們需要的代碼。

@font-face {
  font-family: 'My Font';
  font-path: '/path/to/font/file';
  font-weight: normal;
  font-style: normal;}

寫這篇文章的時候,社區里有超過 100 個插件,涉及未來的 CSS 語法、快捷方式、工具、語言擴展等等。它不僅僅是一個工具,從使用的用戶量來說,可以比得上 WordPress、Google 和 推ter。

工作流中加入 PostCSS

PostCSS 是用 JavaScript 寫的,我們可以在代碼里用 Gulp 或者 Grunt 這樣的任務管理器來轉換 CSS。下面的教程演示了如何在項目中使用 Gulp 或 Grunt 的工作流中與 PostCSS進行協作。兩者之間具體選擇哪個并不重要,取決于個人喜好以及是否適合項目。

注意:工具的 Gulp 和 Grunt 版本的列表在 GitHub 上。你可以任選一個作為起始模板,然后安裝自己需要進行擴展。

在 Gulp 里配置 PostCSS

如果你對 Gulp 不太熟悉,建議你先閱讀一下 Callum Macrae 的使用 Gulp 進行構建”來了解和運行這個工具。

在終端運行這個命令可以在項目里安裝 PostCSS 模塊:npm i gulp-postcss -D.

在項目的 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 入門和實踐”,可以讓你對這個工具更了解一些。

在終端運行這個命令可以在項目里安裝 PostCSS 模塊:npm i grunt-postcss -D.

插件安裝完成之后,在 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/'
        }]
      }
    }
  });

  // Load post-css.  grunt.loadNpmTasks('grunt-postcss');};</pre>

在命令行執行 grunt styles 運行這個任務。

安裝插件

PostCSS 自身并不強大;它的強大來自它的插件。也許你已經發現之前 Gulp 和 Grunt 的實現當中,任務說明中的數組是空的。這些數組可以定義我們打算 import 的社區開發的 PostCSS 插件,也就是我們需要包含的那些功能。

PostCSS 的 GitHub 頁面可以找到那些驗證過的插件列表,跟 NPM 的包一樣,這些插件也都可以通過命令行安裝。很多插件只能作為 PostCSS 的擴展,而不能直接在你所用的 task runner 中使用。例如,我們安裝插件 PostCSS Focus 后,會給 hover 增加一個 a:focus 狀態。

接下來的例子里,我們都會使用命令行用 NPM 在我們的項目里安裝包。

PostCSS 插件安裝示例 鏈接

npm i postcss-focus -D

插件可以直接作為方法的參數,不過為了代碼清晰,我們可以構造一個數組,然后把插件放到數組里作為參數。在數組里,我們可以包含所有需要的 require 語句,這些 require 語句會返回插件,然后被立即調用。如果你需要對此有更多的了解,可以看一下 Ryan Christiani 的Javascript 中函數作為一等公民”。

require('postcss-focus')()

對于 Grunt,修改后的代碼如下(包含我們剛創建的 processorArray 數組):

var processorArray = [
    require('postcss-plugin')()];// Snipped for brevitystyles: {
      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'))});

插件

安裝好插件,build 工具也可以編譯我們的代碼后,我們就可以開始使用 PostCSS 及其插件的功能了。首先要做的是在開發目錄下創建一個 .css 為后綴的文件。

“什么!一個 CSS 文件?” 每錯,就是一個 CSS 文件。因為 PostCSS 會幫我們轉換 CSS,所以我們不需要特殊的語法,只需要使用傳統的 CSS。如果你對預處理的機制比較熟悉,你可能會覺得有些不自然,因為我們隱藏了.sass、.scss、.styl 或 .less 文件,又回到了 .css 文件。不過實事是,這并非是改換,而是一種轉換。

為了處理我們剛安裝的 PostCSS 插件的樣式,我們可以分別安照 grunt 和 gulp 的樣式去運行 task runner。CSS 文件將被 PostCSS 以及相應的插件處理,輸出結果會保存到指定的輸出目錄。

下面是一些對你會有幫助的插件的介紹,包含了插件的安裝指導和使用說明。

Autoprefixer

編寫能適用于數量眾多的瀏覽器版本和不同的設備是一件痛苦的事情,要記得哪些屬性需要加哪些前綴就更是一個挑戰。幸運的是,Autoprefixer 可以告訴我們什么時候、在哪里需要添加這些瀏覽器廠商的前綴。這個插件讓我們只需要關注如何使用最新的功能和屬性來編寫樣式,而不用關系這些屬性針對不同的瀏覽器需要添加哪些前綴。

命令行安裝這個插件的方式:

npm i autoprefixer -D

當我們把這個插件加到我們的數組里后,可以提供一個對象,這個對象包含了項目需要支持的瀏覽器的數組。可用的選項列表可以在這里找到:Browserslist Github Account

下面我們就把 Autoprefixer 插件加到 processor 中:

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 很快就會到來,它會帶來一些新的特性,包括本地變量自定義媒體查詢自定義的選擇器 和新的pseudo-links。雖然寫本文的時候 CSS4 還沒有被所有瀏覽器支持,不過它被批準后肯定會被最新的瀏覽器支持的。

CSSNext 可以把所有 CSS4 特性轉換成瀏覽器可以識別的 CSS3 代碼。這個工具可以單獨使用,也可以作為 PostCSS 的一個插件。我們可以將其加到 processorsArray,這個數組包含了其他的 PostCSS 插件。

通過命令行安裝 CSSNext 插件

npm i cssnext -D

然后,添加插件到你的處理器

var processorsArray = [
  // snipped for brevity  require('cssnext')()];

現在,在產品代碼中,你可以寫 CSS4 特性,以及 PostCSS 將通過任務運行器轉換語義,從而支持今日的瀏覽器。當瀏覽器來支持新語義時,你可以通過開發 CSS 來替換轉換的輸出。

在這里開發 CSS:

// Custom Variables
:root {
  --linkColour: purple;}a {
  color: var(--linkColour);}// Custom media queries with ranges@custom-media --only-medium-screen (width >;= 500px) and (width <= 1200px);@media (--only-medium-screen) {
  /* Medium viewport styles */}// Custom selectors@custom-selector :--enter :hover, :focus;@custom-selector :--input input, .input, .inputField;

a:--enter {
  /* Enter styles go here */}:--input {
  /* Input field styles go here */}

這里是轉換后的輸出:

a {
  color: purple;}@media (min-width:500px) and (max-width:1200px){
  body{
    background:#00f;
  }}a:focus,a:hover{
  background:#00f;}.input, .inputField, input{
  background:red;}

如果你想探索更多的 CSSNext 特性,該網站有一個游樂場,你可以嘗試使用當前 CSSNext-supported 的 CSS4 特性。

SaaS 語法

如果 Sass 是你首選預處理的程序語言,別害怕:你可以通過 PostCSS 來使用其語法與工具。然而傳統的 CSS 還不支持諸如 PreCSS 允許我們使用這些特性和在傳統的 CSS 文件中寫 SaaS 語法的變量,嵌套和進口插件。

如果我們在我們的數組中通過命令行和參考包來添加插件到我們的構建,我們可以立即在 Sass 語法中開始編寫。如果你從 Sass 切換到 PostCSS,你可以改變文件擴展到 .css 以及通過任務運行器來輸送。

通過命令行來安裝 PreCSS 插件,像這樣:

npm i precss -D

然后,添加插件到你的處理器:

var processorsArray = [
  // snipped for brevity  require('precss')()];

此外,在這里開發 CSS:

/*Variables*/$blue: #0000ff;$green: #00ff00;$radius: 10px;.square {
  background: $blue;
  border-radius: $radius;}/*Imports*/@import "partials/_base.css";/*Mixins*/@define-mixin square $dimension {
    width: $dimension;
    height: $dimension;}/*Nesting, variables and mixins*/.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,它允許在我們的項目中自定義屬性,選擇器和價值觀,使我們能夠更有效地和使用更少的搜索來編寫樣式。

量查詢

量查詢是強大的。他們允許我們計算元素的 CSS 和基于他們同胞數量之上的應用樣式。雖然選擇器有點難寫,因為他們使用一些先進的 CSS 選擇器,今天您可以在你的 CSS 中使用它們。雖然像 QQ 在線工具的存在是為了幫助我們寫這些查詢,我們可以直接的利用 PostCSS 來使用自定義選擇器的樣式。

通過使用量查詢,以及在像任何其他的項目中安裝插件,通過命令行:

npm i postcss-quantity-queries -D

并將插件添加到你的處理器:

var processors = [
  // Snipped for brevity  require('postcss-quantity-queries')()];

一旦安裝,您可以使用自定義選擇器,僅僅可用于基于匹配的元素應用樣式來通過其插件。

在這里開發 CSS:

// To apply styles if 'at least' number of sibling elements present
.container > .item:at-least(5) {
  background: blue;}

// To apply styles if 'at most' number of sibling elements present
.item > a:at-most(10) {
  color: green;}

// To apply styles if number of sibling items 'between' a range is present
.gallery > img:between(4, 7) {
  width: 25%;}

// To apply styles if 'exactly' number of provided items is present
.profiles:exactly(4) {
  flex: 1 0 50%;}

 然后轉換輸出:

// To apply styles if 'at least' number of sibling elements present
.container > .item:nth-last-child(n+5), .container > .item:nth-last-child(n+5) ~ .item {
  background: blue;}

// To apply styles if 'at most' number of sibling elements present
.item > a:nth-last-child(-n+10):first-child, .item > a:nth-last-child(-n+10):first-child ~ a {
  color: green;}

// To apply styles if number of sibling items 'between' a range is present
.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%;}

// To apply styles if 'exactly' number of provided items is present
.profiles:nth-last-child(4):first-child, .profiles:nth-last-child(4):first-child ~ .profiles {
      flex: 1 0 50%;}

通過 Short 擴展 Shorthand Properties

當我們編寫樣式時,您可能會遇到讓你說,“這可能是更短的。“的語法屬性。 該 Short 插件幫助我們做到那一點:更符合邏輯地編寫我們的樣式。它使我們編寫 shorthand properties forpositionandsize,就像 howbackgroundandfontcan 能用一個簡單的聲明。

通過該 PostCSS API,該 shorthand 聲明被轉換為允許一個清潔發展樣式表和一個更有組織的生產樣式表的 browser-digestible 風格。

通過命令行安裝 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-spacing and font-family.

在這里開發 CSS:

p {
  text: 300 uppercase dimgrey center 1.6rem 1.7 .05em;}

然后轉換輸出:

p {
  color: dimgrey;
  font-weight: 300;
  text-align: center;
  text-transform: uppercase;
  font-size: 25px;
  font-size: 1.6rem;
  line-height: 1.7;
  letter-spacing: .05em;}

該聲明中的 position 屬性允許包括 top, left, right, bottom 值。該值的順序是順時針方向的,在語法中使用 1 到 4 的值。如果有一個在其位置中你愿意排除和僅僅通過一個*的值。

在這里開發 CSS,然后:

section {
  position: absolute 10px * *;}.topNav {
  position: fixed 0 * * 0;}.modal {
  position: fixed 40% 25%;}

然后轉換輸出:

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,以此把 PostCSS 整合到你的工作流程中。在你現有的 Sass 工程中合并一個像 PreCSS 這樣的插件,就可以移植到 PostCSS,你連語法都不用轉換。

就在本文的寫作的同時,一場關于哪里是寫 CSS 的最佳位置的討論正在進行。隨著 React 等庫的流行,在組件內部寫樣式的想法勢頭正猛,它允許我們將樣式與 JavaScript 直接編譯。雖然這還知識是一個討論,但是這的確是一種與使用 PostCSS 進行改動樣式的方案。

另一個在業界引起轟動的項目是 CSS 模塊,它把樣式包含在本地文件中,按需使用。這個概念已經 JavaScript 圈子里流行。并且隨著 React 和 JSX等前端語言之間的界限越來越模糊,CSS 和 JavaScript 的聯合力量變得難以忽視。

當 PostCSS 用新的方式自定義語法和特性來繼承 CSS 的時候,它可能會給那些試著掌握這種語言和它的復雜性的初學者帶來挑戰。如果你和一個中級開發者使用 PostCSS 開發一個項目,盡量鼓勵他們去深入理解這門語言,像 Sass 一樣,PostCSS 是一個簡單的制作工具,它使編寫樣式變得高效。

今天就使用 PostCSS

在接下來的幾年里,我們使用 CSS 的方式將會有許多的改變。每一個項目都有不同的需求,我們需要適應我們的生產方法。使用像 PostCSS 這樣的模塊化生態系統能讓我們選擇和使用我們所需要的特征去完成項目。

我希望你去探索 PostCSS 的世界以及它里面所有可用的插件。因為它是一個社區項目,只有當人們使用它、給它制作插件才會使這個生態系統成長。想要探索更多的插件,可以瀏覽 NPM 上的可用包,并且測試它們的性能在 PostCSS Playground上。

(rb, al, ml)

 本文由用戶 Krystal 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!