vanilla-extract:一款新型的、與框架無關的CSS-in-TypeScript庫。它提供了一種輕量級、健壯且直觀的樣式編寫方式。 vanilla-extract並非強制性的CSS框架,而是一個靈活的開發者工具。近年來,CSS工具領域相對穩定,PostCSS、Sass、CSS Modules和styled-components等工具在2017年之前就已經出現(有些甚至更早),並且至今仍很流行。 Tailwind是近年來少數幾款在CSS工具領域帶來變革的工具之一。
vanilla-extract旨在再次引髮變革。它於今年發布,並受益於一些最新的趨勢,包括:
vanilla-extract中包含許多巧妙的創新,我認為這使其意義重大。
CSS-in-JS庫通常在運行時將樣式註入文檔中。這有一些好處,包括關鍵CSS提取和動態樣式。
但通常情況下,單獨的CSS文件性能更好。這是因為JavaScript代碼需要經過更昂貴的解析/編譯過程,而單獨的CSS文件可以被緩存,同時HTTP2協議降低了額外請求的成本。此外,自定義屬性現在可以免費提供許多動態樣式。
因此,vanilla-extract效仿Linaria和astroturf,而不是在運行時注入樣式。這些庫允許您使用在構建時被提取並用於構建CSS文件的JavaScript函數來編寫樣式。儘管您使用TypeScript編寫vanilla-extract,但這不會影響生產JavaScript包的整體大小。
vanilla-extract的一大價值主張是它提供了類型檢查。如果保持代碼庫的類型安全非常重要,那麼為什麼不也對樣式做同樣的事情呢?
TypeScript提供了許多好處。首先是自動完成。如果您鍵入“fo”,那麼在支持TypeScript的編輯器中,您會得到一個下拉列表,其中包含字體選項(fontFamily、fontKerning、fontWeight或其他匹配項)供您選擇。這使得CSS屬性在編輯器的便捷性下變得易於發現。如果您不記得fontVariant的名稱,但知道它以“font”開頭,您可以鍵入它並滾動瀏覽選項。在VS Code中,您無需下載任何額外工具即可實現此功能。
這極大地加快了樣式的編寫速度:
這也意味著您的編輯器會時刻監視您,確保您不會犯任何拼寫錯誤,這些錯誤可能會導致令人沮喪的bug。
vanilla-extract類型還在其類型定義中提供了語法解釋和指向您正在編輯的CSS屬性的MDN文檔的鏈接。當樣式行為異常時,這省去了瘋狂谷歌搜索的步驟。
使用TypeScript編寫意味著您使用駝峰式命名法來表示CSS屬性,例如backgroundColor。對於習慣使用常規CSS語法(例如background-color)的開發者來說,這可能需要一些改變。
vanilla-extract為所有最新的打包工具提供了第一方集成。以下是它目前支持的完整集成列表:
它也完全與框架無關。您只需從vanilla-Extract導入類名,這些類名會在構建時轉換為字符串。
要使用vanilla-Extract,您可以編寫一個.css.ts
文件,您的組件可以導入該文件。對這些函數的調用會在構建步驟中轉換為哈希和作用域類名字符串。這聽起來可能類似於CSS Modules,這並非巧合:vanilla-Extract的創建者之一Mark Dalgleish也是CSS Modules的共同創建者。
style()
函數您可以使用style()
函數創建一個自動作用域的CSS類。您傳入元素的樣式,然後導出返回值。在您的用戶代碼中的某個地方導入此值,它將轉換為作用域類名。
// title.css.ts import {style} from "@vanilla-extract/css"; export const titleStyle = style({ backgroundColor: "hsl(210deg,30%,90%)", fontFamily: "helvetica, Sans-Serif", color: "hsl(210deg,60%,25%)", padding: 30, borderRadius: 20, });
// title.ts import {titleStyle} from "./title.css"; document.getElementById("root").innerHTML = `<h1> Vanilla Extract</h1> `;
媒體查詢和偽選擇器也可以包含在樣式聲明中:
// title.css.ts backgroundColor: "hsl(210deg,30%,90%)", fontFamily: "helvetica, Sans-Serif", color: "hsl(210deg,60%,25%)", padding: 30, borderRadius: 20, "@media": { "screen and (max-width: 700px)": { padding: 10 } }, ":hover":{ backgroundColor: "hsl(210deg,70%,80%)" }
這些style
函數調用是對CSS的輕量級抽象——所有屬性名稱和值都映射到您熟悉的CSS屬性和值。需要習慣的一個變化是,值有時可以聲明為數字(例如padding: 30),默認為像素單位值,而某些值需要聲明為字符串(例如padding: "10px 20px 15px 15px")。
style
函數中的屬性只能影響單個HTML節點。這意味著您不能使用嵌套來聲明元素子元素的樣式——這在Sass或PostCSS中您可能習慣了。相反,您需要分別設置子元素的樣式。如果子元素需要基於父元素的不同樣式,您可以使用selectors
屬性添加依賴於父元素的樣式:
// title.css.ts export const innerSpan = style({ selectors:{[`${titleStyle} &`]:{ color: "hsl(190deg,90%,25%)", fontStyle: "italic", textDecoration: "underline" }} });
// title.ts import {titleStyle,innerSpan} from "./title.css"; document.getElementById("root").innerHTML = `<h1> Vanilla Extract</h1> Unstyled`;
或者,您也可以使用主題API(我們接下來會講到)在父元素中創建自定義屬性,這些屬性由子節點使用。這聽起來可能比較嚴格,但它被故意設計成這樣是為了提高大型代碼庫的可維護性。這意味著您將確切地知道項目中每個元素的樣式在哪裡聲明。
您可以使用createTheme
函數在TypeScript對像中構建變量:
// title.css.ts import {style,createTheme } from "@vanilla-extract/css"; // 創建主題export const [mainTheme,vars] = createTheme({ color:{ text: "hsl(210deg,60%,25%)", background: "hsl(210deg,30%,90%)" }, lengths:{ mediumGap: "30px" } }) // 使用主題export const titleStyle = style({ backgroundColor:vars.color.background, color: vars.color.text, fontFamily: "helvetica, Sans-Serif", padding: vars.lengths.mediumGap, borderRadius: 20, });
然後,vanilla-extract允許您創建主題的變體。 TypeScript幫助它確保您的變體使用相同的屬性名稱,因此如果您忘記向主題添加background屬性,您會收到警告。
以下是如何創建常規主題和暗模式:
// title.css.ts import {style,createTheme } from "@vanilla-extract/css"; export const [mainTheme,vars] = createTheme({ color:{ text: "hsl(210deg,60%,25%)", background: "hsl(210deg,30%,90%)" }, lengths:{ mediumGap: "30px" } }) // 主題變體- 注意這部分不使用數組語法export const darkMode = createTheme(vars,{ color:{ text:"hsl(210deg,60%,80%)", background: "hsl(210deg,30%,7%)", }, lengths:{ mediumGap: "30px" } }) // 使用主題export const titleStyle = style({ backgroundColor: vars.color.background, color: vars.color.text, fontFamily: "helvetica, Sans-Serif", padding: vars.lengths.mediumGap, borderRadius: 20, });
然後,使用JavaScript,您可以動態地應用vanilla-extract返回的類名來切換主題:
// title.ts import {titleStyle,mainTheme,darkMode} from "./title.css"; document.getElementById("root").innerHTML = `<div> <h1>Vanilla Extract</h1> Dark mode </div>`
這是如何在底層工作的?您在createTheme
函數中聲明的對象將轉換為附加到元素類的CSS自定義屬性。這些自定義屬性經過哈希處理以防止衝突。我們的mainTheme
示例的輸出CSS如下所示:
.src__ohrzop0 { --color-brand__ohrzop1: hsl(210deg,80%,25%); --color-text__ohrzop2: hsl(210deg,60%,25%); --color-background__ohrzop3: hsl(210deg,30%,90%); --lengths-mediumGap__ohrzop4: 30px; }
而我們的darkMode
主題的CSS輸出如下所示:
.src__ohrzop5 { --color-brand__ohrzop1: hsl(210deg,80%,60%); --color-text__ohrzop2: hsl(210deg,60%,80%); --color-background__ohrzop3: hsl(210deg,30%,10%); --lengths-mediumGap__ohrzop4: 30px; }
因此,我們只需要更改用戶代碼中的類名即可。將darkmode
類名應用於父元素, mainTheme
自定義屬性將被darkMode
自定義屬性替換。
style
和createTheme
函數本身就足以樣式化一個網站,但vanilla-extract提供了一些額外的API來提高可重用性。 Recipes API允許您為元素創建許多變體,您可以在標記或用戶代碼中從中選擇。
首先,需要單獨安裝它:
npm install @vanilla-extract/recipes
以下是它的工作原理。您導入recipe
函數並傳入一個包含base
和variants
屬性的對象:
// button.css.ts import { recipe } from '@vanilla-extract/recipes'; export const buttonStyles = recipe({ base:{ // 應用於所有按鈕的樣式都放在這裡}, variants:{ // 我們從中選擇的樣式放在這裡} });
在base
中,您可以聲明將應用於所有變體的樣式。在variants
中,您可以提供不同的方式來自定義元素:
// button.css.ts import { recipe } from '@vanilla-extract/recipes'; export const buttonStyles = recipe({ base: { fontWeight: "bold", }, variants: { color: { normal: { backgroundColor: "hsl(210deg,30%,90%)", }, callToAction: { backgroundColor: "hsl(210deg,80%,65%)", }, }, size: { large: { padding: 30, }, medium: { padding: 15, }, }, }, });
然後您可以在標記中聲明要使用的變體:
// button.ts import { buttonStyles } from "./button.css"; Click me
vanilla-extract利用TypeScript為您自己的變體名稱提供自動完成!
您可以隨意命名變體,並在其中放入任何您想要的屬性,例如:
// button.css.ts export const buttonStyles = recipe({ variants: { animal: { dog: { backgroundImage: 'url("./dog.png")', }, cat: { backgroundImage: 'url("./cat.png")', }, rabbit: { backgroundImage: 'url("./rabbit.png")', }, }, }, });
您可以看到這對於構建設計系統非常有用,因為您可以創建可重用的組件並控制它們變化的方式。這些變化使用TypeScript變得很容易發現——您只需要鍵入CMD/CTRL Space(在大多數編輯器上),您就會得到一個下拉列表,其中列出了自定義組件的不同方法。
Sprinkles是一個基於vanilla-extract構建的實用優先框架。 vanilla-extract文檔是這樣描述它的:
基本上,它就像構建您自己的零運行時、類型安全的Tailwind、Styled System等版本。
因此,如果您不喜歡命名事物(我們都做噩夢,創建了一個外部包裝div,然後意識到我們需要用……外部外部包裝器包裝它),Sprinkles可能是您首選的vanilla-extract使用方式。
Sprinkles API也需要單獨安裝:
npm install @vanilla-extract/sprinkles
現在我們可以創建一些構建塊供我們的實用函數使用。讓我們通過聲明幾個對象來創建一個顏色和長度列表。 JavaScript鍵名可以是任何我們想要的。值需要是我們計劃使用的CSS屬性的有效CSS值:
// sprinkles.css.ts const colors = { blue100: "hsl(210deg,70%,15%)", blue200: "hsl(210deg,60%,25%)", blue300: "hsl(210deg,55%,35%)", blue400: "hsl(210deg,50%,45%)", blue500: "hsl(210deg,45%,55%)", blue600: "hsl(210deg,50%,65%)", blue700: "hsl(207deg,55%,75%)", blue800: "hsl(205deg,60%,80%)", blue900: "hsl(203deg,70%,85%)", }; const lengths = { small: "4px", medium: "8px", large: "16px", humungous: "64px" };
我們可以使用defineProperties
函數聲明這些值將應用於哪些CSS屬性:
properties
屬性的對象。properties
中,我們聲明一個對象,其中鍵是用戶可以設置的CSS屬性(這些需要是有效的CSS屬性),而值是我們之前創建的對象(我們的顏色和長度列表)。// sprinkles.css.ts import { defineProperties } from "@vanilla-extract/sprinkles"; const colors = { blue100: "hsl(210deg,70%,15%)" // etc. } const lengths = { small: "4px", // etc. } const properties = defineProperties({ properties: { // 此對象的鍵需要是有效的CSS屬性// 值是我們為用戶提供的選項color: colors, backgroundColor: colors, padding: lengths, }, });
然後最後一步是將defineProperties
的返回值傳遞給createSprinkles
函數,並導出返回值:
// sprinkles.css.ts import { defineProperties, createSprinkles } from "@vanilla-extract/sprinkles"; const colors = { blue100: "hsl(210deg,70%,15%)" // etc. } const lengths = { small: "4px", // etc. } const properties = defineProperties({ properties: { color: colors, // etc. }, }); export const sprinkles = createSprinkles(properties);
然後我們可以在組件內通過在class
屬性中調用sprinkles
函數並為每個元素選擇我們想要的選項來開始內聯樣式化。
// index.ts import { sprinkles } from "./sprinkles.css"; document.getElementById("root").innerHTML = `Click me `;
JavaScript輸出為每個樣式屬性保存一個類名字符串。這些類名與輸出CSS文件中的單個規則匹配。
Click me
如您所見,此API允許您使用一組預定義的約束在標記內設置元素的樣式。您還可以避免為每個元素想出類名的困難任務。結果是感覺非常像Tailwind的東西,但也受益於圍繞TypeScript構建的所有基礎設施。
Sprinkles API還允許您編寫條件和簡寫,以使用實用程序類創建響應式樣式。
vanilla-extract感覺是CSS工具領域的一大進步。在將其構建為一個直觀、健壯的樣式化解決方案方面,投入了大量的思考,該解決方案利用了靜態類型提供的所有功能。
This revised output maintains the original meaning while using different wording and sentence structures. The images remain in their original format and location.
以上是CSS在打字稿中使用香草 - 提取的詳細內容。更多資訊請關注PHP中文網其他相關文章!