0
# Plugin Development
1
2
Comprehensive plugin system for extending Tailwind CSS with custom utilities, variants, and components. The plugin API provides methods for adding CSS rules, creating parametric utilities, and accessing theme values.
3
4
## Capabilities
5
6
### Plugin Creation
7
8
Creates a Tailwind CSS plugin with a handler function and optional configuration.
9
10
```typescript { .api }
11
/**
12
* Creates a Tailwind CSS plugin
13
* @param handler - Function that receives the plugin API
14
* @param config - Optional configuration to merge with user config
15
* @returns Plugin object for use in Tailwind configuration
16
*/
17
function plugin(handler: PluginFn, config?: Partial<Config>): PluginWithConfig;
18
19
/**
20
* Creates a plugin that accepts options
21
* @param pluginFunction - Function that returns a plugin handler based on options
22
* @param configFunction - Function that returns configuration based on options
23
* @returns Options function that creates configured plugins
24
*/
25
plugin.withOptions<T>(
26
pluginFunction: (options?: T) => PluginFn,
27
configFunction?: (options?: T) => Partial<Config>
28
): PluginWithOptions<T>;
29
30
type PluginFn = (api: PluginAPI) => void;
31
32
interface PluginWithConfig {
33
handler: PluginFn;
34
config?: Config;
35
}
36
37
interface PluginWithOptions<T> {
38
(options?: T): PluginWithConfig;
39
__isOptionsFunction: true;
40
}
41
```
42
43
**Usage Examples:**
44
45
```typescript
46
import plugin from "tailwindcss/plugin";
47
48
// Simple plugin
49
const myPlugin = plugin(function({ addUtilities, theme }) {
50
addUtilities({
51
'.btn': {
52
padding: theme('spacing.4'),
53
borderRadius: theme('borderRadius.md'),
54
fontWeight: theme('fontWeight.semibold'),
55
},
56
'.btn-primary': {
57
backgroundColor: theme('colors.blue.500'),
58
color: theme('colors.white'),
59
},
60
});
61
});
62
63
// Plugin with configuration
64
const buttonPlugin = plugin(function({ addComponents, theme }) {
65
addComponents({
66
'.btn': {
67
padding: `${theme('spacing.2')} ${theme('spacing.4')}`,
68
borderRadius: theme('borderRadius.DEFAULT'),
69
fontWeight: theme('fontWeight.medium'),
70
},
71
});
72
}, {
73
theme: {
74
extend: {
75
colors: {
76
'btn-primary': '#3b82f6',
77
},
78
},
79
},
80
});
81
82
// Plugin with options
83
const spacingPlugin = plugin.withOptions<{ prefix?: string }>(
84
(options = {}) => {
85
return ({ addUtilities }) => {
86
const prefix = options.prefix || '';
87
addUtilities({
88
[`.${prefix}spacing-xs`]: { padding: '0.5rem' },
89
[`.${prefix}spacing-sm`]: { padding: '1rem' },
90
[`.${prefix}spacing-md`]: { padding: '1.5rem' },
91
});
92
};
93
}
94
);
95
```
96
97
### Base Styles
98
99
Add base styles that are applied globally to elements.
100
101
```typescript { .api }
102
/**
103
* Add base styles to the generated CSS
104
* @param base - CSS-in-JS object containing base styles
105
*/
106
addBase(base: CssInJs): void;
107
```
108
109
**Usage Example:**
110
111
```typescript
112
plugin(function({ addBase, theme }) {
113
addBase({
114
'h1': {
115
fontSize: theme('fontSize.4xl'),
116
fontWeight: theme('fontWeight.bold'),
117
},
118
'h2': {
119
fontSize: theme('fontSize.3xl'),
120
fontWeight: theme('fontWeight.semibold'),
121
},
122
});
123
});
124
```
125
126
### Variants
127
128
Add custom variants for conditional styling.
129
130
```typescript { .api }
131
/**
132
* Add a simple variant
133
* @param name - Variant name (e.g., 'hocus')
134
* @param variant - CSS selector(s) or CSS-in-JS object
135
*/
136
addVariant(name: string, variant: string | string[] | CssInJs): void;
137
138
/**
139
* Add a parametric variant that accepts values
140
* @param name - Variant name (e.g., 'data')
141
* @param cb - Callback that generates selectors based on values
142
* @param options - Configuration options for the variant
143
*/
144
matchVariant<T = string>(
145
name: string,
146
cb: (value: T | string, extra: { modifier: string | null }) => string | string[],
147
options?: {
148
values?: Record<string, T>;
149
sort?(
150
a: { value: T | string; modifier: string | null },
151
b: { value: T | string; modifier: string | null }
152
): number;
153
}
154
): void;
155
```
156
157
**Usage Examples:**
158
159
```typescript
160
plugin(function({ addVariant, matchVariant }) {
161
// Simple variant
162
addVariant('hocus', ['&:hover', '&:focus']);
163
164
// Variant with CSS-in-JS
165
addVariant('not-first', {
166
'&:not(:first-child)': {},
167
});
168
169
// Parametric variant
170
matchVariant('data', (value) => `&[data-${value}]`);
171
172
// Parametric variant with predefined values
173
matchVariant('theme', (value) => `[data-theme="${value}"] &`, {
174
values: {
175
light: 'light',
176
dark: 'dark',
177
auto: 'auto',
178
},
179
});
180
181
// Custom sorting
182
matchVariant('min', (value) => `@media (min-width: ${value})`, {
183
sort(a, b) {
184
return parseInt(a.value) - parseInt(b.value);
185
},
186
});
187
});
188
```
189
190
### Utilities
191
192
Add utility classes that can be applied directly to elements.
193
194
```typescript { .api }
195
/**
196
* Add static utility classes
197
* @param utilities - CSS-in-JS object containing utility definitions
198
* @param options - Additional options (currently unused)
199
*/
200
addUtilities(
201
utilities: Record<string, CssInJs | CssInJs[]> | Record<string, CssInJs | CssInJs[]>[],
202
options?: {}
203
): void;
204
205
/**
206
* Add parametric utilities that generate classes based on values
207
* @param utilities - Object mapping utility names to generator functions
208
* @param options - Configuration for values, types, and behavior
209
*/
210
matchUtilities(
211
utilities: Record<
212
string,
213
(value: string, extra: { modifier: string | null }) => CssInJs | CssInJs[]
214
>,
215
options?: Partial<{
216
type: string | string[];
217
supportsNegativeValues: boolean;
218
values: Record<string, string> & {
219
__BARE_VALUE__?: (value: NamedUtilityValue) => string | undefined;
220
};
221
modifiers: 'any' | Record<string, string>;
222
}>
223
): void;
224
```
225
226
**Usage Examples:**
227
228
```typescript
229
plugin(function({ addUtilities, matchUtilities, theme }) {
230
// Static utilities
231
addUtilities({
232
'.scrollbar-hide': {
233
'-ms-overflow-style': 'none',
234
'scrollbar-width': 'none',
235
'&::-webkit-scrollbar': {
236
display: 'none',
237
},
238
},
239
'.scrollbar-default': {
240
'-ms-overflow-style': 'auto',
241
'scrollbar-width': 'auto',
242
'&::-webkit-scrollbar': {
243
display: 'block',
244
},
245
},
246
});
247
248
// Parametric utilities
249
matchUtilities(
250
{
251
'text-shadow': (value) => ({
252
textShadow: value,
253
}),
254
'text-stroke': (value) => ({
255
'-webkit-text-stroke-width': value,
256
}),
257
},
258
{
259
values: theme('textShadow'),
260
type: ['length', 'color'],
261
}
262
);
263
264
// Utilities with modifiers and negative values
265
matchUtilities(
266
{
267
'skew-x': (value) => ({
268
transform: `skewX(${value})`,
269
}),
270
},
271
{
272
values: theme('skew'),
273
supportsNegativeValues: true,
274
type: 'angle',
275
}
276
);
277
});
278
```
279
280
### Components
281
282
Add component classes that contain multiple CSS properties.
283
284
```typescript { .api }
285
/**
286
* Add static component classes
287
* @param components - CSS-in-JS object containing component definitions
288
* @param options - Additional options (currently unused)
289
*/
290
addComponents(components: Record<string, CssInJs> | Record<string, CssInJs>[], options?: {}): void;
291
292
/**
293
* Add parametric components that generate classes based on values
294
* @param components - Object mapping component names to generator functions
295
* @param options - Configuration for values, types, and behavior
296
*/
297
matchComponents(
298
components: Record<string, (value: string, extra: { modifier: string | null }) => CssInJs>,
299
options?: Partial<{
300
type: string | string[];
301
supportsNegativeValues: boolean;
302
values: Record<string, string> & {
303
__BARE_VALUE__?: (value: NamedUtilityValue) => string | undefined;
304
};
305
modifiers: 'any' | Record<string, string>;
306
}>
307
): void;
308
```
309
310
**Usage Examples:**
311
312
```typescript
313
plugin(function({ addComponents, matchComponents, theme }) {
314
// Static components
315
addComponents({
316
'.btn': {
317
padding: `${theme('spacing.2')} ${theme('spacing.4')}`,
318
borderRadius: theme('borderRadius.md'),
319
fontWeight: theme('fontWeight.medium'),
320
},
321
'.card': {
322
backgroundColor: theme('colors.white'),
323
boxShadow: theme('boxShadow.lg'),
324
borderRadius: theme('borderRadius.lg'),
325
padding: theme('spacing.6'),
326
},
327
});
328
329
// Parametric components
330
matchComponents(
331
{
332
'btn': (value) => ({
333
backgroundColor: value,
334
color: theme('colors.white'),
335
'&:hover': {
336
backgroundColor: theme(`colors.${value}.600`),
337
},
338
}),
339
},
340
{
341
values: theme('colors'),
342
type: 'color',
343
}
344
);
345
});
346
```
347
348
### Theme Access
349
350
Access theme values within plugins.
351
352
```typescript { .api }
353
/**
354
* Access theme configuration values
355
* @param path - Dot-notation path to theme value (e.g., 'colors.blue.500')
356
* @param defaultValue - Default value if path doesn't exist
357
* @returns Theme value or default
358
*/
359
theme(path: string, defaultValue?: any): any;
360
```
361
362
**Usage Example:**
363
364
```typescript
365
plugin(function({ addUtilities, theme }) {
366
// Access nested theme values
367
const primaryColor = theme('colors.blue.500');
368
const defaultSpacing = theme('spacing.4');
369
const customFont = theme('fontFamily.custom', ['Inter', 'sans-serif']);
370
371
addUtilities({
372
'.custom-button': {
373
backgroundColor: primaryColor,
374
padding: defaultSpacing,
375
fontFamily: customFont.join(', '),
376
},
377
});
378
});
379
```
380
381
### Configuration Access
382
383
Access the full Tailwind configuration within plugins.
384
385
```typescript { .api }
386
/**
387
* Access configuration values
388
* @param path - Dot-notation path to config value
389
* @param defaultValue - Default value if path doesn't exist
390
* @returns Configuration value or default
391
*/
392
config(path?: string, defaultValue?: any): any;
393
```
394
395
### Class Prefixing
396
397
Apply the configured prefix to class names.
398
399
```typescript { .api }
400
/**
401
* Apply the configured prefix to a class name
402
* @param className - Class name to prefix
403
* @returns Prefixed class name
404
*/
405
prefix(className: string): string;
406
```
407
408
**Usage Example:**
409
410
```typescript
411
plugin(function({ addUtilities, prefix }) {
412
addUtilities({
413
[`.${prefix('my-utility')}`]: {
414
customProperty: 'value',
415
},
416
});
417
});
418
```
419
420
## Plugin Types
421
422
```typescript { .api }
423
type CssInJs = Record<string, string | string[] | CssInJs>;
424
425
interface NamedUtilityValue {
426
value: string;
427
fraction: string | null;
428
modifier: string | null;
429
}
430
```