Skip to content
Created: March 24, 2025

The JavaScript configuration and plugin snippets here target Tailwind CSS 3. Tailwind CSS 4 uses CSS-first configuration; explicitly load a compatible legacy config with @config rather than assuming automatic discovery. Upgrade guide.

Tailwind plug-in mechanism (addUtilities/addComponents) belongs to 👉 The watershed of "from being able to use Tailwind → to being able to build a component library/standard system"

1. What is the plug-in mechanism for? ​

In one sentence:

Use JS to batch generate Tailwind classes instead of handwriting CSS

You can:

  • Define a set of utilities
  • Define a set of components
  • Read design variables in theme()
  • Automatic support for hover / dark / responsive

2. Basic structure of plug-in ​

js
// tailwind.config.js
import plugin from 'tailwindcss/plugin'

export default {
  theme: { extend: {} },
  plugins: [
    plugin(function ({ addUtilities, addComponents, theme }) {
      // 写插件逻辑
    })
  ]
}

3. addUtilities (tool class) ​

When to use it? ​

👉 Single function, freely combinable atomic capabilities

Such as:

  • .safe-top
  • .text-shadow
  • .scrollbar-hide

1️⃣ The simplest example ​

js
addUtilities({
  '.safe-top': {
    paddingTop: 'env(safe-area-inset-top)'
  }
})
html
<div class="safe-top"></div>

2️⃣ Support responsive / hover / dark ​

js
addUtilities(
  {
    '.text-shadow': {
      textShadow: '0 2px 4px rgba(0,0,0,.2)'
    }
  },
  ['responsive', 'hover', 'dark']
)
html
<div class="hover:text-shadow dark:text-shadow"></div>

3️⃣ Get value from theme (core) ​

js
addUtilities(
  {
    '.bg-primary-gradient': {
      background: `linear-gradient(
        90deg,
        ${theme('colors.primary.500')},
        ${theme('colors.primary.700')}
      )`
    }
  }
)

📌 This step = plug-in + design system integration

4️⃣ Batch generation of utilities (common techniques) ​

js
const sizes = {
  sm: '4px',
  md: '8px',
  lg: '16px'
}

addUtilities(
  Object.entries(sizes).map(([key, value]) => ({
    [`.blur-${key}`]: { filter: `blur(${value})` }
  }))
)

Use:

html
<div class="blur-md"></div>

4. addComponents (component class) ​

When to use it? ​

👉 A complete set of fixed structure styles

Such as:

  • Button
  • Card
  • Alert
  • Tag

1️⃣ Button component example (core) ​

js
addComponents({
  '.btn': {
    padding: '8px 16px',
    borderRadius: theme('borderRadius.md'),
    fontWeight: '500'
  },
  '.btn-primary': {
    backgroundColor: theme('colors.primary.500'),
    color: '#fff',
    '&:hover': {
      backgroundColor: theme('colors.primary.700')
    }
  }
})
html
<button class="btn btn-primary"></button>

📌 btn = structure 📌 btn-primary = skin

2️⃣ Responsive components ​

js
addComponents({
  '.card': {
    padding: '16px',
    '@screen md': {
      padding: '24px'
    }
  }
})

3️⃣ Dark Mode component ​

js
addComponents({
  '.card': {
    backgroundColor: '#fff',
    '.dark &': {
      backgroundColor: '#111'
    }
  }
})

5. addUtilities vs addComponents (key comparison) ​

dimensionsaddUtilitiesaddComponents
PositioningAtomic capabilitiesComponent packaging
CombinatorialityStrongWeak
Is there semanticsAlmost noneStrong
Suitable for scenariosFunctional classesComponent library

📌 Rule of Thumb

Detachable → utilities Don’t want to dismantle → components

6. addBase (by the way) ​

Used to change the default label style ​

js
addBase({
  'h1': { fontSize: theme('fontSize.xl') },
  'h2': { fontSize: theme('fontSize.lg') }
})

📌 Commonly used in:

  • reset
  • markdown style

7. Practical combat: Make an "enterprise-level button plug-in" ​

js
// plugins/button.js
import plugin from 'tailwindcss/plugin'

export default plugin(({ addComponents, theme }) => {
  addComponents({
    '.btn': {
      display: 'inline-flex',
      alignItems: 'center',
      justifyContent: 'center',
      borderRadius: theme('borderRadius.md'),
      padding: '8px 16px',
      fontWeight: '500'
    },
    '.btn-primary': {
      backgroundColor: theme('colors.primary.500'),
      color: '#fff',
      '&:hover': {
        backgroundColor: theme('colors.primary.700')
      }
    },
    '.btn-danger': {
      backgroundColor: theme('colors.danger.500'),
      color: '#fff'
    }
  })
})
js
// tailwind.config.js
import button from './plugins/button'

plugins: [button]

8. Best practices for combining with Vue components ​

The Tailwind plug-in is responsible for "style rules" ​

Vue components are responsible for "structure + logic" ​

vue
<button class="btn" :class="`btn-${type}`">
  <slot />
</button>

9. Common pitfalls (you will definitely encounter them) ​

1️⃣ Will classes generated by plug-ins also be purged? ​

✅ No (plug-ins are injected during build)

2️⃣ How to choose plug-in vs @apply? ​

  • Public system → plug-in
  • local component → @apply