# 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