Tailwind CSS v4 Plugin System — @plugin Directive and Custom Extensions
In this tutorial, you will learn about Tailwind CSS v4 Plugin System. We cover key concepts, practical examples, and best practices to help you master this topic.
Tailwind CSS v4 plugin system replaces the JavaScript plugin API with the CSS @plugin directive, supporting official plugins, npm packages, and custom CSS-based plugins.
What You'll Learn
You will learn how to install and load plugins with @plugin, create custom CSS-based plugins, manage plugin options, and handle plugin versioning.
Why It Matters
The CSS-first plugin system simplifies setup and keeps everything in CSS. DodaTech's v4 projects load plugins directly in the main CSS file without JavaScript configuration.
Real-World Use
Doda Browser uses @plugin "@tailwindcss/forms" and @plugin "@tailwindcss/typography" in its main CSS, with custom plugin files in a plugins/ directory for brand-specific utilities.
flowchart LR
A[Integration] --> B[Plugin System]
B --> C[@plugin Directive]
B --> D[Official Plugins]
B --> E[Custom Plugins]
B --> F[Options]
style B fill:#38bdf8,stroke:#0284c7,color:#fff
style C fill:#22c55e,stroke:#16a34a,color:#fff
Installing and Loading Plugins
npm install @tailwindcss/forms @tailwindcss/typography
@import "tailwindcss";
/* Load official plugins with @plugin */
@plugin "@tailwindcss/forms";
@plugin "@tailwindcss/typography";
Expected output: Plugins are loaded with @plugin in CSS, not in a JavaScript config file. The plugins extend Tailwind with form resets and prose styles.
Official Plugins in v4
@import "tailwindcss";
/* Forms plugin -- consistent form element styling */
@plugin "@tailwindcss/forms";
/* Typography plugin -- rich text content styling */
@plugin "@tailwindcss/typography";
/* Typography with options */
@plugin "@tailwindcss/typography" {
/* Custom prose class names */
/* Plugin-specific options go here */
}
<form class="space-y-4 max-w-md mx-auto">
<input type="text" class="w-full rounded-lg border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
<select class="w-full rounded-lg border-gray-300 shadow-sm">
<option>Option 1</option>
</select>
</form>
<article class="prose prose-lg prose-blue max-w-none">
<h1>Typographic content</h1>
<p>Styled automatically by the typography plugin.</p>
</article>
Expected output: Official plugins work identically to v3 but are loaded via @plugin in CSS instead of JavaScript configuration.
Custom CSS Plugins
/* plugins/brand-utilities.css */
@layer utilities {
.text-gradient {
background: linear-gradient(to right, var(--tw-gradient-stops));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.text-balance {
text-wrap: balance;
}
.scrollbar-thin {
scrollbar-width: thin;
}
}
@layer components {
.brand-button {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
font-weight: 600;
transition: all 0.2s ease;
}
}
/* main.css */
@import "tailwindcss";
@plugin "./plugins/brand-utilities.css";
<h1 class="text-gradient from-blue-500 to-purple-600 text-4xl font-bold">
Custom plugin utilities
</h1>
<button class="brand-button bg-blue-600 text-white hover:bg-blue-700">
Component from plugin
</button>
Expected output: Custom CSS plugins in .css files are loaded with @plugin "./path/to/plugin.css". They extend Tailwind with project-specific utilities and components.
Plugin with Configuration
/* plugins/theme-plugin.css */
@layer base {
:root {
--plugin-border-radius: 0.5rem;
--plugin-spacing: 1rem;
}
}
@layer components {
.plugin-card {
border-radius: var(--plugin-border-radius);
padding: var(--plugin-spacing);
background: var(--color-white, white);
border: 1px solid var(--color-gray-200, #e5e7eb);
}
}
<div class="plugin-card">
<h3 class="font-bold">Plugin Card Component</h3>
<p class="text-gray-600 mt-2">Defined entirely in a plugin CSS file.</p>
</div>
Expected output: Plugins can define configuration via CSS variables in @layer base, making them configurable per project.
Plugin with @theme Extensions
/* plugins/extended-theme.css */
@theme {
--color-plugin-accent: #7c3aed;
--color-plugin-secondary: #6d28d9;
--font-family-plugin: "Inter", sans-serif;
--spacing-plugin: 2rem;
}
/* main.css */
@import "tailwindcss";
@plugin "./plugins/extended-theme.css";
<div class="bg-plugin-accent text-white p-plugin rounded-lg">
Theme tokens from plugin
</div>
Expected output: Plugins can extend @theme with additional design tokens that become available as utility classes.
Versioning and Updating Plugins
# Check plugin versions
npm list @tailwindcss/forms
# Update plugins
npm update @tailwindcss/forms @tailwindcss/typography
# Or install specific versions
npm install @tailwindcss/forms@0.5.9
Expected output: Plugin versions are managed through npm. The @plugin directive loads whatever version is installed in node_modules.
Common Mistakes
1. Using JavaScript Plugin API
The old require('@tailwindcss/forms') in plugins array does not work in v4. Use @plugin "@tailwindcss/forms" in CSS.
2. Plugin Not Installed
@plugin "@tailwindcss/forms" fails if the package is not installed via npm. Always install before loading.
3. Wrong Plugin Path
Custom plugins with relative paths must start with ./ or ../. @plugin "plugins/custom.css" should be @plugin "./plugins/custom.css".
4. Plugin Order Matters
Plugins are loaded in order. If plugin B depends on plugin A's tokens, load plugin A first.
5. Forgetting @layer in Custom Plugins
Custom plugin CSS should use @layer to integrate with Tailwind's cascade. Without @layer, styles may not override correctly.
Practice Questions
How do you load a plugin in v4? Use
@plugin "package-name"in CSS. Example:@plugin "@tailwindcss/forms".How do you create a custom plugin? Create a CSS file with @layer definitions and load it via
@plugin "./path/to/plugin.css".Can plugins extend @theme? Yes. Plugins can include @theme blocks with additional design tokens.
How do you pass options to plugins? Add a block after the @plugin directive:
@plugin "@tailwindcss/typography" { /* options */ }.Do plugins affect build performance? Minimally. Each plugin adds processing, but the impact is negligible with Lightning CSS.
Challenge
Create a custom plugin that adds: a text-gradient utility, a scrollbar-thin utility, a @theme extension for 3 brand colors, and a card component in @layer components. Load it in a project and use all features.
FAQ
Mini Project
Build a plugin library with 3 plugins: base-theme.css (@theme with colors, fonts, spacing), components.css (button, card, badge components), utilities.css (text-gradient, scrollbar, text-balance). Load all three in a main.css and use every feature.
What's Next
Now master the Standalone CLI for Tailwind v4 for projects without build tools. Then explore Vite Plugin for deeper framework integration.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro