2023 告別 CSS 預處理工具,徹底擁抱 TailwindCSS

Meathill發表於2023-02-19

CSS 是宣告式語言,很簡單,很好學,但是寫起來很累,所有東西都要寫出來才能生效。複用方面更是無從下手,雖然大家都在不斷總結,但始終沒能找到足夠好用的方案,可以有效改善 CSS 開發。

於是我們只好把視線轉出 CSS 之外,轉投 CSS 預處理工具,Less、SASS(SCSS)、Stylus,引入種種 CSS 不具備的功能,幫助我們改進開發體驗。比如巢狀、函式、迴圈、條件,等等。然而如果你細心觀察,實際上,這幾個工具最近 5、6 年都沒怎麼更新(我說的是功能性),因為該有的都有了,甚至很穩定;其它來自於 CSS 的改進,幾乎跟它們沒什麼關係,也不用更新。

最近幾年,隨著 CSS 發展,一些新特性逐步引入,我覺得這些工具越來越難用,它們能帶來的好處已經無法掩蓋它們所造成的問題。是時候告別 CSS 預處理工具了,就像我們當年告別 jQuery 一樣。

為什麼說預處理工具落後?

我把理由分成三大類:

預處理工具的問題

  • 對 CSS 函式相容性不好,尤其是 rgba()hsl() 這些常用的顏色函式
  • 數值型別轉換,有不符合預期的行為,比如 Stylus 實現 content:5

CSS 的改進

  • CSS 擁有越來越多的函式,可以直接進行計算,比如前面提到的顏色;還有 calc() 來完成基礎數學計算
  • CSS 變數非常好用,可以大大改程序式設計體驗,配合各種 JS 框架,我們可以更容易的把數學邏輯和顯示效果繫結在一起
  • CSS Houdini 可以實現很多新功能,即使不深入使用(JS 部分),也有好用的自定義屬性
  • CSS 也開始從預處理工具吸收營養,比如近期的巢狀功能已經開始被整合,未來我們可以直接使用

預處理工具無法跟進的問題

  • 很多縮寫、複合屬性無法處理,比如 background-image、box-shadow 等,都支援多屬性共同生效,預處理工具擅長的迴圈、條件、函式無法提供幫助。
  • 預處理,顧名思義,發生在生產之前。實際上,網頁在實際瀏覽時,會有很多因素影響到渲染結果,比如解析度、dark mode 等。預處理工具對這些需求也沒有改進。

替代方案

我目前的替代方案基於 TailwindCSS,所以自然包含 PostCSS、AutoPrefixer 等工具。然後用 postcss-import 實現自動匯入和模組化;使用 tailwindcss/nesting 實現巢狀。

為什麼選用 TailwindCSS?首先,實際開發中,不管使用什麼前端框架,我們都需要大量原子化的膠水樣式,比如調整間距、改變字號、給容器新增一些邊框、圓角、陰影等。這些樣式如果都手寫,工作量並不小;學習不同的樣式名也是負擔;以及最重要的,CSS 優先順序問題。使用 TailwindCSS 就都能很好解決。

TailwindCSS 不僅包含一大堆原子化樣式,自身也是個完整且優秀的 CSS 編譯器。它包含 reset,提供一組全域性通用的 CSS 變數;它可以從各種檔案裡把我們用到的樣式提取出來,構建後生成的 CSS 裡只有我們要用到樣式,不會有多餘的;它會分析我們對樣式的使用,合理的調整樣式順序,保證樣式能正確生效。使用 TailwindCSS 可以節省很多時間。

它還自帶若干外掛,比如解決巢狀的 tailwindcss/nesting,支援內容類元素的的 @tailwindcss/typography 等。使用這些外掛也可以幫我們節省很多時間。

最後,TailwindCSS 的生態不斷成長,我們的選擇範圍越來越寬:HeadlessUI、DaisyUI、付費的 Tailwind UI 等。方便我們從產品生命週期的任意階段開始整合。

推薦專案配置

啟動專案的時候,安裝依賴。包含 PostCSS + AutoPrefixer、TailwindCSS 和 DaisyUI。前者提供 CSS 處理框架,包含自動匯入 css 和巢狀功能;後兩者提供可見的 UI。

pnpm i postcss postcss-import tailwindcss autoprefixer daisyui -D

自動初始化配置,-p 會自動生成 PostCSS 配置:

pnpm tailwindcss init -p

調整 postcss.config.js,啟用 postcss-importtailwindcss/nesting。目前我們常用的巢狀規則和 CSS 規範略有區別,不過無所謂,規範也沒確定,所以這樣就足夠了。

// postcss.config.js
module.exports = {
  plugins: {
    'postcss-import': {},
    'tailwindcss/nesting': {},
    tailwindcss: {},
    autoprefixer: {},
  },
}

然後調整 tailwind.config.js

// tailwind.config.js
const DaisyUI = require('daisyui');
// 這個外掛可以幫我們處理檔案類內容,我建議常用
const Typography = require('@tailwindcss/typography');

module.exports = {
  // 從以下檔案查詢用到的樣式
  content: [
    './index.html',
    './src/**/*.{js,ts,jsx,tsx,vue}',
  ],
  theme: {
    extend: {
      // 擴充 TailwindCSS 沒有包含的樣式
    },
  },
  plugins: [
    DaisyUI,
    Typography,
  ],
  daisyui: {
    themes: [{
      // 只構建一個主題: luxury,並覆蓋其中的兩個屬性
      luxury: {
        ...require('daisyui/src/colors/themes')[ '[data-theme=luxury]' ],
        primary: '#FFA028',
        '--bc': '0 0% 87.5%',
      },
    }],
  },
}

然後,建立樣式入口 main.css。其它樣式可以如常寫在這個檔案裡,不過如果要 @import 其它 CSS 檔案,就要進行一些調整。具體可以看官方檔案。

// main.css
@tailwind base;
@tailwind components;
@tailwind utilities;

然後在入口檔案引用 main.css 即可:

// main.js
import './main.css';

至此,新專案配置完成,可以照常開發了。

下期預告

這次我先分享了整體思路:用新的工具鏈替代預處理工具,保證已有的功能不缺失。那麼下期分享的內容就是使用新的 CSS 特性,更好的完成開發。


如果你對新 CSS 感興趣,對預處理工具和新工具鏈有興趣和疑問,歡迎留言討論。如果本文對你有啟發,也請幫我點贊分享,謝謝。


本文參與了SegmentFault 思否寫作挑戰賽,歡迎正在閱讀的你也加入。

相關文章