時(shí)間:2023-09-10 18:30:02 | 來源:網(wǎng)站運(yùn)營
時(shí)間:2023-09-10 18:30:02 來源:網(wǎng)站運(yùn)營
CSS預(yù)編譯器三劍客及PostCSS:這篇文章包含兩個部分,第一部分是個CSS預(yù)編譯器:Sass、Less、Stylus,他們之間的對比,第二部分是現(xiàn)在大火的PostCSS。Less & SCSS:.wrap { display: block;}Sass:.wrap display: blockStylus:.wrap display block
Sass最開始通過縮進(jìn),空格,換行的形式來控制層級關(guān)系,寫過Python的同學(xué)一定不會陌生,后來又支持了傳統(tǒng)的類CSS語法的Scss。Less中規(guī)中矩,使用CSS的風(fēng)格,對新手非常友好,也利于現(xiàn)有項(xiàng)目的遷移。Stylus既可以使用Sass風(fēng)格的語法來編寫,也兼容CSS的風(fēng)格。Less:@smallFont: 12px;small { font-size: @smallFont;}Sass:$smallFont: 12px;small { font-size: $smallFont;}Stylus:smallFont = 12pxsmall font-size smallFont
Less:@color: red;.content-1 { color: @color;}@color: black;.content-2 { color: @color;}/* 編譯出來的CSS*/.content-1 { color: black;}.content-2 { color: black;}
Less中的變量,在聲明中使用時(shí),如果出現(xiàn)多次賦值的情況,其會取最后一次賦值的值,這也就是上面的.content-1, content-2中的color都是black的原因?;贚ess中變量的這個特性,我們可以很輕易的改變原有組件庫或者類庫中變量的值,只需要在引入Less文件后,對特定的變量賦值即可。同時(shí)也會帶來一定的隱患:如果不同的組件庫或類庫使用了相同的變量名,那么就會出現(xiàn)覆蓋的情況,所以應(yīng)該采用模塊化的方式。Sass:$color: red;.content-1 { color: $color;}$color: black;.content-2 { color: $color;}Stylus:color = red;.content-1 color colorcolor = black;.content-2 color color;/* 編譯出來的CSS*/.content-1 { color: red;}.content-2 { color: black;}
上面我們可以看到,Sass/Stylus中的變量,如果出現(xiàn)多次賦值的情況,其會取聲明前面最近的一次賦值的值,這就是為什么.content-1的color為red,.content-2的color為black的原因。同時(shí),在Sass/Stylus編寫的不同組件庫或類庫中的變量,不會出現(xiàn)沖突,但是這就為通過覆蓋變量的值來自定義樣式提出了挑戰(zhàn),我們應(yīng)該怎么做呢?考點(diǎn)來了,Sass/Stylus中提供了"不存在即賦值"的變量聲明:Sass:$a: 1;$a: 5 !default;$b: 3 !default;// $a = 1, $b = 3Stylus:a = 1a := 5 b = 3// a = 1, b = 3
細(xì)看代碼,你一定會明白:使用"不存在即賦值"語法,編譯器會檢查前面是否定義了同名變量,如果沒有定義,執(zhí)行變量定義;如果前面定義了同名變量,則不會執(zhí)行這個賦值的操作。因此,我們可以在使用了Sass/Stylus的組件庫或類庫中使用"不存在即賦值"的方式來定義變量,在引入之前定義好需要同名變量,就能達(dá)到目的了。Less:@prefix: ui;@prop: background;.@{prefix}-button { @{prop}-color: red;}Sass:$prefix: ui$prop: background;.#{$prefix}-button{ #{$prop}-color: red;}Stylus:prefix = uiprop = background.{prefix}-button {prop}-color red
變量相關(guān)的內(nèi)容基本上覆蓋到了,接下來就是樣式的復(fù)用了。提到樣式復(fù)用,必定會提到mixin和繼承了。對于mixin,這三個預(yù)編譯器也都有不同的實(shí)現(xiàn)方式:Less:.mixin-style(@color: red) { color: @color;}.content { .mixin-style(red);}Sass:@mixin mixin-style { color: red;}.content { @include mixin-style;}Stylus: mixin-style(color) color color .content mixin-style(red) // or mixin-styls red 透明mixin
在Less中,可以直接引入一個CSS的class作為mixin(這種方式非常不推薦), 同時(shí)也提供上面的能夠傳入?yún)?shù)的mixin;Sass比較中規(guī)中矩,通過@mixin和@include的方式定義和引入mixin;Stylus不需要顯示的聲明mixin,同時(shí)還提供透明mixin的功能,就像屬性一樣引入。Sass/Stylus:.message{ padding: 10px; border: 1px solid #eee;}.warning{ @extend .message; color: #e2e21e;}Less:.message { padding: 10px; border: 1px solid #eee;}.warning { &:extend(.message); color: #e2e21e;}
個中優(yōu)劣,大家可以自己評判。更多詳細(xì)的對比,可以查看顧軼靈大神的文章。PostCSS is a tool for transforming styles with JS plugins. These plugins can lint your CSS, support variables and mixins, transpile future CSS syntax, inline images, and more.所以我的理解是,PostCSS是一個使用JS插件來轉(zhuǎn)換樣式的工具。PostCSS跟CSS預(yù)處理器的定位不同,看了前面的內(nèi)容,大家都知道CSS預(yù)處理器的作用是什么,而PostCSS的作用主要有l(wèi)int css,支持CSS Next語法,自動添加前綴等等功能,通過插件,基本上可以覆蓋CSS 預(yù)處理器的功能,同時(shí)實(shí)現(xiàn)多得多的預(yù)處理器實(shí)現(xiàn)不了的功能。既然PostCSS這么牛逼,那我們來深入研究一下。
.content{ color: red;}
如果我們檢測到某個樣式中有"color: red"這樣一條樣式規(guī)則,需要自動增加"background-color: red"這樣一條規(guī)則。git clone git@github.com:postcss/postcss-plugin-boilerplate.git
node start這個時(shí)候會需要你輸入一些信息,然后就會自動生成一個插件的模板文件夾,還是進(jìn)入到這個對應(yīng)的文件夾下,這個時(shí)候就能看到熟悉的package.json,index.js等文件,使用npm安裝了依賴之后就可以在index.js文件中編寫插件的邏輯了。同樣的,我們可以在項(xiàng)目中通過npm安裝任意依賴,然后在index.js中通過require引入,這就是背靠JavaScript的優(yōu)勢。
var postcss = require('postcss');module.exports = postcss.plugin('postcss-practice', function (opts) { opts = opts || {}; // Work with options here return function (root, result) { // Transform CSS AST here };});
編寫出來的插件代碼是這樣的:const postcss = require('postcss');const postcss = require('postcss');module.exports = postcss.plugin('postcss-practice', function (opts) { opts = opts || {}; console.log(opts); // Work with options here return function (root) { root.walkRules(rule => { console.log(rule.selector); rule.walkDecls(decl => { if ( decl.prop === 'color' && decl.value === 'red' ) { rule.append({ prop: 'background-color', value: 'red' }); } }); }); };});
非常簡單,解釋一下:root.walkRules會遍歷每一個CSS規(guī)則,可以通過rule.selector拿到每一組規(guī)則中的選擇器,然后通過rule.walkDecls遍歷每一組規(guī)則中的樣式聲明, 通過decl.prop,decl.value拿到樣式聲明中的屬性和值。上面判斷屬性是否為'background-color'、值是否為'red',如果滿足條件則向規(guī)則中插入一條新的樣式聲明(這里為了簡單,沒有考慮是否已經(jīng)存在background-color聲明)。var postcss = require('postcss');var plugin = require('./index.js');function run(input, output, opts) { return postcss([ plugin(opts) ]).process(input) .then(result => { expect(result.css).toEqual(output); expect(result.warnings().length).toBe(0); });}// Write tests hereit('does something', () => { return run('a{color: red;}', 'a{color: red;background-color: red;}', {});});
然后是運(yùn)行: "npm run test"的結(jié)果:關(guān)鍵詞:編譯
客戶&案例
營銷資訊
關(guān)于我們
微信公眾號
版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。