
tailwind-4
by yacosta738
My Personal Blog and Portfolio ๐
SKILL.md
name: tailwind-4 description: > Tailwind CSS 4 patterns and best practices. Trigger: When styling with Tailwind - :class/class usage, theme variables, no var() in class. allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
Tailwind CSS 4 Best Practices
This document outlines best practices for using Tailwind CSS 4 in Astro and Vue projects, focusing on when to use class/:class, optional helpers, style constants, and dynamic styles.
Styling Decision Tree
Tailwind class exists? โ class="..." (Astro/Vue static)
Dynamic value (Vue)? โ :style="{ width: x + '%' }"
Dynamic value (Astro)? โ style="width: ${x}%" (string)
Conditional styles (Vue) โ :class="['base', condition && 'variant']" or :class="{ variant: condition }"
Conditional styles (Astro)โ class="base ${condition ? 'variant' : ''}"
Static only? โ class="..." (no helper needed)
Library can't use class? โ style props with var() constants
Critical Rules
Never Use var() in class
// โ NEVER: var() in class
<div class = "bg-[var(--color-primary)]" / >
<div class = "text-[var(--text-color)]" / >
// โ
ALWAYS: Use Tailwind semantic classes
<div class = "bg-primary" / >
<div class = "text-slate-400" / >
Never Use Hex Colors
// โ NEVER: Hex colors in class
<p class = "text-[#ffffff]" / >
<div class = "bg-[#1e293b]" / >
// โ
ALWAYS: Use Tailwind color classes
<p class = "text-white" / >
<div class = "bg-slate-800" / >
Conditional Classes in Vue/Astro
Prefer framework-native patterns:
<!-- Vue: arrays and objects -->
<template>
<div :class="['base-class', isActive && 'active-class']" />
<div :class="{ 'active-class': isActive }" />
<button :class="['px-4', size === 'lg' && 'py-3', size === 'sm' && 'py-1']" />
</template>
---
const isActive = true;
const variant = 'primary';
---
<div class={`base-class ${isActive ? 'active-class' : ''}`} />
<div class={`rounded-lg border ${variant === 'primary' ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-800'}`} />
Optional helper (only when programmatically composing class strings or merging potential Tailwind conflicts):
import {clsx} from "clsx";
import {twMerge} from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
Using cn() in Vue/Astro
Use cn() when you need to merge potentially conflicting Tailwind classes or compose classes
programmatically. Prefer native :class/string interpolation for simple conditions.
<script setup lang="ts">
import { cn } from "@/lib/utils";
const props = defineProps<{ active?: boolean; size?: 'sm'|'md'|'lg'; class?: string }>();
</script>
<template>
<!-- Merge variants + external class -->
<button :class="cn(
'inline-flex items-center font-medium',
props.size === 'lg' && 'px-4 py-3 text-base',
props.size === 'sm' && 'px-2 py-1 text-sm',
props.active && 'bg-blue-600 text-white',
props.class
)" />
<!-- Plain conditions can use native :class -->
<div :class="['rounded', props.active && 'ring-2 ring-blue-500']" />
</template>
---
import { cn } from "@/lib/utils";
const { active = false, size = 'md', class: className = '' } = Astro.props;
---
<button class={cn(
'inline-flex items-center font-medium',
size === 'lg' && 'px-4 py-3 text-base',
size === 'sm' && 'px-2 py-1 text-sm',
active && 'bg-blue-600 text-white',
className
)} />
<!-- Simple conditions: prefer string interpolation -->
<div class={`rounded ${active ? 'ring-2 ring-blue-500' : ''}`} />
When NOT to Use cn()
<!-- โ Static classes - unnecessary helper -->
<div :class="cn('flex items-center gap-2')" />
<!-- โ
Just use native binding -->
<div class="flex items-center gap-2" />
<!-- โ Static classes - unnecessary helper -->
<div class={cn('flex items-center gap-2')} />
<!-- โ
Just use class directly -->
<div class="flex items-center gap-2" />
Style Constants for Charts/Libraries
When libraries don't accept class/:class (e.g., Recharts, Chart.js, ECharts):
// โ
Constants with var() - ONLY for library props
const CHART_COLORS = {
primary: "var(--color-primary)",
secondary: "var(--color-secondary)",
text: "var(--color-text)",
gridLine: "var(--color-border)",
};
// Usage (can't use class)
<XAxis tick = {
{
fill: CHART_COLORS.text
}
}
/>
< CartesianGrid
stroke = {CHART_COLORS.gridLine}
/>
Dynamic Values
// โ
Vue: style binding for truly dynamic values
<div :style="{ width: percentage + '%', opacity: isVisible ? 1 : 0 }" />
// โ
Astro: style as string
<div style={`width: ${percentage}%`} />
<div style={`opacity: ${isVisible ? 1 : 0}`} />
// โ
CSS custom properties for theming
// Vue
<div :style="{ '--progress': value + '%' }" />
// Astro
<div style={`--progress: ${value}%`} />
Common Patterns
Flexbox
<div class = "flex items-center justify-between gap-4" / >
<div class = "flex flex-col gap-2" / >
<div class = "inline-flex items-center" / >
Grid
<div class = "grid grid-cols-3 gap-4" / >
<div class = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6" / >
Spacing
// Padding
<div class = "p-4" / > // All sides
<div class = "px-4 py-2" / > // Horizontal, vertical
<div class = "pt-4 pb-2" / > // Top, bottom
// Margin
<div class = "m-4" / >
<div class = "mx-auto" / > // Center horizontally
<div class = "mt-8 mb-4" / >
Typography
<h1 class = "text-2xl font-bold text-white" / >
<p class = "text-sm text-slate-400" / >
<span class = "text-xs font-medium uppercase tracking-wide" / >
Borders & Shadows
<div class = "rounded-lg border border-slate-700" / >
<div class = "rounded-full shadow-lg" / >
<div class = "ring-2 ring-blue-500 ring-offset-2" / >
States
<button class = "hover:bg-blue-600 focus:ring-2 active:scale-95" / >
<input class = "focus:border-blue-500 focus:outline-none" / >
<div class = "group-hover:opacity-100" / >
Responsive
<div class = "w-full md:w-1/2 lg:w-1/3" / >
<div class = "hidden md:block" / >
<div class = "text-sm md:text-base lg:text-lg" / >
Dark Mode
<div class = "bg-white dark:bg-slate-900" / >
<p class = "text-gray-900 dark:text-white" / >
Arbitrary Values (Escape Hatch)
// โ
OK for one-off values not in design system
<div class = "w-[327px]" / >
<div class = "top-[117px]" / >
<div class = "grid-cols-[1fr_2fr_1fr]" / >
// โ Don't use for colors - use theme instead
<div class = "bg-[#1e293b]" / > // NO
Score
Total Score
Based on repository quality metrics
SKILL.mdใใกใคใซใๅซใพใใฆใใ
ใฉใคใปใณในใ่จญๅฎใใใฆใใ
100ๆๅญไปฅไธใฎ่ชฌๆใใใ
GitHub Stars 100ไปฅไธ
1ใถๆไปฅๅ ใซๆดๆฐ
10ๅไปฅไธใใฉใผใฏใใใฆใใ
ใชใผใใณIssueใ50ๆชๆบ
ใใญใฐใฉใใณใฐ่จ่ชใ่จญๅฎใใใฆใใ
1ใคไปฅไธใฎใฟใฐใ่จญๅฎใใใฆใใ
Reviews
Reviews coming soon

