PostCSS真的太好用了!

趁你還年輕233發表於2018-12-01

image.png

PostCSS官網有著這樣的對PostCSS特性介紹,箭頭後面是對應功能的外掛及其github地址。

PostCSS是一款使用外掛去轉換CSS的工具,有許多非常好用的外掛,例如autoprefixer,cssnext以及CSS Modules。而上面列舉出的這些特性,都是由對應的postcss外掛去實現的。而使用PostCSS則需要與webpack或者parcel結合起來。 在Parcel中使用PostCSS的方法:新增配置檔案.postcssrc(JSON),.postcssrc.js或者是postcss.config.js。 拿 .postcssrc 檔案來舉例:

{
  "modules": true,
  "plugins": {
    "autoprefixer": {
      "grid": true
    }
  }
}
複製程式碼

Plugins 在 plugins 物件中被指定為 key,並使用物件的值定義選項。如果外掛沒有選項,只需將其設定為 true 即可。 下面我將對根據官方readme的演示demo,對各個外掛進行一一介紹,並新增一些隱藏在外掛背後的知識點的說明。

1.什麼是Autoprefixer?

首先明確一點Autoprefixer是一個根據can i use解析css並且為其新增瀏覽器廠商字首的PostCSS外掛。 不加任何vender prefix的通常寫法。

::placeholder {
    color: gray;
}
複製程式碼

Autoprefixer將使用基於當前瀏覽器支援的特性和屬性資料去為你新增字首。你可以嘗試下Autoprefixer的demo:autoprefixer.github.io/

image
由上圖可以看出,像沒有瀏覽器差異已經完全符合W3C標準的css2.1屬性display,position等,Autoprefixer不會為其加字首,而像css3屬性transform就會為其加字首,其中--webkit是chrome和safari字首,--ms則是ie的字首,像firefox由於已經實現了對transform的W3C標準化,因此使用transform即可。

因此Autoprefixer是一個非常有用的加速前端開發的一個工具,但是它需要基於PostCSS去發揮作用。

如果對vender prefix存疑,可以去看我的這篇部落格:rem / Vender Prefix / CSS extensions

2.什麼是postcss-cssnext?

postcss-cssnext語法input:

:root {
  --fontSize: 1rem;
  --mainColor: #12345678;
  --centered: {
      display: flex;
      align-items: center;
      justify-content: center;
  };
}
body {
    color: var(--mainColor);
    font-size: var(--fontSize);
    line-height: calc(var(--fontSize) * 1.5);
    padding: calc((var(--fontSize) / 2) + 1px);
}
.centered {
    @apply --centered;
}
複製程式碼

瀏覽器可用語法output:

body {
    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);
}
.centered {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-align: center;
        -ms-flex-align: center;
            align-items: center;
    -webkit-box-pack: center;
        -ms-flex-pack: center;
            justify-content: center;
}
複製程式碼

粗略看了一遍演示demo,cssnext.io/playground/… 好用的地方在於通過var()和calc()進行css屬性值的計算,也有@apply這樣的應用大段規則的寫法,也可以藉此去了解一些新的css草案特性;不好用的地方在於有一定的學習成本,而且在前期與webpack,gulp以及parcel進行結合時也需要花費一定時間,並且如果有新的前端組成員加入,必須要掌握這種cssnext的語法。 這樣做有些似乎在嘗試將css變為一種可以進行邏輯處理的語言,但是我個人認為這對於css這樣的靈活的需要具象思維並且需要大量除錯的語言來說,工作中使用cssnext不是一個很好的選擇,但是工作之餘可以作為一個學習新的css草案特性的一個入口,待到納入標準再去使用。

剛開始對自己的想法不確定,因此去看了下前輩們的想法,其中顧鐵靈對cssnext的想法與我的想法如出一轍:

CSS 的轉譯器(transpiler),根據目前仍處於草案階段、未被瀏覽器實現的標準把程式碼轉譯成符合目前瀏覽器實現的 CSS。類似 ES6 的 Babel。 相比之下,Autoprefixer 更加具有實用價值,而 cssnext 實現的功能以後瀏覽器會怎麼實現還存疑,感覺只能玩玩。

3.什麼是postcss-modules?

在看postcss-modules之前,首先要明確的是CSS Modules的這個概念,關於CSS Modules,可以閱讀我翻譯的一篇文章:【譯】什麼是CSS Modules ?我們為什麼需要他們?

postcss-modules則是CSS Modules在PostCSS上的實現外掛,這裡有一篇外掛作者本人寫的介紹postcss-modules的文章:PostCSS-modules:make CSS great again!

在我有限的開發經驗中,只在react中使用過css modules,在vue和angularjs中都沒用到過,而且在react中使用時,不會去用postcss-modules這個外掛,而是使用react-css-modules這個CSS Modules思想在react中的外掛。

下面將給出最簡單的入門例子: 在React上下文中,CSS Modules可能像下面這樣寫:

import React from 'react';
import styles from './table.css';

export default class Table extends React.Component {
    render () {
        return <div className={styles.table}>
            <div className={styles.row}>
                <div className={styles.cell}>A0</div>
                <div className={styles.cell}>B0</div>
            </div>
        </div>;
    }
}
複製程式碼

最後渲染出的元件的標籤會是如下形式:

<div class="table__table___32osj">
    <div class="table__row___2w27N">
        <div class="table__cell___1oVw5">A0</div>
        <div class="table__cell___1oVw5">B0</div>
    </div>
</div>
複製程式碼

如果對為什麼會把class名編譯成table__table___32osj這樣的形式存在疑惑,需要先把css modules搞清楚:【譯】什麼是CSS Modules ?我們為什麼需要他們?

如果需要在開發環境或者生產環境結合webpack去使用,那麼可以閱讀react-css-modules的官方文件尋找答案。

通過這次探索我們可以發現,前端開發在不同的生態,或者說框架體系下,同一個技術,例如CSS Modules這種將思想,會有對應的實現方式,而我們要掌握的,不僅僅是在某種框架下配置使用的方法,而是這種開發思想。因為學習的核心在於學習知識,而不是無休止的學習工具。

4.什麼是stylelint?

這是用來強制開發人員按照團隊css規範寫css樣式的工具,類似eslint。 若想使用,只需要去啟用規則即可。

節選一段stylelint作者博文中的話:

沒錯,你的團隊可能在某個地方的某條純文字wiki中記錄了團隊的程式碼樣式規範。但是,不容忽視的是人的因素:人總是會犯錯——總是在無意之間。 而且即使你很自律地執著遵循某個規範的程式碼風格,但是你沒辦法確保你的同事或是你的開源專案的貢獻者能夠像你一樣。沒有linter的幫助,你必須人工檢查程式碼樣式和錯誤。而機器存在的意義就是代替人來完成能夠自動化實現的任務。linter就是這樣的機器,有了linter,你不需要浪費時間檢查程式碼風格,也不需要對每一個程式碼錯誤都寫一大堆的註釋,因此它能夠極大程度地減少你花費在程式碼審閱上的時間。你無須檢查程式碼究竟做了些什麼,也無需關心它看起來什麼樣。

事實與stylelint作者說的是一樣的,即使團隊有前端開發規範,也會不經意間寫出不符合規範的程式碼,因為每次寫css規則前都去規範check一遍不是誰都能做到的,如果團隊再沒有code review這一關的話,寫出各種各樣風格的css程式碼就是一件必然的事了,短期沒有什麼影響,當專案變得龐大起來,增加新功能或者重寫舊功能將會是一件很痛苦的事。

我們主要去關注Rules部分: sytlelint的規則主要有3類,我將從每一類規則中挑一個拿出來作為示例。

  • Possible errors(常見的錯誤寫法,強烈推薦開啟)

  • Limit language features(棄用一些正確的寫法,中等推薦開啟)

  • Stylistic issues(程式碼風格程式碼統一,普通建議開啟)

  • Possible errors ------ color-no-invalid-hex: 禁止無效的十六進位制顏色 完全形式的十六進位制顏色可以是6或者8(7,8位是透明度的值)個字元。同樣他們的縮寫可以是3或者4個字元。 options : true 下面的程式碼違反規則:

a { color: #00; }
a { color: #fff1az; }
a { color: #12345aa; }
複製程式碼

下面的程式碼符合規則:

a { color: #000; }
a { color: #000f; }
a { color: #fff1a0; }
a { color: #123450aa; }
複製程式碼
  • Limit language features ------ color-no-hex:禁止使用十六進位制顏色 options : true 十六進位制的顏色違反規則:
a { color: #000; }
a { color: #fff1aa; }
a { color: #123456aa; }
複製程式碼

無效的十六進位制色同樣違規:

a { color: #foobar; }
a { color: #0000000000000000; }
複製程式碼

下面的是符合規則的:

a { color: black; }
a { color: rgb(0, 0, 0); }
a { color: rgba(0, 0, 0, 1); }
複製程式碼
  • Stylistic issues ------ color-hex-case: 自動將十六進位制色轉換為大寫或者小寫 Options string: "lower"|"upper" 可以使用stylelint "foo/*.css" --fix實現同樣的功能。 "小寫" 下面的程式碼是違規的:
a { color: #FFF; }
複製程式碼

下面的是符合規則的:

a { color: #000; }
a { color: #fff; }
複製程式碼

"大寫" 下面的程式碼是違規的:

a { color: #fff; }
複製程式碼

下面的是符合規則的:

a { color: #000; }
a { color: #FFF; }
複製程式碼

更多的stylelint的規則可以查閱:github.com/stylelint/s…

5.什麼是LostGrid?

Lost Grid是一個強大的PostCSS網格系統,可與任何前處理器甚至是原生CSS一起使用。 在這裡有非常好的demo展示:lostgrid.org/lostgrid-ex…

節選2個展示進行說明。

.ColumnSection__grid div {
    lost-column: 1/1;
}
@media (min-width: 400px) {
    .ColumnSection__grid div {
        lost-column: 1/3;
    }
}
@media (min-width: 900px) {
    .ColumnSection__grid div {
        lost-column: 1/6;
    }
}
複製程式碼

大於900px時:

image
小於900px時:
image

.NestingSection__grid {
    background: #8eb19d;
}

.NestingSection__grid div {
    background: #7ba48d;
    lost-column: 1/3;
}
.NestingSection__grid div div {
    background: #68977c;
    lost-column: 1/2;
}
複製程式碼

image

經過檢視css樣式我們發現,其實就是巧用了table佈局,before/after偽元素,以及css選擇器,以及border-box佈局,但其實最最核心的地方還是在於很好的使用了css本身具有的流式佈局以及BFC,針對各種情況,在外掛內部使用了大量的樣式進行約束。

image

在css3的flex佈局和grid佈局逐漸被瀏覽器所支援的今天,我個人建議不使用LostGrid外掛。

期待和大家交流,共同進步,歡迎大家加入我建立的與前端開發密切相關的技術討論小組:

努力成為優秀前端工程師!PostCSS真的太好用了!

相關文章