免費體驗 Gpt4 plus 與 AI作圖神器,我們出的錢 體驗地址:體驗
使用 Tailwind css,我避免了在 React 項目中復(fù)制大量 CSS 文件的麻煩,使網(wǎng)頁開發(fā)變得更加迅速高效。雖然 Tailwind 已經(jīng)非常優(yōu)秀,但我還是發(fā)現(xiàn)了一些技巧,可以進(jìn)一步提升使用這個框架的體驗。
IDE 設(shè)置
智能提示擴(kuò)展
Tailwind 智能提示是一款適用于 VSCode 和 JetBrains(如 IDEA 和 Webstorm)的擴(kuò)展。它提供自動補(bǔ)全功能,便于在 html 元素上編寫類,并可訪問 Tailwind 配置。若您忘記了定義的顏色名稱,它還能幫助您快速選取。
下載鏈接如下:
VSCode 版本:https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss。
IDEA 和 Webstorm 版本:https://plugins.jetbrains.com/plugin/15260-tailwind-intellisense。
或者在代碼編輯器的擴(kuò)展市場中搜索即可。
Prettier 插件
在給元素編寫許多類名時,有時會變得難以管理,難以區(qū)分哪些是自定義的,哪些用于響應(yīng)式布局,以及哪些樣式應(yīng)該為了更好的理解而分組。比如,在編寫一堆樣式時,突然想起忘記為 flexbox
設(shè)置間隙,需要將其復(fù)制并粘貼到代碼的不同位置。這種情況對我來說需要過多的思考。
為解決此類問題,Tailwind 團(tuán)隊推出了一個 Prettier 插件來為我們整理代碼。使用它,只需運行:
npm i -D prettier prettier-plugin-tailwindcss
要使其工作,如果您之前沒有使用過 prettier,請安裝官方擴(kuò)展,并配置一些您喜歡的快捷鍵來格式化文檔:
如果你安裝了 eslint,可能想將默認(rèn)格式化程序更改為它。為此,請按 CTRL + Shift + P,選擇“使用格式化文檔”,然后選擇“配置默認(rèn)格式化程序”,并從列表中選擇 prettier。如果您之前使用了一些 eslint 選項,可以在 Prettier 的官方網(wǎng)站上閱讀如何將這些規(guī)則與 prettier 集成。
這個插件的排序順序如下:
- Tailwind 中未定義的類名,即用戶自定義的類名
- Tailwind 中的寬度、彈性布局等其他樣式,按其重要性排序
- 媒體查詢和懸停效果
配置我們的項目
當(dāng)剛安裝 Tailwind 時,您可能會運行以下命令:
npx tailwindcss init -y
這會生成 Tailwind 配置文件。如果正確探索并填寫它,它將非常有用!
逆向媒體查詢
在開始任何 Tailwind 項目之前,首先要做的兩件最重要的事情是:
使用逆向媒體查詢。
制作響應(yīng)式網(wǎng)站通常有兩種基本方法:移動端優(yōu)先和桌面端優(yōu)先:
第一種方法首先從制作移動視圖開始,然后調(diào)整至桌面視圖,而另一種則恰好相反。
默認(rèn)情況下,Tailwind 基于第一種方法,這就是為什么它的所有基本媒體查詢都是 min-width 類型的,意味著需要在某個斷點以下定義樣式,然后使用 md 和其他變體類進(jìn)行更改。
對我來說,這個決定有些麻煩,因為我習(xí)慣于從桌面視圖開始制作網(wǎng)站。如果你和我一樣,有一個小技巧可以使 Tailwind 按我們想要的方式工作,只需將以下內(nèi)容添加到配置文件的 theme 中:
screens: {
'2xl': {'max': '1535px'},
// => @media (max-width: 1535px) { ... }
'xl': {'max': '1279px'},
// => @media (max-width: 1279px) { ... }
'lg': {'max': '1023px'},
// => @media (max-width: 1023px) { ... }
'md': {'max': '767px'},
// => @media (max-width: 767px) { ... }
'sm': {'max': '639px'},
// => @media (max-width: 639px) { ... }
}
完成后,所有斷點都將從特定寬度開始工作,我們不需要反向思考了!
使用任意 REM 值
你可能已經(jīng)知道,CSS 中有許多單位用來定義大小,如 pt、px、cm、em、rem 等。對我來說,這些單位中最有價值的是 rem。rem 的默認(rèn)大小是 16px,即 HTML document的默認(rèn)大小,這意味著當(dāng)用戶在瀏覽器中更改縮放比例時,我們的document 也會相應(yīng)放大。
但你可能會問,當(dāng)需要將所有 Figma 設(shè)計轉(zhuǎn)換為這些值并花費大量時間時,如何使用這些值呢?為此,我們可以在主 CSS 文件中這樣定義基本字體大小:
html {
font-size: 62.5%
}
從基本的 16 像素出發(fā),62.5% 實際上是 10px。有了它,我們可以簡單地將所有像素值除以 10,所以 100 變成 10,123 變成 12.3,0.523 變成 0.0523 —— 您需將小數(shù)點向左移動一位 —— 很簡單!
那么,這與我們的 Tailwind 之旅有何關(guān)系呢?你可能已經(jīng)注意到,將預(yù)定義的 Figma 項目轉(zhuǎn)換為即時網(wǎng)站非常痛苦,因為盡管基本的 Tailwind 類非常周到,幾乎適合所有設(shè)計,但找到每一個類都需要一些時間和思考。例如,我們在 Figma 設(shè)計中有一個 20px 的大小 —— 我們可以去 Tailwind 文檔中找到相應(yīng)的類,或者我們可以直接寫:
class="px-[2rem]"
將值鎖定在方括號中意味著我們可以在其中編寫任何基本的 CSS,例如我們自己的值而不是預(yù)定義的值。沒有其他!無需再搜索或四舍五入!
這是否會使您的包大小增加,因為定義任何任意值時 Tailwind 會創(chuàng)建一個附加類?不會,因為 Tailwind 是可搖樹的 —— 這意味著所有基本類都從您的包中刪除了,如果您沒有使用它們 —— 對您來說更好!
那么可重用性如何呢?我們可以在配置中以與此處相同的方式定義自己的樣式,或者使用 Tailwind 的基本樣式,并且確實應(yīng)該這樣做!我建議將任意值的使用限制在間隙、特定寬度和高度以及任何不可預(yù)測且不適合設(shè)計系統(tǒng)的其他事物上。
使用這種方法使 Tailwind 智能提示注釋變得過時了嗎?實際上并不是,因為可以在 settings.json 中這樣調(diào)整擴(kuò)展的基本字體大小:
"tailwindCSS.rootFontSize": 10,
添加我們自己的插件
有時,Tailwind 存在一個問題:它允許我們使用基本的 CSS 構(gòu)造,比如將某些樣式應(yīng)用于元素的所有子元素,但要使其工作,我們需要重寫每個帶有該構(gòu)造的樣式,這種方法完全違背了 DRY(不重復(fù)自己)原則。
為了更清楚地說明,我們來看一個基本的例子:
假設(shè)我們需要制作這樣一個組件:
<nav className="flex flex-col gap-[1rem] text-center text-medium font-bold underline ">
<a href="/catland" className="rounded-medium bg-orange px-[1rem] py-[1.4rem] text-blue">
catland 32 apartment 69
</a>
<a href="/station" className="rounded-medium bg-orange px-[1rem] py-[1.4rem] text-blue-dark">
cat’s station in Cat York
</a>
<a href="/cafe" className="rounded-medium bg-orange px-[1rem] py-[1.4rem] text-blue-darkest">
cat cafe at Catfel Tower
</a>
</nav>
注意我們是如何重復(fù)自己的?如果我們以后需要更改這個類怎么辦?當(dāng)然,我們可以利用現(xiàn)代 IDE 的多重選擇功能,但對我來說那太麻煩了。
.class > * {
@Apply bg-orange rounded-medium px-[1rem] py-[1.4rem]
}
將會把這個樣式應(yīng)用到所有子元素上,而不需要重復(fù)。因此我們在 Tailwind 類中用 Arbitrary value 用法實現(xiàn)它:
<nav className="flex flex-col gap-[1rem] text-center text-medium font-bold underline [&>*]:rounded-medium [&>*]:bg-orange [&>*]:px-[1rem] [&>*]:py-[1.4rem]">
<a href="/catland" className="text-blue">
catland 32 apartment 69
</a>
<a href="/station" className="text-blue-dark">
cat’s station in Cat York
</a>
<a href="/cafe" className="text-blue-darkest">
cat cafe at Catfel Tower
</a>
</nav>
但這也有重復(fù)!如果我們以后需要使用這種結(jié)構(gòu),或者我們的一些同事根本不知道它,每次都會忘記怎么辦?為了解決這個問題,有一個解決方案:Tailwind 插件。
在 Tailwind 配置中,我們可以定義我們自己的自定義屬性,以后可以在基本函數(shù)中重用,如下所示:
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {},
plugins: [
function ({ addVariant }) {
addVariant("child", "& > *");
},
],
};
這里,我們說現(xiàn)在我們的代碼將有一個名為 ‘child’ 的變體類,它將采用之前在 Arbitrary value 括號中定義的功能。
現(xiàn)在我們可以這樣寫:
<nav className="text-medium child:rounded-medium child:bg-orange child:px-[1rem] child:py-[1.4rem] flex flex-col gap-[1rem] text-center font-bold underline ">
<a href="/catland" className="text-blue">
catland 32 apartment 69
</a>
<a href="/station" className="text-blue-dark">
cat’s station in Cat York
</a>
<a href="/cafe" className="text-blue-darkest">
cat cafe at Catfel Tower
</a>
</nav>
使用 React 和 TypeScript 制作動態(tài)可復(fù)用組件
由于 React 和 TypeScript 的技術(shù)組合越來越受歡迎,我們將利用 Tailwind 制作一些酷炫的可復(fù)用按鈕。
在此過程中,我們還將了解一些非常小的庫來幫助我們:
- Class-variance-authority 是一個用于制作可復(fù)用類的庫,特別適合于 Tailwind,因為我們不需要在它之外定義任何東西 —— 一個安全、始終有效的工具!
- Tailwind-merge 和 clsx 是兩個幫助我們管理我們在 class-variance-authority 定義中定義的類的庫。它們的使用完全是可選的,因為它們只在一些罕見的情況下有用。
我們安裝這些庫,然后開始創(chuàng)建我們的按鈕!
npm i tailwind-merge clsx class-variance-authority
首先,我們創(chuàng)建一個名為 Button.tsx 的文件,其中包含一個基本的按鈕組件:
export const Button = () => {
return (
<button>
</button>
);
};
然后,我們用 class-variance-authority 定義我們的類。為此,從庫中導(dǎo)入函數(shù),如下所示:
import { cva } from "class-variance-authority";
函數(shù)接受兩個參數(shù):
- 適用于我們可復(fù)用按鈕所有變體的基本類
- 包括我們定義的變體及其基本回退情況的對象(以防我們忘記定義某些內(nèi)容)。
示例如下:
export const buttonVariants = cva(
"text-black transition-all border-[1px] border-solid focus:ring-2 text-small",
{
variants: {
variant: {
filled: "bg-yellow-600 ring-black border-yellow-600 hover:bg-white",
outline: "border-yellow-600 ring-black bg-white hover:bg-yellow-600",
},
size: {
small: "px-[1.5rem] py-[1rem] rounded-sm",
medium: "px-[2rem] py-[1.5rem] rounded-md",
},
},
defaultVariants: {
variant: "filled",
size: "small",
},
}
);
然后,我們定義默認(rèn)變體:variant 將是 filled,size 將是 small。
由于我們的組件是可復(fù)用的,我們需要以某種方式將這些屬性傳遞給它 —— 我們將通過 props 來做,并使它們類型安全。
首先,我們將聲明一個基本接口:
interface IButtonProps {}
然后,我們將從 class-variance-authority 的泛型接口 VariantProps 擴(kuò)展,可以通過 cva 函數(shù)導(dǎo)入它。它接受我們定義的 buttonVariants 的 typeof 并使 props 類型安全,因此我們不會定義我們沒有的 big 尺寸:
interface IButtonProps extends VariantProps<typeof buttonVariants> {}
最后,我們還將從 React 的 HTMLAttributes 擴(kuò)展,它也是泛型并接受 HTML 元素的類型。它將使我們的 props 包括按鈕的所有基本 HTML 屬性,如 onClick,以及我們類型中定義的 React children:
interface IButtonProps
extends HTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {}
完成所有這些后,我們可以這樣對組件進(jìn)行類型化并使用其 props:
export const Button = ({
variant,
size,
className,
children,
...props
}: IButtonProps) => {
return (
<button className={buttonVariants({ size, variant })} {...props}>
{children}
</button>
);
};
現(xiàn)在,當(dāng)我們傳遞 variant 和 size 時,按鈕將改變其視圖!看:
export default function App() {
return (
<>
<Button variant="filled">填充按鈕</Button>
<Button variant="outline">輪廓按鈕</Button>
</>
);
}
但是,當(dāng)我們需要稍微調(diào)整按鈕時怎么辦?為此,我們有我們的 className 屬性,可以用兩種不同的方式使用:
我們在現(xiàn)場將其與我們的 buttonVariants 函數(shù)合并,使用模板字面量:
<button className={`${buttonVariants({ size, variant })} ${className}`} {...props}>
我們使用之前提到的兩個庫來確保我們的類沒有重復(fù):例如,當(dāng)我們有 mx-2
和 my-2
時,它將被轉(zhuǎn)換為 m-2
。
為此,讓我們在其他地方定義一個小函數(shù),如下所示:
import clsx, { ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export const clsxm = (...classes: ClassValue[]) => twMerge(clsx(...classes));
這里,它接受任何數(shù)量的類并將它們與 tailwind-merge 庫中的函數(shù)合并。現(xiàn)在,我們可以用該函數(shù)而不是模板字面量合并我們的類:
<button
className={twMerge(buttonVariants({ size, variant }), className)}
{...props}
>
完成!
需要注意的一點 —— class-variance-authority 方法制作可復(fù)用組件的最佳之處在于,我們能夠在應(yīng)用程序的任何其他地方重用我們收到的函數(shù),這就是為什么我們要導(dǎo)出它的原因。在這里,最常見的用途可能是需要為某個 <a> 鏈接設(shè)置樣式,可以輕松實現(xiàn):只需導(dǎo)入函數(shù)并定義類即可!
import { buttonVariants } from "./Button/Button";
export default function App() {
return (
<>
<a className={buttonVariants({ size: "medium", variant: "filled" })}>
中等大小填充鏈接!
</a>
</>
);
}
最后,如果您一直在跟隨我的示例,您可能已經(jīng)注意到,當(dāng)我們在 cva 函數(shù)內(nèi)編寫類時,Tailwind 智能提示擴(kuò)展不起作用。這是因為它沒有被訓(xùn)練去做這件事 —— 它只在我們編寫類名和使用 @apply 樣式時觸發(fā)。為了解決這個問題,我們可以稍微調(diào)整 settings.json 文件,添加以下行:
"tailwindCSS.experimental.classRegex": [
["cva\(([^)]*)\)", "["'`]([^"'`]*).*?["'`]"]
],