本文へ移動
cccskills
無料GitHub で公開

tailwind

Use when styling with Tailwind CSS v4 - @theme syntax, design token architecture, dark mode strategy, bundle size optimization, component-layer discipline, or migrating from v3

インストール方法を見る

含まれるファイル(4)

  • SKILL.md12.9 KB
  • references/migration-v4.md4.2 KB
  • references/theme.md5.7 KB
  • references/utilities-variants.md5.2 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Overview

Tailwind CSS v4 is a complete rewrite built on the Rust-based Oxide engine. Configuration moves from JavaScript to CSS via @theme.

Key v4 shifts:

  • Config: tailwind.config.js → CSS @theme block
  • Import: @tailwind base/components/utilities → @import "tailwindcss"
  • Dark mode: automatic via @media (prefers-color-scheme)
  • Content detection: automatic, no content array needed

Browser support: Safari 16.4+, Chrome 111+, Firefox 128+

Installation

Vite (Recommended)

npm install tailwindcss @tailwindcss/vite
// vite.config.js
import tailwindcss from "@tailwindcss/vite";

export default {
  plugins: [tailwindcss()],
};

PostCSS

npm install -D tailwindcss @tailwindcss/postcss
// postcss.config.js
export default {
  plugins: {
    "@tailwindcss/postcss": {},
  },
};

CLI

npm install -D @tailwindcss/cli
npx @tailwindcss/cli -i input.css -o output.css --watch

Basic Setup

/* input.css */
@import "tailwindcss";

/* Your custom styles and @theme block below */

That's it. No @tailwind base/components/utilities directives—they're gone.

Design Token Architecture (v4)

Single source of truth: The @theme block in your main CSS file defines all design tokens. Every color, spacing value, and font becomes a CSS variable.

Token Definition Pattern

@import "tailwindcss";

@theme {
  /* Replace, don't extend, the default palette */
  --color-brand: oklch(65% 0.25 250);
  --color-brand-dark: oklch(55% 0.25 250);
  --color-bg: oklch(98% 0.01 250);
  --color-surface: oklch(100% 0 250);
  --color-text: oklch(20% 0.02 250);
  --color-text-muted: oklch(50% 0.02 250);

  /* Spacing scale */
  --spacing-xs: 0.25rem;
  --spacing-sm: 0.5rem;
  --spacing-md: 1rem;
  --spacing-lg: 1.5rem;
  --spacing-xl: 2rem;

  /* Typography */
  --font-display: "Clash Display", sans-serif;
  --font-body: "Satoshi", system-ui, sans-serif;
}

Why Replace Instead of Extend

The default Tailwind palette is generic. Replacing it with your semantic tokens:

  • Prevents bg-blue-500 from leaking into a design that uses bg-brand-500
  • Makes theme changes a token edit, not a class sweep
  • Keeps the design system coherent

Failure mode: Hardcoding a hex in a component class:

/* BAD: This breaks the theme system */
.card {
  background-color: #3b82f6; /* Can't change via @theme */
}

Correct:

/* GOOD: Theme change is one token edit */
@theme {
  --color-card-bg: var(--color-surface);
}

.card {
  background-color: var(--color-card-bg);
}

Token-to-Component Mapping

Component styles reference tokens, not raw values:

@layer components {
  .btn {
    background-color: var(--color-brand);
    color: var(--color-surface);
    padding: var(--spacing-sm) var(--spacing-md);
    font-family: var(--font-display);
  }

  .btn:hover {
    background-color: var(--color-brand-dark);
  }
}

Result: Changing --color-brand in @theme updates every button site-wide. No search-and-replace.

The --color-* Namespace Rule

Any --color-* variable in @theme automatically generates utility classes:

@theme {
  --color-primary: oklch(60% 0.18 250);
}

Now bg-primary, text-primary, border-primary all work. The engine maps:

  • --color-{name} → {prop}-{name} utilities

Dark Mode Decision Guide

v4 defaults to @media (prefers-color-scheme)—no config needed. But product requirements dictate the right strategy.

Three Strategies

StrategyMechanismBest For
Media query@media (prefers-color-scheme: dark)Static sites, blogs, no user preference
Manual toggle.dark class on <html>Apps with user theme preference
Data attribute[data-theme="dark"] on <html>Multiple themes (light/dark/sepia)

Decision Logic

Does the product need user-chosen theme that survives reload?
├─ Yes → Use `.dark` class or `data-theme` attribute
│        Persist choice in localStorage
│        Sync with `<html class="dark">` or `<html data-theme="dark">`
│
└─ No → Media query is enough. Do nothing.

Manual Toggle Implementation

<!-- HTML -->
<html class="dark">
  <div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">
    Content
  </div>
</html>
// JavaScript toggle
function toggleDark() {
  const html = document.documentElement;
  const isDark = html.classList.toggle("dark");
  localStorage.setItem("theme", isDark ? "dark" : "light");
}

// Restore on load
const saved = localStorage.getItem("theme");
if (saved === "dark") {
  document.documentElement.classList.add("dark");
}

Avoiding Flash-of-Wrong-Theme

On first paint, before JS runs, the page may flash the wrong theme. Fix:

<!-- Inline script before any CSS/JS -->
<script>
  const saved = localStorage.getItem("theme");
  const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
  if (saved === "dark" || (!saved && prefersDark)) {
    document.documentElement.classList.add("dark");
  }
</script>

Place this in <head> before any stylesheets.

Why Not dark: on Every Color

Adding dark: to every utility duplicates tokens:

<!-- BAD: Duplicates token definitions -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 border-gray-200 dark:border-gray-800">

Better: Define semantic tokens that invert automatically:

@theme {
  --color-bg: oklch(100% 0 250);
  --color-bg-dark: oklch(15% 0.02 250);
  --color-text: oklch(20% 0.02 250);
  --color-text-dark: oklch(90% 0.02 250);
}
<!-- Use semantic tokens, fewer dark: prefixes -->
<div class="bg-bg text-text">

Or use CSS color-scheme with automatic contrast:

@layer base {
  :root {
    color-scheme: light dark;
  }
}

Bundle Size and Content Detection

Content Detection in v4 (@source)

v4 automatically scans your project. No content array needed. But you can explicitly add sources:

@import "tailwindcss";

@source "../components/**/*.{js,ts,jsx,tsx,vue,svelte}";
@source "../pages/**/*.{js,ts,jsx,tsx}";

Rule: Content scanning must cover all template files, not just JS. If you use Blade, EJS, Handlebars, or PHP templates, add them:

@source "../views/**/*.blade.php";
@source "../templates/**/*.html";

Why Unused Utilities Are Tree-Shaken

The Oxide engine generates only the utilities you actually use. Unused classes are never emitted.

What inflates output:

  • Arbitrary values: bg-[#3b82f6] prevents some optimizations because each arbitrary value is unique
  • Icon libraries: SVG icons in HTML add bulk
  • Plugin CSS: Custom plugins that emit raw CSS (not utilities)
  • Preflight: The base reset (~15KB)

Measuring Bundle Size

# Build and measure
npx @tailwindcss/cli -i input.css -o output.css
wc -c output.css  # Byte count

# Compare with and without @source directives

Target: A typical v4 build is 10–30KB gzipped for a medium app.

Reducing Bundle Size

  1. Use semantic tokens instead of arbitrary values:

    <!-- BAD: Arbitrary value -->
    <div class="bg-[#3b82f6]">
    
    <!-- GOOD: Token -->
    <div class="bg-brand">
    
  2. Exclude unused plugin CSS:

    /* Don't import full plugins if you only need one utility */
    @plugin "@tailwindcss/typography"; /* Only if you need prose */
    
  3. Use @reference for component styles:

    <style>
    @reference "../app.css";
    /* Only what you @apply here */
    </style>
    

Component-Layer Discipline

When a utility pattern repeats, decide between three approaches:

1. Plain Class (Default)

@layer components {
  .btn {
    display: inline-flex;
    align-items: center;
    padding: var(--spacing-sm) var(--spacing-md);
    border-radius: 0.5rem;
    font-weight: 600;
  }
}

Use when: The pattern is used in 3+ places and has no variants.

2. @utility Directive (v4)

@utility btn {
  display: inline-flex;
  align-items: center;
  padding: var(--spacing-sm) var(--spacing-md);
  border-radius: 0.5rem;
  font-weight: 600;
}

Use when: You want the pattern to work with variants (hover:btn, dark:btn).

Failure in JSX-heavy codebases: @apply re-opens the specificity fight utilities were meant to end:

/* BAD: @apply in a component library */
.btn {
  @apply bg-blue-500 text-white px-4 py-2;
}

Why it fails:

  • The component CSS may load after Tailwind, overriding your utilities
  • Specificity becomes unpredictable
  • You're back to fighting CSS cascade instead of avoiding it

Correct: Define the component in @layer components with raw CSS, or use @utility if you need variant support.

3. Variant with @variant

@variant elevated {
  box-shadow: var(--shadow-card);
  background-color: var(--color-surface);
}

Use when: A state (like "elevated", "pressed", "selected") applies across multiple utilities.

Migration to v4 Checklist

Symptomv3v4Fix
Build fails, unknown directive@tailwind base@import "tailwindcss"Replace all @tailwind directives
Config changes ignoredtailwind.config.js@theme in CSSMove config to CSS @theme block
extend not workingtheme.extend in JSCSS variablesDefine variables directly in @theme
Custom utilities missing@layer utilities@utilityRewrite with @utility directive
Old config neededN/A@configAdd @config "../../tailwind.config.js" (legacy only)
Plugin not loadingplugins: [] in JS@pluginUse @plugin "@tailwindcss/typography"
corePlugins errorcorePlugins: []Not supportedRemove from config, use @theme flags
separator errorseparator: "_"Not supportedUse new arbitrary value syntax

One-line summary:

  • @tailwind base/components/utilities → @import "tailwindcss"
  • tailwind.config.js → CSS @theme block
  • extend → CSS variables in @theme
  • @apply → @utility (for variant support)
  • Plugins → @plugin directive

Framework Integration

Vue / Svelte Component Styles

In v4, styles in separate files don't see theme variables by default. Use @reference:

<template>
  <h1>Hello</h1>
</template>

<style>
@reference "../app.css";

h1 {
  @apply text-2xl font-bold text-red-500;
}
</style>

Next.js / Vite

No special config needed if using the official plugin:

// next.config.js or vite.config.js
import tailwindcss from "@tailwindcss/vite";

export default {
  plugins: [tailwindcss()],
};

Common Issues

Missing Classes After Build

  • Ensure @source directives cover all template files
  • Check that the CSS file with @theme is imported by your entry point

Dark Mode Not Applying

  • For manual toggle: add class="dark" to <html>, not <body>
  • For media: no config needed, just use dark: utilities

Custom Utilities Not Working

  • Use @utility directive, not @layer utilities
  • Ensure the CSS file with @theme is imported

Arbitrary Values Not Parsing

  • v3: bg-[--my-var]
  • v4: bg-(--my-var) (parentheses, not brackets)

Best Practices

Do:

  • Replace the default color palette with semantic tokens in @theme
  • Use @utility for reusable patterns that need variants
  • Let dark mode be automatic unless user preference is required
  • Use @source to explicitly scan non-JS templates
  • Define tokens once, reference everywhere via CSS variables

Don't:

  • Hardcode hex values in component CSS
  • Use @apply in JSX-heavy component libraries
  • Add dark: to every color utility
  • Create a tailwind.config.js for new projects
  • Use Sass/Less/Stylus—they don't work with v4

Deep Dives

Load these reference files for detailed information:

  • Theme Configuration — @theme directive syntax, design tokens, colors, spacing, breakpoints, animations — references/theme.md
  • Custom Utilities & Variants — @utility, @variant directives, utility classes reference — references/utilities-variants.md
  • Migration from v3 — Breaking changes, upgrade tool, new features, Preflight changes — references/migration-v4.md

References

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

aiohttp

無料

Use when building Python async HTTP services or clients with aiohttp - web server routing, middleware, WebSocket, SSE, streaming, client sessions, pytest-aiohttp testing, or troubleshooting SSL and timeout issues

日本語の概要は準備中です。原文の説明を表示しています。

CodeAtCode/oss-ai-skills222026年10月9日 更新

ast-grep

無料

Use when doing structural code search and rewriting - ast-grep linting, refactoring, multi-language patterns

日本語の概要は準備中です。原文の説明を表示しています。

CodeAtCode/oss-ai-skills222026年10月9日 更新

Use when building GBA games with the BPCore Lua engine - entity, sprite and tilemap functions, SRAM save and load, link cable multiplayer protocol, camera and scrolling, or optimization patterns

日本語の概要は準備中です。原文の説明を表示しています。

CodeAtCode/oss-ai-skills222026年10月9日 更新

celery

無料

Use when running background tasks with Celery - worker and broker configuration (Redis, RabbitMQ), task routing by name vs queue, chains/groups/chords, retry patterns (autoretry_for, retry_backoff), acks_late semantics, failure detection, and monitoring with Flower

日本語の概要は準備中です。原文の説明を表示しています。

CodeAtCode/oss-ai-skills222026年10月9日 更新

django

無料

Use when building Django applications - security hardening, authentication and permissions, ORM optimization, PostgreSQL features, Django 6.0, migrations, testing, and ecosystem libraries

日本語の概要は準備中です。原文の説明を表示しています。

CodeAtCode/oss-ai-skills222026年10月9日 更新

Use when customizing Django Admin - save_formset, get_search_results, formsets, queryset optimization, db_index, custom URLs

日本語の概要は準備中です。原文の説明を表示しています。

CodeAtCode/oss-ai-skills222026年10月9日 更新

CodeAtCode のスキルをすべて見る

このスキルの問題を報告する