一起聊聊postcss外掛之自動轉換px到rem

2022-01-27 19:00:46

本篇文章給大家分享postcss的相關知識,postcss是一個通過 js 外掛來轉換 css 的工具,通過這些外掛可以支援變數和混合,可以通過追加瀏覽器字首生成相容性的樣式,希望對大家有幫助。

postcss 是 css 的 transpiler,它對於 css 就像 babel 對於 js 一樣,能夠做 css 程式碼的分析和轉換。同時,它也提供了外掛機制來做自定義的轉換。

這一節,我們通過一個 px 自動轉 rem 的功能來入門一下 postcss 的外掛。

postcss 的原理

postcss 是 css 到 css 的轉譯器,它也和 babel 一樣,分為 parse、transform、generate 3個階段。各種轉換外掛都是工作在 transform 階段,基於 AST 做分析和轉換。

圖片

css 的 AST 比 js 的簡單多了,主要有這麼幾種:

atrule:以 @ 開頭的規則,比如:

@media screen and (min-width: 480px) {
    body {
        background-color: lightgreen;
    }
}

rule:選擇器開頭的規則,比如:

ul li {
 padding: 5px;
}

decl:具體的樣式,比如:

padding: 5px;

比起 js parser 的那幾十種 AST 是不是簡單的多?

這些可以通過 astexplorer.net 來視覺化的檢視

圖片

postcss 外掛的寫法

postcss 外掛是工作在 transform 階段,處理 ast 節點,外掛的形式是這樣的:

const plugin = (options = {}) => {
  return {
    postcssPlugin: '外掛名字',

    Rule (node) {},
    Declaration (node) {},
    AtRule (node) {}
  }
}

外層函數接受 options,返回一個外掛的物件,宣告對什麼節點做處理的 listener,然後在對應的 listener 裡寫處理邏輯就行。

還可以這樣寫:

module.exports = (opts = {}) => {
  return {
    postcssPlugin: '外掛名字',
    prepare (result) {
      // 這裡可以放一些公共的邏輯
      return {
        Declaration (node) {},
        Rule (node) {},
        AtRule (node) {}
      }
    }
  }
}

在 prepare 裡返回各種 listener,這樣比起第一種來,好處是可以存放一些公共的邏輯。

然後可以這樣來執行外掛:

const postcss = require('postcss');

postcss([plugin({
    // options
})]).process('a { font-size: 20px; }').then(result => {
    console.log(result.css);
})

下面我們來寫一個簡易的 px 自動轉 rem 的外掛來練練手。

實戰案例

需求描述

px 是一個固定的長度單位,而裝置視口的尺寸是各種各樣的,我們想通過一套樣式來適配各種裝置的顯示,就需要相對的單位,常用的是 rem。

rem 的本質就是等比縮放,相對於 html 元素的 font-size。

比如 html 的 font-size 設定為 100px,那 1rem 就等於 100px,之後的樣式如果是 200px 就寫為 2rem。

這樣我們只需要修改 html 的 font-size 就可以適配各種螢幕寬度的顯示,具體的單位會做等比縮放。

我們要根據 html 的 font-size 值來把所有的 px 轉換為 rem,一般都是手動來做這件事情的,但比較繁瑣,知道了計算方式之後,完全可以用 postcss 外掛來自動做。

接下來我們就實現下這個 postcss 外掛

程式碼實現

我們搭一下外掛的基本結構,只需要宣告對 Declaration 處理的 listener:

const plugin = (options) => {
    return {
        postcssPlugin: 'postcss-simple-px2rem',
        Declaration (decl) {
           
        }
    }
}

然後要做的就是把 decl 的樣式值中的 px 轉換為 rem,簡單的正則替換就行:

const plugin = (options) => {
    const pxReg = /(\d+)px/ig;
    return {
        postcssPlugin: 'postcss-simple-px2rem',
        Declaration (decl) {
            decl.value = decl.value.replace(pxReg, (matchStr, num) => {
                return num/options.base + 'rem';
            });
        }
    }
}

通過字串的 replace 方法來做替換,第一個引數是匹配的字串,後面的引數是分組,第一個分組就是 px 的值。

計算 px 對應的 rem 需要 1rem 對應的 px 值,可以支援通過 options 來傳入。

然後我們測試下:

postcss([plugin({
    base: 100
})]).process('a { font-size: 20px; }').then(result => {
    console.log(result.css);
})

可以看到,已經正確的做了轉換:

圖片

當然,我們這個外掛只是案例,還不夠完善,要做的完善的話需要更復雜的正則。

總結

postcss 是 css 的 transpiler,就像 babel 是 js 的 transpiler 一樣,而且 postcss 的 AST 只有幾種節點,比較簡單,也可以通過 astexplorer.net 來視覺化的檢視。

postcss 也提供了外掛功能,可以做一些自定義的分析和轉換。

我們實現了簡單的 px 自動轉 rem 的外掛:

rem 是通過等比縮放的方式來達到一套樣式適配不同裝置寬度的顯示的方案,需要做 px 到 rem 的轉換,這件事可以用 postcss 外掛來自動來做。

其實 postcss 外掛的分析和轉換功能還有很多的應用,比如切換主題色,從白到黑,完全就可以用 postcss 自動分析顏色的值,然後做轉換。

postcss 分析和轉換 css 的能力還是很強大很有用的,有很多在業務中的應用場景等你去發掘。

(學習視訊分享:)

以上就是一起聊聊postcss外掛之自動轉換px到rem的詳細內容,更多請關注TW511.COM其它相關文章!