Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
145 lines
3.1 KiB
Markdown
145 lines
3.1 KiB
Markdown
# Tailwind CSS Dynamic Class Generation
|
|
|
|
## Rule
|
|
|
|
Never construct Tailwind CSS class names dynamically using string concatenation or template literals. Tailwind's build process cannot detect dynamically generated class names, causing styles to be missing in production.
|
|
|
|
## Why This Matters
|
|
|
|
- Tailwind uses static analysis at build time to determine which CSS classes to include
|
|
- Dynamically constructed class names (e.g., `bg-${color}-500`) are invisible to Tailwind's scanner
|
|
- Classes work in development with JIT but fail silently in production builds
|
|
- This is a common source of "it works locally but not in production" bugs
|
|
|
|
## Bad Code
|
|
|
|
```vue
|
|
<script setup>
|
|
const props = defineProps({
|
|
color: String, // 'red', 'blue', 'green'
|
|
size: String // 'sm', 'md', 'lg'
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<!-- WRONG: Tailwind cannot detect these classes -->
|
|
<div :class="`bg-${color}-500 text-${size}`">
|
|
Content
|
|
</div>
|
|
|
|
<!-- WRONG: String concatenation -->
|
|
<div :class="'p-' + padding">
|
|
Content
|
|
</div>
|
|
|
|
<!-- WRONG: Template literal in array -->
|
|
<div :class="[`gap-x-${spacing}`]">
|
|
Content
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
## Good Code
|
|
|
|
```vue
|
|
<script setup>
|
|
const props = defineProps({
|
|
color: String,
|
|
size: String
|
|
})
|
|
|
|
// Use a mapping object with complete class names
|
|
const colorClasses = {
|
|
red: 'bg-red-500',
|
|
blue: 'bg-blue-500',
|
|
green: 'bg-green-500'
|
|
}
|
|
|
|
const sizeClasses = {
|
|
sm: 'text-sm p-2',
|
|
md: 'text-base p-4',
|
|
lg: 'text-lg p-6'
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<!-- CORRECT: Full class names that Tailwind can detect -->
|
|
<div :class="[colorClasses[color], sizeClasses[size]]">
|
|
Content
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
## Using Conditional Objects
|
|
|
|
```vue
|
|
<script setup>
|
|
const props = defineProps({
|
|
variant: String // 'primary', 'secondary', 'danger'
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<!-- CORRECT: All class names are complete strings -->
|
|
<button :class="{
|
|
'bg-blue-500 hover:bg-blue-600': variant === 'primary',
|
|
'bg-gray-500 hover:bg-gray-600': variant === 'secondary',
|
|
'bg-red-500 hover:bg-red-600': variant === 'danger'
|
|
}">
|
|
Click me
|
|
</button>
|
|
</template>
|
|
```
|
|
|
|
## Safelist for Truly Dynamic Classes
|
|
|
|
If you must use dynamic classes, add them to Tailwind's safelist:
|
|
|
|
```javascript
|
|
// tailwind.config.js
|
|
module.exports = {
|
|
safelist: [
|
|
'bg-red-500',
|
|
'bg-blue-500',
|
|
'bg-green-500',
|
|
// Or use patterns (use sparingly - increases bundle size)
|
|
{
|
|
pattern: /bg-(red|blue|green)-(100|500|900)/
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Alternative: CSS Custom Properties
|
|
|
|
For truly dynamic values, use CSS custom properties:
|
|
|
|
```vue
|
|
<script setup>
|
|
const props = defineProps({
|
|
customColor: String // Any hex color
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<!-- Use CSS variable for truly dynamic values -->
|
|
<div
|
|
class="dynamic-bg"
|
|
:style="{ '--dynamic-color': customColor }"
|
|
>
|
|
Content
|
|
</div>
|
|
</template>
|
|
|
|
<style>
|
|
.dynamic-bg {
|
|
background-color: var(--dynamic-color);
|
|
}
|
|
</style>
|
|
```
|
|
|
|
## References
|
|
|
|
- [Tailwind CSS Dynamic Class Names](https://tailwindcss.com/docs/content-configuration#dynamic-class-names)
|
|
- [Tailwind Safelist](https://tailwindcss.com/docs/content-configuration#safelisting-classes)
|