前言
現在的前端,javascript的發展有目共睹,框架林立。同時,html也是齊頭並進,推出了HTML5標準,並且得到了普及。這樣的發展卻唯獨少了一個角色?
CSS,就是這個看似不起眼的傢伙,卻在開發中發揮著和js一樣重要的作用。css,是一種樣式指令碼,好像和程式語言有著一定的距離,我們可以將之理解為一種描述方法。這似乎導致css被輕視了。不過,css近幾年來正在經歷著一次鉅變——CSS Module。我記得js的井噴期應該可以說是node帶來的,它帶來了Module的概念,使得JS可以被工程化開發專案。那麼,今天的css,也將越來越美好。如果你喜歡我的文章,歡迎評論,歡迎Star~。歡迎關注我的github部落格
正文
既然作為一篇PostCSS的文章,我們就應該先來了解一下這是什麼,和我們之前講的CSS Module有啥關係?此處讓我為你們娓娓道來。
我想和你們說再見
目前,在工程化開發中,使用最多的應該就是Less、Sass和Stylus。首先,還是介紹一下它們吧。它們有個統一的名字——css前處理器。何為CSS前處理器?應該就是一種可以將你根據它的規則寫出來的格式轉成css的東西(還是講的通俗一點)。它們的出現可以說是恰逢其時,解決了css的一些缺憾:
- 語法不夠強大,不能夠巢狀書寫,不利於模組化開發
- 沒有變數和邏輯上的複用機制,導致在css的屬性值中只能使用字面量形式,以及不斷重複書寫重複的樣式,導致難以維護。
面對以上問題,css前處理器給出了非常可行的解決方案:
變數:就像其他程式語言一樣,免於多處修改。
- Sass:使用「$」對變數進行宣告,變數名和變數值使用冒號進行分割
- Less:使用「@」對變數進行宣告
- Stylus:中宣告變數沒有任何限定,結尾的分號可有可無,但變數名和變數值之間必須要有『等號』。但需要注意的是,如果用“@”符號來宣告變數,Stylus會進行編譯,但不會賦值給變數。就是說,Stylus 不要使用『@』宣告變數。Stylus 呼叫變數的方法和Less、Sass完全相同。
作用域:有了變數,就必須得有作用域進行管理。就想js一樣,它會從區域性作用域開始往上查詢變數。
- Sass:它的方式是三者中最差的,不存在全域性變數的概念
- Less:它的方式和js比較相似,逐級往上查詢變數
- Stylus:它的方式和Less比較相似,但是它和Sass一樣更傾向於指令式查詢
巢狀:對於css來說,有巢狀的寫法無疑是完美的,更像是父子層級之間明確關係
- 三者在這處的處理都是一樣的,使用「&」表示父元素
有了這些方案,會使得我們可以在保證DPY、可維護性、靈活性的前提下,編寫css樣式。
回到話題中,之所以會出現向前處理器這樣子的解決方案,歸根結底還是css標準發展的滯後性導致的。同時,我們也應該考慮一下,真的只要前處理器就夠了嗎?往往在專案過大時,由於缺乏模組的概念,全域性變數的問題會持續困擾著你。每次定義選擇器時,總是要顧及到其他檔案中是否也使用了同樣的命名。畢竟專案是團隊的,而不是個人的。哪是否有方式可以解決這些問題呢?
前人的方法
對於css命名衝突的問題,由來已久,可以說我們前端開發人員,天天在苦思冥想,如何去優雅的解決這些問題。css並未像js一樣出現了AMD、CMD和ES6 Module的模組化方案。
那麼,回到問題,如何去解決呢?我們的前人也有提出過不同的方案:
- Object-Oriented CSS
- BEM
- SMACSS
方案可以說是層出不窮,不乏有團隊內部的解決方案。但是大多數都是一個共同點——為選擇器增加字首。
這可是一個體力活,你可能需要手動的去編寫長長的選擇器,或許你可以使用預編譯的css語言。但是,它們似乎併為解決本質的問題——為何會造成這種缺憾。我們不妨來看看,使用BEM規範寫出來的例子:
<!-- 正確的。元素都位於 'search-form' 模組內 -->
<!-- 'search-form' 模組 -->
<form class="search-form">
<!-- 在 'search-form' 模組內的 'input' 元素 -->
<input class="search-form__input" />
<!-- 在 'search-form' 模組內的 'button' 元素 -->
<button class="search-form__button"></button>
</form>
<!-- 不正確的。元素位於 'search-form' 模組的上下文之外 -->
<!-- 'search-form' 模組 -->
<form class=""search-block>
</form>
<!-- 在 'search-form' 模組內的 'input' 元素 -->
<input class="search-form__input"/>
<!-- 在 'search-form' 模組內的 'button' 元素 -->
<button class="search-form__button"></button>複製程式碼
每次這樣子寫,估計是個程式設計師,都得加班吧,哈哈!
一種希望
現在的網頁開發,講究的是元件化的思想,因此,急需要可行的css Module方式來完成網頁元件的開發。自從2015年開始,國外就流行了CSS-in-JS(典型的代表,react的styled-components),還有一種就是CSS Module。
本篇談及後者,需要對前者進行了解的話,自行Google即可
對於css,大家都知道,它是一門描述類語言,並不存在動態性。那麼,要如何去形成module呢。我們可以先來看一個react使用postcss的例子:
//example.css
.article {
font-size: 14px;
}
.title {
font-size: 20px;
}複製程式碼
之後,將這些命名打亂:
.zxcvb{
font-size: 14px;
}
.zxcva{
font-size: 20px;
}複製程式碼
將之命名對應的內容,放入到JSON檔案中去:
{
"article": "zxcvb",
"title": "zxcva"
}複製程式碼
之後,在js檔案中運用:
import style from 'style.json';
class Example extends Component{
render() {
return (
<div classname={style.article}>
<div classname={style.title}></div>
</div>
)
}
}複製程式碼
這樣子,就描繪出了一副css module的原型。當然,我們不可能每次都需要手動去寫這些東西。我們需要自動化的外掛幫助我們完成這一個過程。之後,我們應該先來了解一下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.
你可以在使用前處理器的情況下使用它,也可以在原生的css中使用它。它都是支援的,並且它具備著一個龐大的生態系統,例如你可能常用的Autoprefixer
,就是PostCSS的一個非常受歡迎的外掛,被Google, Shopify, Twitter, Bootstrap和CodePen等公司廣泛使用。
當然,我們也可以在CodePen中使用它:
這裡推薦大家看一下PostCSS的深入系列
接下來,我們來看一下PostCSS的配置:
這裡我們使用webpack+postcss+postcss-loader+cssnext+postcss-import的組合。
首先,我們可以通過yarn來安裝這些包:
yarn add --dev webpack extract-text-webpack-plugin css-loader file-loader postcss postcss-loader postcss-cssnext postcss-import複製程式碼
然後,我們配置一下webpack.config.js:
const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
context: path.resolve(__dirname, 'src'),
entry: {
app: './app.js';
},
module: {
loaders: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
options: { importLoaders: 1 },
},
'postcss-loader',
],
}),
},
],
},
output: {
path: path.resolve(__dirname, 'dist/assets'),
},
plugins: [
new ExtractTextPlugin('[name].bundle.css'),
],
};複製程式碼
然後在根目錄下配置postcss.config.js
module.exports = {
plugins: {
'postcss-import': {},
'postcss-cssnext': {
browsers: ['last 2 versions', '> 5%'],
},
},
};複製程式碼
之後,就可以在開發中使用cssnext的特性了
/* Shared */
@import "shared/colors.css";
@import "shared/typography.css";
/* Components */
@import "components/Article.css";複製程式碼
/* shared/colors.css */
:root {
--color-black: rgb(0,0,0);
--color-blue: #32c7ff;
}
/* shared/typography.css */
:root {
--font-text: "FF DIN", sans-serif;
--font-weight: 300;
--line-height: 1.5;
}
/* components/Article.css */
.article {
font-size: 14px;
& a {
color: var(--color-blue);
}
& p {
color: var(--color-black);
font-family: var(--font-text);
font-weight: var(--font-weight);
line-height: var(--line-height);
}
@media (width > 600px) {
max-width: 30em;
}
}複製程式碼
最後使用webpack進行編譯就可以了。
總結
PostCSS,國內還沒有太流行起來,不過相信不久的將來也會逐漸的熱門,並且國內的資源較少,不過最近新出了一本大漠老師們一起翻譯的書——《深入PostCSS Web設計》。有興趣的人也可以去看一下,學習一些前言的東西。本篇也只是大概的寫了一下PostCSS的東西,鑑於國內資源較少,所以參考了一下國外的博文教材,下面會有連結。
如果你對我寫的有疑問,可以評論,如我寫的有錯誤,歡迎指正。你喜歡我的部落格,請給我關注Star~呦。大家一起總結一起進步。歡迎關注我的github部落格
參考連結
PostCSS-modules:
make CSS great again!
PostCSS Deep Dive: What You Need to Know
廣告:聽說寫文章可以得到非同步社群的書,非同步社群作為國內頂尖的IT專業圖書社群,它的書我非常想要,所以我竭力寫了這篇文章,我想要這本書,大家如果覺得好給我點個贊吧^-^