什麼是 PikaCSS
PikaCSS 是一套即時、隨需產生的 atomic CSS-in-JS 引擎,會在建置時期把 CSS-in-JS 樣式定義轉換成 atomic CSS,且沒有任何執行階段負擔。
主要特色
零設定
PikaCSS 內建合理的預設值,開箱即用。安裝套件、加入建置外掛,就能開始撰寫樣式,不需要任何設定檔就能上手。
零執行階段成本
所有 CSS 轉換都發生在建置時期。你的正式環境 bundle 只會包含產生出來的 atomic CSS class,樣式處理沒有任何 JavaScript 執行階段成本。
從 CSS-in-JS 到 Atomic CSS
在 JavaScript 物件裡用熟悉的 CSS 屬性名稱撰寫樣式。PikaCSS 會把每一條宣告轉換成可重複使用的原子 class,結合 CSS-in-JS 的開發體驗與 atomic CSS 的效能優勢。詳情請見 pika() 如何運作。
解決層疊順序衝突
傳統的 atomic CSS 有一個已知問題:當簡寫屬性與個別屬性(longhand)同時使用時(例如 padding 與 paddingTop),輸出順序會決定誰勝出,導致結果難以預測。PikaCSS 會自動解決這個問題,確保個別屬性一定會覆寫對應的簡寫屬性,無論你的宣告順序為何。詳情請見 層疊順序衝突。
強大的外掛系統
透過外掛擴充 PikaCSS,支援 CSS reset、圖示、字型、排版等功能。外掛會掛入引擎的生命週期,用來加入 preflight、shortcut、選擇器與自訂行為。
完全可自訂
設定選擇器、shortcut、變數、關鍵影格、layer、自動完成等項目。引擎的每個面向都能透過引擎設定來自訂。
概念
pika() 如何運作
pika() 函式是核心 API。把一個或多個樣式定義物件傳給它,PikaCSS 就會在建置時期把每一次呼叫替換成產生出來的原子 class 名稱字串。
// 你寫的內容:
const className = pika({ color: 'red', fontSize: '16px' })
// 建置後變成的內容:
const className = 'pk-a pk-b'每一條不重複的 CSS 宣告(color: red、font-size: 16px)都會有自己的原子 class。如果同一條宣告出現在其他地方,就會重複使用同一個 class。
const className = pika({
color: 'red',
fontSize: '16px',
})@layer utilities {
.pk-a {
color: red;
}
.pk-b {
font-size: 16px;
}
}可靜態分析
傳給 pika() 的所有引數,在建置時期都必須是可靜態分析的。這表示你不能用動態值、計算後的運算式,或執行階段的變數當作引數。PikaCSS 需要在建置步驟中擷取樣式,過程中不會執行你的程式碼。
警告
動態值、計算後的運算式,以及執行階段的變數都不能當作 pika() 的引數。請使用 ESLint 外掛 及早抓出違規。若需要由執行階段狀態驅動樣式,請見 動態樣式 中的相關模式:variant map、CSS 變數與 shortcut。
// ✅ 有效:靜態物件常值
pika({ color: 'red' })
// ✅ 有效:字串常值
pika('flex-center')
// ❌ 無效:動態變數
const color = getColor()
pika({ color })
// ❌ 無效:計算後的運算式
pika({ color: isDark ? 'white' : 'black' })
// ❌ 無效:spread 運算子
pika({ ...baseStyles })巢狀選擇器
PikaCSS 支援在樣式定義中使用巢狀選擇器。$ 字元代表產生出來的原子 class 選擇器,讓你可以組合偽類(pseudo-class)、媒體查詢與自訂選擇器。
偽類:用 $: 前綴來加入偽類選擇器:
const className = pika({
color: 'blue',
'$:hover': {
color: 'red',
},
})@layer utilities {
.pk-a {
color: blue;
}
.pk-b:hover {
color: red;
}
}媒體查詢:使用標準的 @media at-rule:
const className = pika({
fontSize: '14px',
'@media (min-width: 768px)': {
fontSize: '16px',
},
'@media (min-width: 1024px)': {
fontSize: '18px',
},
})@layer utilities {
.pk-a {
font-size: 14px;
}
@media (min-width: 768px) {
.pk-b {
font-size: 16px;
}
}
@media (min-width: 1024px) {
.pk-c {
font-size: 18px;
}
}
}自訂選擇器:使用你自己定義的選擇器名稱。這個範例需要先註冊 @dark 選擇器:
// pika.config.ts
import { defineEngineConfig } from '@pikacss/core'
export default defineEngineConfig({
selectors: {
definitions: [
['@dark', 'html.dark $'],
],
},
})const className = pika({
color: 'black',
'@dark': {
color: 'white',
},
})@layer utilities {
.pk-a {
color: black;
}
html.dark .pk-b {
color: white;
}
}層疊順序衝突
在傳統的 atomic CSS 中,當簡寫屬性與個別屬性衝突時,class 在樣式表裡產生的順序會決定哪個屬性勝出。舉例來說,如果 padding: 10px 與 padding-top: 20px 同時存在,樣式表裡最後出現的那個會勝出,但這不一定符合作者的意圖。
PikaCSS 解決的方式是確保個別屬性一定會在對應的簡寫屬性之後才輸出,因此 paddingTop: '20px' 一定會蓋過 padding: '10px',無論你當初寫的順序為何。
const className = pika({
padding: '10px',
paddingTop: '20px',
})@layer utilities {
.pk-a {
padding: 10px;
}
.pk-b {
padding-top: 20px;
}
}