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-import
和 tailwindcss/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 思否寫作挑戰賽,歡迎正在閱讀的你也加入。