1. 定制
  2. 插件

概述

插件允许您为 Tailwind 注册新样式,以便使用 JavaScript 而不是 CSS 注入到用户的样式表中。

要开始使用您的第一个插件,请从 tailwindcss/plugin 导入 Tailwind 的 plugin 函数。然后在您的 plugins 数组中,使用匿名函数作为第一个参数调用导入的 plugin 函数。

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addUtilities, addComponents, e, config }) {
      // Add your custom styles here
    }),
  ]
}

插件函数接收一个对象参数,该参数可以是 destructured ,也可以是多个辅助函数:

  • addUtilities(),用于注册新的静态实用程序样式
  • matchUtilities(),用于注册新的动态实用程序样式
  • addComponents(),用于注册新的静态组件样式
  • matchComponents(),用于注册新的动态组件样式
  • addBase(),用于注册新的基本样式
  • addVariant(),用于注册自定义静态变体
  • matchVariant(),用于注册自定义动态变体
  • theme(),用于在用户的主题配置中查找值
  • config(),用于在用户的 Tailwind 配置中查找值
  • corePlugins(),用于检查核心插件是否已启用
  • e(),用于手动转义用于类名的字符串

官方插件

我们为一些流行功能开发了一些官方插件,但由于某种原因,这些功能尚不属于核心。

可以通过 npm 安装插件,然后将其添加到您的 tailwind.config.js 文件中,从而将其添加到您的项目中:

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  // ...
  plugins: [
    require('@tailwindcss/typography'),
    require('@tailwindcss/forms'),
    require('@tailwindcss/aspect-ratio'),
    require('@tailwindcss/container-queries'),
  ]
}

排版

@tailwindcss/typography 插件添加了一组 prose 类,可用于快速向来自 markdown 或 CMS 数据库等来源的内容块添加合理的印刷样式。

<article class="prose lg:prose-xl">
  <h1>Garlic bread with cheese: What the science tells us</h1>
  <p>
    For years parents have espoused the health benefits of eating garlic bread with cheese to their
    children, with the food earning such an iconic status in our culture that kids will often dress
    up as warm, cheesy loaf for Halloween.
  </p>
  <p>
    But a recent study shows that the celebrated appetizer may be linked to a series of rabies cases
    springing up around the country.
  </p>
  <!-- ... -->
</article>

Learn more about the typography plugin →

表格

@tailwindcss/forms 插件添加了一个自定义表单重置层,可以更轻松地使用实用程序类来设置表单元素的样式。

<!-- You can actually customize padding on a select element: -->
<select class="px-4 py-3 rounded-full">
  <!-- ... -->
</select>

<!-- Or change a checkbox color using text color utilities: -->
<input type="checkbox" class="rounded text-pink-500" />

Learn more about the forms plugin →

宽高比

@tailwindcss/aspect-ratio 插件是旧版浏览器中本机 aspect-ratio 支持的替代品,并添加了 aspect-w-*aspect-h-* 类,可以组合起来为元素提供固定的纵横比。

<div class="aspect-w-16 aspect-h-9">
  <iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>

Learn more about the aspect ratio plugin →

容器查询

@tailwindcss/container-queries 插件添加了新的 @{size} 变体,例如 @sm@md,可让您根据标有 @container 的父元素的尺寸而不是视口来设置元素的样式。

<div class="@container">
  <div class="@lg:text-sky-400">
    <!-- ... -->
  </div>
</div>

Learn more about the container queries plugin →


添加实用程序

addUtilitiesmatchUtilities 函数允许您在 Tailwind 的 utilities 层中注册新样式。

与 Tailwind 默认包含的实用程序一样,插件添加的实用程序只有在项目中实际使用时才会包含在生成的 CSS 中。

静态实用程序

使用 addUtilities 函数注册不支持用户提供值的简单静态实用程序:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addUtilities }) {
      addUtilities({
        '.content-auto': {
          'content-visibility': 'auto',
        },
        '.content-hidden': {
          'content-visibility': 'hidden',
        },
        '.content-visible': {
          'content-visibility': 'visible',
        },
      })
    })
  ]
}

CSS-in-JS syntax 参考中了解有关如何在 JavaScript 中表示样式的更多信息。

动态实用程序

使用 matchUtilities 函数注册映射到用户 theme 配置中定义的值的实用程序:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  theme: {
    tabSize: {
      1: '1',
      2: '2',
      4: '4',
      8: '8',
    }
  },
  plugins: [
    plugin(function({ matchUtilities, theme }) {
      matchUtilities(
        {
          tab: (value) => ({
            tabSize: value
          }),
        },
        { values: theme('tabSize') }
      )
    })
  ]
}

以这种方式定义的实用程序还支持 arbitrary values,这意味着您可以使用方括号表示法使用主题中不存在的值:

<div class="tab-[13]">
  <!-- ... -->
</div>

前缀和重要性

默认情况下,插件实用程序会自动尊重用户的 prefiximportant 偏好。

这意味着给定以下 Tailwind 配置:

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  prefix: 'tw-',
  important: true,
  // ...
}

…上面的示例插件将生成以下 CSS:

.tw-content-auto {
  content-visibility: auto !important;
}
.tw-content-hidden {
  content-visibility: hidden !important;
}
.tw-content-visible {
  content-visibility: visible !important;
}

使用修饰符

使用 addUtilities 添加的任何自定义实用程序都可以自动与修饰符一起使用:

<div class="content-auto lg:content-visible">
  <!-- ... -->
</div>

Hover, Focus, and Other States 文档中了解更多信息。

提供默认值

实用程序插件可以通过将配置对象作为 plugin 函数的第二个参数来提供默认值:

./plugins/tab-size.js
const plugin = require('tailwindcss/plugin')

module.exports = plugin(function({ matchUtilities, theme }) {
  matchUtilities(
    {
      tab: (value) => ({
        tabSize: value
      }),
    },
    { values: theme('tabSize') }
  )
}, {
  theme: {
    tabSize: {
      1: '1',
      2: '2',
      4: '4',
      8: '8',
    }
  }
})

这些值的行为与默认配置中的值一样,并且可以被最终用户覆盖或扩展。


添加组件

addComponents 函数允许您在 Tailwind 的 components 层中注册新样式。

使用它来添加更多有主见的、复杂的类,如按钮、表单控件、警报等;您经常在其他框架中看到的那种预构建的组件,您可能需要用实用程序类来覆盖它们。

要从插件添加新的组件样式,请调用 addComponents,并使用 CSS-in-JS syntax 传递您的样式:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addComponents }) {
      addComponents({
        '.btn': {
          padding: '.5rem 1rem',
          borderRadius: '.25rem',
          fontWeight: '600',
        },
        '.btn-blue': {
          backgroundColor: '#3490dc',
          color: '#fff',
          '&:hover': {
            backgroundColor: '#2779bd'
          },
        },
        '.btn-red': {
          backgroundColor: '#e3342f',
          color: '#fff',
          '&:hover': {
            backgroundColor: '#cc1f1a'
          },
        },
      })
    })
  ]
}

与 Tailwind 中的其他组件类一样,插件添加的组件类只有在项目中实际使用时才会包含在生成的 CSS 中。

前缀和重要性

默认情况下,组件类会自动尊重用户的 prefix 偏好,但不会受到用户的 important 偏好的影响。

这意味着给定以下 Tailwind 配置:

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  prefix: 'tw-',
  important: true,
  // ...
}

…上面的示例插件将生成以下 CSS:

.tw-btn {
  padding: .5rem 1rem;
  border-radius: .25rem;
  font-weight: 600;
}
.tw-btn-blue {
  background-color: #3490dc;
  color: #fff;
}
.tw-btn-blue:hover {
  background-color: #2779bd;
}
.tw-btn-red {
  background-color: #e3342f;
  color: #fff;
}
.tw-btn-red:hover {
  background-color: #cc1f1a;
}

尽管很少有充分的理由使组件声明变得重要,但如果您确实需要这样做,您可以随时手动添加 !important

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addComponents }) {
      addComponents({
        '.btn': {
          padding: '.5rem 1rem !important',
          borderRadius: '.25rem !important',
          fontWeight: '600 !important',
        },
        // ...
      })
    })
  ]
}

选择器中的所有类都会默认加上前缀,因此如果你添加更复杂的样式,例如:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  prefix: 'tw-',
  plugins: [
    plugin(function({ addComponents }) {
      const components = {
        // ...
        '.navbar-inverse a.nav-link': {
            color: '#fff',
        }
      }

      addComponents(components)
    })
  ]
}

…将生成以下 CSS:

.tw-navbar-inverse a.tw-nav-link {
    color: #fff;
}

使用修饰符

任何使用 addComponents 添加的组件类都可以自动与修饰符一起使用:

<div class="btn md:btn-lg">
  <!-- ... -->
</div>

Hover, Focus, and Other States 文档中了解更多信息。


添加基本样式

addBase 函数允许您在 Tailwind 的 base 层中注册新样式。使用它来添加诸如基本排版样式、自定全局重置或 @font-face 规则之类的内容。

要从插件添加新的基本样式,请调用 addBase,并使用 CSS-in-JS syntax 传递您的样式:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addBase, theme }) {
      addBase({
        'h1': { fontSize: theme('fontSize.2xl') },
        'h2': { fontSize: theme('fontSize.xl') },
        'h3': { fontSize: theme('fontSize.lg') },
      })
    })
  ]
}

由于基本样式旨在针对 divh1 等裸选择器,因此它们不尊重用户的 prefiximportant 配置。


添加变体

addVariantmatchVariant 函数允许您注册自己的自定义 modifiers,其使用方式与 hoverfocussupports 等内置变体一样。

静态变体

对于简单的自定义变体,使用 addVariant 函数,传递自定义变体的名称以及表示应如何修改选择器的格式字符串。

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  // ...
  plugins: [
    plugin(function({ addVariant }) {
      addVariant('optional', '&:optional')
      addVariant('hocus', ['&:hover', '&:focus'])
      addVariant('inverted-colors', '@media (inverted-colors: inverted)')
    })
  ]
}

第一个参数是用户将在其 HTML 中使用的修饰符名称,因此上述示例可以编写如下类:

<form class="flex inverted-colors:outline ...">
  <input class="optional:border-gray-300 ..." />
  <button class="bg-blue-500 hocus:bg-blue-600">...</button>
</form>

动态变体

使用 matchVariant 函数注册新的参数化变体,如内置的 supports-*data-*aria-* 变体:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ matchVariant }) {
      matchVariant(
        'nth',
        (value) => {
          return `&:nth-child(${value})`;
        },
        {
          values: {
            1: '1',
            2: '2',
            3: '3',
          }
        }
      );
    })
  ]
}

使用 matchVariant 定义的变体还支持使用方括号表示法的任意值:

<div class="nth-[3n+1]:bg-blue-500 ...">
  <!-- ... -->
</div>

如果需要,请使用 sort 选项控制生成的 CSS 的源顺序,以避免来自同一变体的其他值的优先级问题:

matchVariant("min", (value) => `@media (min-width: ${value})`, {
  sort(a, z) {
    return parseInt(a.value) - parseInt(z.value);
  },
});

父级和同级状态

您的自定义修饰符不会自动与 Tailwind 的 parentsibling 状态修饰符一起使用。

为了支持您自己的自定义修饰符的 group-*peer-* 版本,请使用特殊的 :merge 指令将它们注册为单独的变体,以确保 .group.peer 类在最终选择器中仅出现一次。

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  // ...
  plugins: [
    plugin(function({ addVariant }) {
      addVariant('optional', '&:optional')
      addVariant('group-optional', ':merge(.group):optional &')
      addVariant('peer-optional', ':merge(.peer):optional ~ &')
    })
  ]
}

扩展配置

插件可以通过向 plugin 函数提供一个对象作为第二个参数,将其自己的一组配置值合并到用户的 tailwind.config.js 配置中:

./plugins/tab-size.js
const plugin = require('tailwindcss/plugin')

module.exports = plugin(function({ matchUtilities, theme }) {
  matchUtilities(
    {
      tab: (value) => ({
        tabSize: value
      }),
    },
    { values: theme('tabSize') }
  )
}, {
  theme: {
    tabSize: {
      1: '1',
      2: '2',
      4: '4',
      8: '8',
    }
  }
})

这对于为插件生成的类提供默认 theme 值等事情很有用。


展示选项

有时,以不属于 theme 的方式配置插件是有意义的,比如您可能希望用户能够自定义插件使用的类名。

对于这种情况,您可以使用 plugin.withOptions 定义一个可以通过配置对象调用的插件。此 API 与常规 plugin API 类似,不同之处在于每个参数都应该是一个函数,该函数接收用户的 options 并返回您通常使用常规 API 传入的值:

./plugins/markdown.js
const plugin = require('tailwindcss/plugin')

module.exports = plugin.withOptions(function (options = {}) {
  return function({ addComponents }) {
    const className = options.className ?? 'markdown'

    addComponents({
      [`.${className}`]: {
        // ...
      }
    })
  }
}, function (options) {
  return {
    theme: {
      markdown: {
        // ...
      }
    },
  }
})

用户将在其 plugins 配置中注册时传递他们的选项来调用您的插件:

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    // ...
  },
  plugins: [
    require('./plugins/markdown.js')({
      className: 'wysiwyg'
    })
  ],
}

如果不需要传入任何自定义选项,用户也可以正常注册以这种方式创建的插件而无需调用它们:

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    // ...
  },
  plugins: [
    require('./plugins/markdown.js')
  ],
}

CSS-in-JS 语法

Tailwind 的插件系统要求将 CSS 规则编写为 JavaScript 对象,使用您可能从 CSS-in-JS 库(如 Emotion)中认识的相同语法,由 postcss-js 提供支持。

考虑这个简单的 CSS 规则:

.card {
  background-color: #fff;
  border-radius: .25rem;
  box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}

将其转换为 CSS-in-JS 对象如下所示:

addComponents({
  '.card': {
    'background-color': '#fff',
    'border-radius': '.25rem',
    'box-shadow': '0 2px 4px rgba(0,0,0,0.2)',
  }
})

为了方便起见,属性名称也可以用驼峰式命名法 (camelCase) 书写,并将自动转换为破折号命名法 (dash-case):

addComponents({
  '.card': {
    backgroundColor: '#fff',
    borderRadius: '.25rem',
    boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
  }
})

还支持嵌套(由 postcss-nested 提供支持),使用您可能熟悉的 Sass 或 Less 的相同语法:

addComponents({
  '.card': {
    backgroundColor: '#fff',
    borderRadius: '.25rem',
    boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
    '&:hover': {
      boxShadow: '0 10px 15px rgba(0,0,0,0.2)',
    },
    '@media (min-width: 500px)': {
      borderRadius: '.5rem',
    }
  }
})

可以在同一个对象中定义多个规则:

addComponents({
  '.btn': {
    padding: '.5rem 1rem',
    borderRadius: '.25rem',
    fontWeight: '600',
  },
  '.btn-blue': {
    backgroundColor: '#3490dc',
    color: '#fff',
    '&:hover': {
      backgroundColor: '#2779bd'
    },
  },
  '.btn-red': {
    backgroundColor: '#e3342f',
    color: '#fff',
    '&:hover': {
      backgroundColor: '#cc1f1a'
    },
  },
})

…或者作为对象数组,以防您需要重复相同的键:

addComponents([
  {
    '@media (min-width: 500px)': {
      // ...
    }
  },
  {
    '@media (min-width: 500px)': {
      // ...
    }
  },
  {
    '@media (min-width: 500px)': {
      // ...
    }
  },
])