# tailwindcss
## Dynamic Classes in Tailwind CSS
勁量避免用 `Dynamic variable` 方式寫 `class` 因為 `tailwindcss` 在 `bundle css` 時無法知道你的 `variable` 是對應哪一種 `class`。
```typescript
// ❌ using a dynamic value within Tailwind CSS class
<p className={`text-${size}xl`}>Hello</p>
// ❌ using a variable that contains a dynamic value
const style = `text-${size}xl`;
<p className={style}>Hello</p>
```
如果真的需要透過變數,你可能不能透過 `Dynamic` 方式,而是改用 `mention` 寫法告訴 `tailwindcss` 就可以知道他然後成功 `compiled`
```typescript
let style;
if (size === 2) {
// ✅ referencing a Tailwind CSS class
style = `text-2xl`;
}
<p className={style}>Hello</p>
```
或是透過 `switch`
```typescript
export default function Heading({ level, size, children }) {
const Heading = `h${level}`;
let style;
switch(size) {
case 4:
style = 'text-4xl';
break;
case 2:
style = 'text-2xl';
break;
// ...other cases
}
return (
<Heading className={style}>
{children}
</Heading>
);
}
```
## Safelisting Classes
但如果你真的需要透過 `Dynamic` 的話,那你就需要 `pre-build` 告訴 `tailwindcss` 可能會用到的 `class` 有哪些,如此一來就算你的 `variable` 值怎麼變化, `bundle` 的 `css` 已經包含可能用到的 `class`。
```typescript
module.exports = {
safelist: [
'text-4xl',
'text-2xl',
'text-xl',
'text-base',
],
};
```
這樣你的 `size` 就可以用 `Dynamic` 寫法了。
```typescript
const [size,setSize] = useState<'base'|'xl'|'2xl'|'4xl'>('base')
<p className={`text-${size}`}>Hello</p>
```
甚至可以用正則簡化寫法。
```typescript
module.exports = {
safelist: [
{
pattern: /text-(base|xl|2xl|4xl)/,
},
],
};
```
但會有另外一個問題是 `tailwindcss` 有很多 `variants` ,如果是以下寫法,那你只會有 `bg-red-200` 事先 `bundle` 出來 ,`/hover:bg-red-.+/` 則不會。
```typescript
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
safelist: [
'text-2xl',
'text-3xl',
{
pattern: /bg-(red|green|blue)-(100|200|300)/,
},
],
// ...
}
```
所以你需要告訴 `pattern` 你的 `variants` 要什麼,如此一來 `/hover:bg-red-.+/ ` 也會 跟著`bundle` 進去。
```typescript
** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
safelist: [
'text-2xl',
'text-3xl',
{
pattern: /bg-(red|green|blue)-(100|200|300)/,
variants: ['lg', 'hover', 'focus', 'lg:hover'],
},
],
// ...
}
```
## Discarding classes
當然可以事先 `bundle class` ,你也可以事先告知 `tailwindcss` 哪些 `class` 你不想要 `bundle` ,可以透過 `blocklist`。
```typescript
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
blocklist: [
'container',
'collapse',
],
// ...
}
```
會有這個原因是因為 `tailwindcss` 的掃描機制,不只會掃描 `class` 內容,`text` 也會例如以下的 `container`。
```typescript
<div class="text-lg leading-8 text-gray-600">
Every custom pool we design starts as a used shipping `container`, and is
retrofitted with state of the art technology and finishes to turn it into
a beautiful and functional way to entertain your guests all summer long.
</div>
```
但 `blocklist` 通常不會用到這邊只是剛好看到 `tailwindcss` 有提供這功能記錄一下XD