「及時」模式:全新世代的 Tailwind CSS
Tailwind CSS on GitHub

配置變化模式 (Configuring Variants)

為你的專案配置啟用哪些功能變化模式。

Overview

tailwind.config.js 檔案中的 variants 是你控制每個核心插件應該啟用哪些變化模式的地方。

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

每個屬性都是一個核心插件的名稱,而要應用在這個核心插件的變化模式必須以陣列形式表示。

以下為支援開箱即用的變化模式:

變化模式描述
responsive響應式變化模式,如 smmdlgxl
dark觸發深色模式。
motion-safe觸發 prefers-reduced-motion: no-preference 媒體查詢 (media query)。
motion-reduce觸發 prefers-reduced-motion: reduce 媒體查詢 (media query)。
first觸發 first-child pseudo-class。
last觸發 last-child pseudo-class。
odd觸發 odd-child pseudo-class。
even觸發 even-child pseudo-class。
visited觸發 visited pseudo-class。
checked觸發 checked pseudo-class。
group-hover當被標記的父層 (parent) 符合 hover pseudo-class 時,觸發元素。
group-focus當被標記的父層 (parent) 符合 focus pseudo-class 時,觸發元素。
focus-within觸發 focus-within pseudo-class。
hover觸發 hover pseudo-class。
focus觸發 focus pseudo-class。
focus-visible觸發 focus-visible pseudo-class。
active觸發 active pseudo-class。
disabled觸發 disabled pseudo-class。

更多有關變化模式如何作用的資訊,請閱讀我們的文件 響應式變化模式深色模式變化模式hover、focus 和其他狀態變化模式


啟用額外變化模式

如果你想為插件啟用除了預設值以外的變化模式,你可以使用 extend 配置你的變化模式,如同你如何在 theme 使用 extend

// tailwind.config.js
module.exports = {
  variants: {
    // 除預設值外,還將產生 'active' 變化模式
    extend: {
      backgroundColor: ['active']
    }
  },
}

因為 變化模式的順序很重要,在 extend 下新增的任何變化模式都會使用合理的預設變化模式順序自動為你排序。若有需要,你可以選擇使用 variantOrder 客製化順序。


覆蓋預設變化模式

任何在 variants 下直接配置的變化模式,將覆蓋該插件的預設變化模式。

// tailwind.config.js
module.exports = {
  variants: {
    // 只會產生 'active' 變化模式
    backgroundColor: ['active'],
  },
}

當覆蓋預設變化模式時,確保你總是指定 所有 你想啟用的變化模式,而不僅僅是你想新增的新變化模式。

排序變化模式

值得注意的是,當覆蓋變化模式時,變化模式會按照你指定的順序生成,因此在清單最後的變化模式將優先於在清單一開始的變化模式。

例如,在這裡 focus 變化模式於 backgroundColor 功能中具有最高優先權,但於 borderColor 功能中則是 hover 變化模式具有最高優先權。

// tailwind.config.js
module.exports = {
  variants: {
    backgroundColor: ['hover', 'focus'],
    borderColor: ['focus', 'hover'],
  },
}
/* 產生 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">

…如果輸入框同時 hover focus,背景將是白色的,但邊框將是黑色的。

作為終端使用者,按順序產生變化模式能為你帶來最大的彈性,但它也是一個利器,如果你不小心,可能會產生意想不到的後果。我們建議 啟用額外變化模式 而不是盡可能地覆蓋預設值,並且只把此功能視為應急的辦法。


特殊變化模式

響應式

在 Tailwind 中,responsive 變化模式是一種特殊的情況,並且 不會 受到你在變化模式配置中列出的順序的影響。

這是因為 responsive 變化模式會自動與其他變化模式 堆疊 在一起,這意味著如果你為一個功能指定了 responsivehover 變化模式,Tailwind 也會產生 responsive hover 變化模式。

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

不論 responsive 出現在 variants 清單中的哪裡,響應式變化模式都會被群組在一起,並且預設插入樣式表的最後,以避免特異性問題。

如果你基於任何原因想要客製化此行為,你可以使用 @tailwind screens 指令來指定響應式變化模式應該插入的位置。

Dark、motion-safe 和 motion-reduce

darkmotion-safemotion-reduce 變化模式也會與其他變化模式堆疊,但與 responsive 不同的是,它們疊加在同一個「slot (插槽)」中,所以你可以將它們與 responsive 和簡單狀態變化模式結合,但不能互相結合。

這些變化模式的順序對於它們彼此之間來說很重要,但對於其他變化模式來說不重要。在實際上,幾乎無法想像這些變化模式會有相互衝突的情況,所以無論如何,這最終都不會成為問題。

你可以在 variants 配置中,以任何順序引入這些變化模式,並且永遠不會注意到它們之間的差異。

預設值

相較於其他變化模式,你可以使用特殊的 DEFAULT 變化模式來控制產生一個普通且無前綴版本的功能。

這是一個進階功能,只有當你有客製化變化模式 (像是下方範例中的 children),它的優先級低於普通版本的功能時,此功能才真正有用。

// tailwind.config.js
module.exports = {
  variants: {
    backgroundColor: ['children', 'DEFAULT', 'hover', 'focus'],
  },
}
/* 產生 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 }
/* ... */

變化模式插件文件 中,了解更多關於新增客製化變化模式的資訊。


使用客製化變化模式

如果你撰寫或安裝 插件,這個插件增加了一個新的變化模式,你可以在你的變化模式配置中引入它來啟用這個變化模式,就像是個內建變化模式一樣。

例如,tailwindcss-interaction-variants 插件 增加了一個 group-disabled 變化模式 (其中之一):

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

變化模式插件文件 中,了解更多關於新增客製化變化模式的資訊。

排序客製化變化模式

如果你想要為客製化變化模式指定一個預設的排序位置,覆蓋你的 variantOrder 來包含客製化變化模式。

// 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', // 客製化變化模式
    'disabled',
  ],
  variants: {
    extend: {
      backgroundColor: ['group-disabled'],
    }
  }
}

你需要在覆蓋 variantOrder 時指定整個清單,來包含任何客製化變化模式。


預設變化模式參考

這是 Tailwind 預設變化模式配置的完整參考,當你想新增一個新的變化模式且同時保留預設值時,它會很有用。

// Default configuration
module.exports = {
  // ...
  variants: {
    accessibility: ['responsive', 'focus-within', 'focus'],
    alignContent: ['responsive'],
    alignItems: ['responsive'],
    alignSelf: ['responsive'],
    animation: ['responsive'],
    appearance: ['responsive'],
    backdropBlur: ['responsive'],
    backdropBrightness: ['responsive'],
    backdropContrast: ['responsive'],
    backdropFilter: ['responsive'],
    backdropGrayscale: ['responsive'],
    backdropHueRotate: ['responsive'],
    backdropInvert: ['responsive'],
    backdropOpacity: ['responsive'],
    backdropSaturate: ['responsive'],
    backdropSepia: ['responsive'],
    backgroundAttachment: ['responsive'],
    backgroundBlendMode: ['responsive'],
    backgroundClip: ['responsive'],
    backgroundColor: ['responsive', 'dark', 'group-hover', 'focus-within', 'hover', 'focus'],
    backgroundImage: ['responsive'],
    backgroundOpacity: ['responsive', 'dark', 'group-hover', 'focus-within', 'hover', 'focus'],
    backgroundPosition: ['responsive'],
    backgroundRepeat: ['responsive'],
    backgroundSize: ['responsive'],
    backgroundOrigin: ['responsive'],
    blur: ['responsive'],
    borderCollapse: ['responsive'],
    borderColor: ['responsive', 'dark', 'group-hover', 'focus-within', 'hover', 'focus'],
    borderOpacity: ['responsive', 'dark', 'group-hover', 'focus-within', 'hover', 'focus'],
    borderRadius: ['responsive'],
    borderStyle: ['responsive'],
    borderWidth: ['responsive'],
    boxDecorationBreak: ['responsive'],
    boxShadow: ['responsive', 'group-hover', 'focus-within', 'hover', 'focus'],
    boxSizing: ['responsive'],
    brightness: ['responsive'],
    clear: ['responsive'],
    container: ['responsive'],
    contrast: ['responsive'],
    cursor: ['responsive'],
    display: ['responsive'],
    divideColor: ['responsive', 'dark'],
    divideOpacity: ['responsive', 'dark'],
    divideStyle: ['responsive'],
    divideWidth: ['responsive'],
    dropShadow: ['responsive'],
    fill: ['responsive'],
    filter: ['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'],
    grayscale: ['responsive'],
    gridAutoColumns: ['responsive'],
    gridAutoFlow: ['responsive'],
    gridAutoRows: ['responsive'],
    gridColumn: ['responsive'],
    gridColumnEnd: ['responsive'],
    gridColumnStart: ['responsive'],
    gridRow: ['responsive'],
    gridRowEnd: ['responsive'],
    gridRowStart: ['responsive'],
    gridTemplateColumns: ['responsive'],
    gridTemplateRows: ['responsive'],
    height: ['responsive'],
    hueRotate: ['responsive'],
    inset: ['responsive'],
    invert: ['responsive'],
    isolation: ['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'],
    mixBlendMode: ['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', 'dark', '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', 'dark', 'focus-within', 'focus'],
    ringWidth: ['responsive', 'focus-within', 'focus'],
    rotate: ['responsive', 'hover', 'focus'],
    saturate: ['responsive'],
    scale: ['responsive', 'hover', 'focus'],
    sepia: ['responsive'],
    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', 'dark', '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']
  }
}