Tailwind CSS on GitHub

配置变体

为需要的工具类配置变体。

Overview

配置文件中的variants配置项,可以控制哪一个核心插件需要什么样的变体:

// tailwind.config.js
module.exports = {
  variants: {
    extend: {
      backgroundColor: ['active'],
      // ...
      borderColor: ['focus-visible', 'first'],
      // ...
      textColor: ['visited'],
    }
  },
}

每个属性都是一个核心插件名,为该插件配置需要生成的变体数组。

下面的变体是开箱即用的:

VariantDescription
responsiveResponsive variants like sm, md, lg, and xl.
darkTargets dark mode.
motion-safeTargets the prefers-reduced-motion: no-preference media query.
motion-reduceTargets the prefers-reduced-motion: reduce media query.
firstTargets the first-child pseudo-class.
lastTargets the last-child pseudo-class.
oddTargets the odd-child pseudo-class.
evenTargets the even-child pseudo-class.
visitedTargets the visited pseudo-class.
checkedTargets the checked pseudo-class.
group-hoverTargets an element when a marked parent matches the hover pseudo-class.
group-focusTargets an element when a marked parent matches the focus pseudo-class.
focus-withinTargets the focus-within pseudo-class.
hoverTargets the hover pseudo-class.
focusTargets the focus pseudo-class.
focus-visibleTargets the focus-visible pseudo-class.
activeTargets the active pseudo-class.
disabledTargets the disabled pseudo-class.

关于变体是如何工作的,可以查看自适应变体暗黑变体、以及hover、focus及其他变体


启用额外的变体

如果你想在插件默认值之外启用额外的变体,你可以使用extend关键字来配置你的变体,就像你可以在theme配置项中使用extend一样:

// tailwind.config.js
module.exports = {
  variants: {
    // The 'active' variant will be generated in addition to the defaults
    extend: {
      backgroundColor: ['active']
    }
  },
}

因为变体的顺序非常重要,所以在extend字段下添加的任何变体都会使用合理的默认变体顺序自动排序。如果需要,可以使用variantOrder选项定制顺序。


覆盖默认变体

直接在variants字段下定制变体,将会覆盖该插件的默认变体:

// tailwind.config.js
module.exports = {
  variants: {
    // Only 'active' variants will be generated
    backgroundColor: ['active'],
  },
}

当覆盖默认的变体时,确保启用你想要的的所有变体,而不仅仅是您想要添加的这个新变体。

变体排序

重要的是要注意,当覆盖变体时,将按照数组列出的顺序生成变体,因此数组末尾的变体将优先于数组开头的变体。

例如,focus变体对于backgroundColor类具有最高的优先级,而hover变体对于borderColor类具有最高的优先级:

// tailwind.config.js
module.exports = {
  variants: {
    backgroundColor: ['hover', 'focus'],
    borderColor: ['focus', 'hover'],
  },
}
/* Generated CSS */

.bg-black { background-color: #000 }
.bg-white { background-color: #fff }
/* ... */

.hover\:bg-black:hover { background-color: #000 }
.hover\:bg-white:hover { background-color: #fff }
/* ... */

.focus\:bg-black:focus { background-color: #000 }
.focus\:bg-white:focus { background-color: #fff }
/* ... */

.border-black { border-color: #000 }
.border-white { border-color: #fff }
/* ... */

.focus\:border-black:focus { border-color: #000 }
.focus\:border-white:focus { border-color: #fff }
/* ... */

.hover\:border-black:hover { border-color: #000 }
.hover\:border-white:hover { border-color: #fff }
/* ... */

在下面的HTML中:

<input class="focus:bg-white hover:bg-black focus:border-white hover:border-black">

如果input同时被hover以及focus,背景色变成白色,但是边框是黑色

以这种方式生成变体为最终用户提供了最大的灵活性,但它也是一种锋利的工具,如果不小心,可能会产生意想不到的后果。我们建议在任何可能的情况下启用额外的变体,而不是覆盖默认值,并且只将此特性用作一个缓冲通道。


特殊的变体

自适应

responsive变体的特别之处在于,它的权重不受配置列表里的顺序影响。

这是因为responsive自动与其他变体堆叠,这意味着如果你指定一个工具类的responsivehover变体,Tailwind将生成responsive hover变体:

// tailwind.config.js
module.exports = {
  variants: {
    backgroundColor: ['responsive', 'hover'],
    borderColor: ['responsive', 'focus'],
  },
}

无论responsive出现在配置数组的什么位置,它生成的时候都会被放到样式表的末尾。

无论出于何种原因,如果你想自定义此行为,你可以使用@tailwind screens屏幕指令来指定响应式变体应该插入的位置。

暗黑模式、

The dark, motion-safe, and motion-reduce variants also stack with other variants, but unlike responsive, they stack in the same "slot", so you can combine them with both responsive and simple state variants, but not with each other.

The order of these variants matter relative to each other, but not relative to other variants. There is just about no situation imaginable where these would conflict with each other in practice, so this ends up being a non-issue anyways.

You can include these variants in any order in your variants configuration and never notice the difference.

Default

You can use the special DEFAULT variant to control where the normal, non-prefixed version of a utility is generated relative to the other variants.

This is an advanced feature and only really useful if you have a custom variant (like children in the example below) that should have a lower precedence than the normal version of a utility.

// tailwind.config.js
module.exports = {
  variants: {
    backgroundColor: ['children', 'DEFAULT', 'hover', 'focus'],
  },
}
/* Generated CSS */

.children\:bg-black > * { background-color: #000; }
.children\:bg-white > * { background-color: #fff; }

.bg-black { background-color: #000 }
.bg-white { background-color: #fff }
/* ... */

.hover\:bg-black:hover { background-color: #000 }
.hover\:bg-white:hover { background-color: #fff }
/* ... */

.focus\:bg-black:focus { background-color: #000 }
.focus\:bg-white:focus { background-color: #fff }
/* ... */

Learn more about creating custom variants in the variant plugin documentation.


Using custom variants

If you've written or installed a plugin that adds a new variant, you can enable that variant by including it in your variants configuration just like if it were a built-in variant.

For example, the tailwindcss-interaction-variants plugin adds a group-disabled variant (among others):

// tailwind.config.js
{
  variants: {
    backgroundColor: ['responsive', 'hover', 'focus', 'group-disabled'],
  },
  plugins: [
    require('tailwindcss-interaction-variants')(),
  ],
}

Learn more about creating custom variants in the variant plugin documentation.

Ordering custom variants

If you'd like to specify a default sort position for a custom variant, override your variantOrder to include the custom variant:

// tailwind.config.js
module.exports = {
  // ...
  variantOrder: [
    'first',
    'last',
    'odd',
    'even',
    'visited',
    'checked',
    'group-hover',
    'group-focus',
    'focus-within',
    'hover',
    'focus',
    'focus-visible',
    'active',
    'group-disabled', // Custom variant
    'disabled',
  ],
  variants: {
    extend: {
      backgroundColor: ['group-disabled'],
    }
  }
}

You'll need to specify the entire list when overriding the variantOrder to include any custom variants.


Default variants reference

Here is a complete reference of Tailwind's default variants configuration, which can be useful when you'd like to add a new variant while preserving the defaults.

// Default configuration
module.exports = {
  // ...
  variants: {
    accessibility: ['responsive', 'focus-within', 'focus'],
    alignContent: ['responsive'],
    alignItems: ['responsive'],
    alignSelf: ['responsive'],
    animation: ['responsive'],
    appearance: ['responsive'],
    backgroundAttachment: ['responsive'],
    backgroundClip: ['responsive'],
    backgroundColor: ['responsive', 'dark', 'group-hover', 'focus-within', 'hover', 'focus'],
    backgroundImage: ['responsive'],
    backgroundOpacity: ['responsive', 'group-hover', 'focus-within', 'hover', 'focus'],
    backgroundPosition: ['responsive'],
    backgroundRepeat: ['responsive'],
    backgroundSize: ['responsive'],
    borderCollapse: ['responsive'],
    borderColor: ['responsive', 'dark', 'group-hover', 'focus-within', 'hover', 'focus'],
    borderOpacity: ['responsive', 'group-hover', 'focus-within', 'hover', 'focus'],
    borderRadius: ['responsive'],
    borderStyle: ['responsive'],
    borderWidth: ['responsive'],
    boxShadow: ['responsive', 'group-hover', 'focus-within', 'hover', 'focus'],
    boxSizing: ['responsive'],
    clear: ['responsive'],
    container: ['responsive'],
    cursor: ['responsive'],
    display: ['responsive'],
    divideColor: ['responsive', 'dark'],
    divideOpacity: ['responsive'],
    divideStyle: ['responsive'],
    divideWidth: ['responsive'],
    fill: ['responsive'],
    flex: ['responsive'],
    flexDirection: ['responsive'],
    flexGrow: ['responsive'],
    flexShrink: ['responsive'],
    flexWrap: ['responsive'],
    float: ['responsive'],
    fontFamily: ['responsive'],
    fontSize: ['responsive'],
    fontSmoothing: ['responsive'],
    fontStyle: ['responsive'],
    fontVariantNumeric: ['responsive'],
    fontWeight: ['responsive'],
    gap: ['responsive'],
    gradientColorStops: ['responsive', 'dark', 'hover', 'focus'],
    gridAutoColumns: ['responsive'],
    gridAutoFlow: ['responsive'],
    gridAutoRows: ['responsive'],
    gridColumn: ['responsive'],
    gridColumnEnd: ['responsive'],
    gridColumnStart: ['responsive'],
    gridRow: ['responsive'],
    gridRowEnd: ['responsive'],
    gridRowStart: ['responsive'],
    gridTemplateColumns: ['responsive'],
    gridTemplateRows: ['responsive'],
    height: ['responsive'],
    inset: ['responsive'],
    justifyContent: ['responsive'],
    justifyItems: ['responsive'],
    justifySelf: ['responsive'],
    letterSpacing: ['responsive'],
    lineHeight: ['responsive'],
    listStylePosition: ['responsive'],
    listStyleType: ['responsive'],
    margin: ['responsive'],
    maxHeight: ['responsive'],
    maxWidth: ['responsive'],
    minHeight: ['responsive'],
    minWidth: ['responsive'],
    objectFit: ['responsive'],
    objectPosition: ['responsive'],
    opacity: ['responsive', 'group-hover', 'focus-within', 'hover', 'focus'],
    order: ['responsive'],
    outline: ['responsive', 'focus-within', 'focus'],
    overflow: ['responsive'],
    overscrollBehavior: ['responsive'],
    padding: ['responsive'],
    placeContent: ['responsive'],
    placeItems: ['responsive'],
    placeSelf: ['responsive'],
    placeholderColor: ['responsive', 'dark', 'focus'],
    placeholderOpacity: ['responsive', 'focus'],
    pointerEvents: ['responsive'],
    position: ['responsive'],
    resize: ['responsive'],
    ringColor: ['responsive', 'dark', 'focus-within', 'focus'],
    ringOffsetColor: ['responsive', 'dark', 'focus-within', 'focus'],
    ringOffsetWidth: ['responsive', 'focus-within', 'focus'],
    ringOpacity: ['responsive', 'focus-within', 'focus'],
    ringWidth: ['responsive', 'focus-within', 'focus'],
    rotate: ['responsive', 'hover', 'focus'],
    scale: ['responsive', 'hover', 'focus'],
    skew: ['responsive', 'hover', 'focus'],
    space: ['responsive'],
    stroke: ['responsive'],
    strokeWidth: ['responsive'],
    tableLayout: ['responsive'],
    textAlign: ['responsive'],
    textColor: ['responsive', 'dark', 'group-hover', 'focus-within', 'hover', 'focus'],
    textDecoration: ['responsive', 'group-hover', 'focus-within', 'hover', 'focus'],
    textOpacity: ['responsive', 'group-hover', 'focus-within', 'hover', 'focus'],
    textOverflow: ['responsive'],
    textTransform: ['responsive'],
    transform: ['responsive'],
    transformOrigin: ['responsive'],
    transitionDelay: ['responsive'],
    transitionDuration: ['responsive'],
    transitionProperty: ['responsive'],
    transitionTimingFunction: ['responsive'],
    translate: ['responsive', 'hover', 'focus'],
    userSelect: ['responsive'],
    verticalAlign: ['responsive'],
    visibility: ['responsive'],
    whitespace: ['responsive'],
    width: ['responsive'],
    wordBreak: ['responsive'],
    zIndex: ['responsive', 'focus-within', 'focus']
  }
}