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

Hover, Focus 以及其他狀態

使用 Tailwind 功能來建立元素 (elements) 的 hover, focus 等狀態樣式。

概述

就像是 Tailwind 在處理 響應式設計 一樣,使用合適的狀態前綴詞變化模式 (variants) 來設計元素的 hover, focus 等樣式。

<form>
  <input class="border border-transparent focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-transparent ...">
  <button class="bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:ring-opacity-50 ...">
    Sign up
  </button>
</form>

因為檔案大小的考量,並非所有的狀態變化模式都預設包含在功能中,但是我們盡了最大的努力建立出最常見的組合。

想知道全部的預設變化模式,請 參考 頁面最底部變化模式的完整列表。

如果你需要使用 Tailwind 不支援的狀態,可以參閱 建立自定義變化模式插件 來擴充所需要的變化模式。


Hover

新增 hover: 前綴詞讓元素處於 hover 狀態時才啟用該功能。

<button class="bg-red-500 hover:bg-red-700 ...">
  Hover me
</button>

預設狀況下,hover 變化模式支援下列核心功能:

  • backgroundColor
  • backgroundOpacity
  • borderColor
  • borderOpacity
  • boxShadow
  • gradientColorStops
  • opacity
  • rotate
  • scale
  • skew
  • textColor
  • textDecoration
  • textOpacity
  • translate

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 hover 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      padding: ['hover'],
    }
  },
}

Focus

新增 focus: 前綴詞讓元素處於 focus 狀態時才啟用該功能。

<input class="focus:ring-2 focus:ring-blue-600 ...">

預設狀況下,focus 變化模式支援下列核心功能:

  • accessibility
  • backgroundColor
  • backgroundOpacity
  • borderColor
  • borderOpacity
  • boxShadow
  • gradientColorStops
  • opacity
  • outline
  • placeholderColor
  • placeholderOpacity
  • ringColor
  • ringOffsetColor
  • ringOffsetWidth
  • ringOpacity
  • ringWidth
  • rotate
  • scale
  • skew
  • textColor
  • textDecoration
  • textOpacity
  • translate
  • zIndex

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 focus 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      maxHeight: ['focus'],
    }
  },
}

Active

Add the active: prefix to only apply a utility when an element is active. 新增 active: 前綴詞讓元素處於 active 狀態時才啟用該功能。

<button class="bg-green-500 active:bg-green-700 ...">
  Click me
</button>

預設狀況下,active 不支援任何核心功能

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 active 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      backgroundColor: ['active'],
    }
  },
}

Group-hover

如果你需要在 hover 一個父元素時,讓其一個子元素產生樣式變化,在父元素加上 group class 並且在子元素新增 group-hover: 前綴詞。

New Project

Create a new project from a variety of starting templates.

<div class="group border-indigo-500 hover:bg-white hover:shadow-lg hover:border-transparent ...">
  <p class="text-indigo-600 group-hover:text-gray-900 ...">New Project</p>
  <p class="text-indigo-500 group-hover:text-gray-500 ...">Create a new project from a variety of starting templates.</p>
</div>

預設狀況下,group-hover 變化模式支援下列核心功能:

  • backgroundColor
  • backgroundOpacity
  • borderColor
  • borderOpacity
  • boxShadow
  • opacity
  • textColor
  • textDecoration
  • textOpacity

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 group-hover 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      divideColor: ['group-hover'],
    }
  },
}

Group-focus

group-focus 變化模式的功能就像 group-hover 一樣,除了 focus:

<button class="group bg-yellow-500 focus:bg-yellow-600 ...">
  <svg class="text-white group-focus:text-yellow-300 ..."></svg>
  Bookmark
</button>

預設狀況下,group-focus 不支援任何核心功能

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 group-focus 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      backgroundColor: ['group-focus'],
    }
  },
}

Focus-within

Add the focus-within: prefix to only apply a utility when that element or any of its descendants have focus.

<form>
  <div class="text-gray-400 focus-within:text-gray-600 ...">
    <div class="...">
      <svg fill="currentColor"></svg>
    </div>
    <input class="focus:ring-2 focus:ring-gray-300 ...">
  </div>
</form>

預設狀況下,focus-within 變化模式支援下列核心功能:

  • accessibility
  • backgroundColor
  • backgroundOpacity
  • borderColor
  • borderOpacity
  • boxShadow
  • opacity
  • outline
  • ringColor
  • ringOffsetColor
  • ringOffsetWidth
  • ringOpacity
  • ringWidth
  • textColor
  • textDecoration
  • textOpacity
  • zIndex

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 focus-within 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      scale: ['focus-within'],
    }
  },
}

Focus-visible

注意!目前 focus-visible 需要 JS 和 PostCSS polyfills 來提供足夠的瀏覽器支援。

新增 focus-visible: 前綴詞讓元素處於 focus 狀態且使用者使用鍵盤時才啟用該功能。

<button class="focus:ring-2 focus:ring-red-500 ...">
  Ring on focus
</button>
<button class="focus:outline-none focus-visible:ring-2 focus-visible:ring-rose-500 ...">
  Ring on focus-visible
</button>

請注意目前只有 Chrome、Edge 和 Firefox 支援原生的 focus-visible 功能。為了完整的瀏覽器支援,你應該要安裝設定 focus-visible JS polyfillfocus-visible PostCSS polyfill,並在你的 PostCSS 插件列表中於 Tailwind 之後 引用:

// postcss.config.js
module.exports = {
  plugins: {
    tailwindcss: {},
    'postcss-focus-visible': {},
    autoprefixer: {}
  }
}

預設狀況下,focus-visible 不支援任何核心功能

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 focus-visible 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      textDecoration: ['focus-visible'],
    }
  },
}

Motion-safe

新增 motion-safe: 前綴詞讓 prefers-reduced-motion 符合 no-preference 時才啟用該功能。

舉例來說,這個按鈕只有在使用者沒有啟用 “Reduce motion” 時並且 hover 時才會有動畫效果。

<button class="transform motion-safe:hover:scale-110 ...">
  Hover me
</button>

跟其他大部分的變化模式不一樣,motion-safe 可以結合響應式和其他變化模式,像是 hover 一起使用:

<div class="sm:motion-safe:hover:animate-spin">
  <!-- ... -->
</div>

預設狀況下,motion-safe 不支援任何核心功能

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 motion-safe 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      animation: ['motion-safe'],
    }
  },
}

Motion-reduce

新增 motion-reduce: 前綴詞讓 prefers-reduced-motion 符合 reduce 時才啟用該功能。

舉例來說,在預設情況下,這個按鈕在 hover 會產生動畫,但是如果使用者啟用 “Reduce motion”,則動畫就會失效。

<button class="transform hover:scale-110 motion-reduce:transform-none ...">
  Hover me
</button>

跟其他大部分的變化模式不一樣,motion-reduce 可以結合響應式和其他變化模式,像是 hover 一起使用:

<div class="sm:motion-reduce:hover:animate-none">
  <!-- ... -->
</div>

預設狀況下,motion-reduce 不支援任何核心功能

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 motion-reduce 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      animation: ['motion-reduce'],
    }
  },
}

Disabled

新增 disabled: 前綴詞讓元素處於 disabled 狀態時才啟用該功能。

<button class="disabled:opacity-50 ...">
  Submit
</button>
<button class="disabled:opacity-50 ..." disabled>
  Submit
</button>

預設狀況下,disabled 不支援任何核心功能

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 disabled 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      opacity: ['disabled'],
    }
  },
}

Visited

新增 visited: 前綴詞讓連結為 visited 時才啟用該功能。

<a href="#" class="text-blue-600 visited:text-purple-600 ...">Link</a>

預設狀況下,visited 不支援任何核心功能

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 visited 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      textColor: ['visited'],
    }
  },
}

Checked

新增 checked: 前綴詞讓 radio 或 checkbox 的狀態為 checked 時才啟用該功能。

<input type="checkbox" class="appearance-none checked:bg-blue-600 checked:border-transparent ...">

預設狀況下,checked 不支援任何核心功能

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 checked 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      backgroundColor: ['checked'],
      borderColor: ['checked'],
    }
  },
}

First-child

新增 first: 前綴詞使得當該元素為其父元素的第一個子元素 (first-child) 時才啟用該功能。這在元素透過某些迴圈方式產生時特別有用。

<div class="...">
  <div v-for="item in items" class="transform first:rotate-45 ...">
    {{ item }}
  </div>
</div>

It’s important to note that you should add any first: utilities to the child element, not the parent element. 需要注意的是,你應該要在任意的子元素上新增 first: 而不是父元素。

預設狀況下,first-child 不支援任何核心功能

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 first 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      borderWidth: ['first'],
    }
  },
}

Last-child

新增 last: 前綴詞使得當該元素為其父元素的最後一個子元素 (last-child) 時才啟用該功能。這在元素透過某些迴圈方式產生時特別有用。

<div class="...">
  <div v-for="item in items" class="transform last:rotate-45 ...">
    {{ item }}
  </div>
</div>

需要注意的是,你應該要在任意的子元素上新增 last: 而不是父元素。

預設狀況下,last-child 不支援任何核心功能

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 last 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      borderWidth: ['last'],
    }
  },
}

Odd-child

新增 odd: 前綴詞使得當該元素為其父元素的奇數子元素 (odd-child) 時才啟用該功能。這在元素透過某些迴圈方式產生時特別有用。

<div class="...">
  <div v-for="item in items" class="transform odd:rotate-45 ...">
    {{ item }}
  </div>
</div>

It’s important to note that you should add any odd: utilities to the child element, not the parent element. 需要注意的是,你應該要在任意的子元素上新增 odd: 而不是父元素。

預設狀況下,odd-child 不支援任何核心功能

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 odd 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      backgroundColor: ['odd'],
    }
  },
}

Even-child

新增 even: 前綴詞使得當該元素為其父元素的偶數子元素 (even-child) 時才啟用該功能。這在元素透過某些迴圈方式產生時特別有用。

<div class="...">
  <div v-for="item in items" class="transform even:rotate-45 ...">
    {{ item }}
  </div>
</div>

需要注意的是,你應該要在任意的子元素上新增 even: 而不是父元素。

預設狀況下,even-child 不支援任何核心功能

你可以在 tailwind.config.js 文件中的 variants 部分開關特定功能的 even 變化模式:

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      backgroundColor: ['even'],
    }
  },
}

結合響應式前綴詞一起使用

狀態變化模式也是響應式的,舉例來說,這代表你可以讓同一個元素依照不同的斷點使用不同的 hover 樣式。

要讓狀態變化模式在一個特定的斷點作用,需要將響應式前綴詞添加在狀態前綴詞的前面:

<button class="... hover:bg-green-500 sm:hover:bg-blue-500">
  <!-- ... -->
</button>

為自定義功能新增變化模式

你可以為你自定義的 CSS class 新增狀態變化模式,只要使用 @variants 指令將它們給囊括著:

/* Input: */
@variants group-hover, hover, focus {
  .banana {
    color: yellow;
  }
}

/* Output: */
.banana {
  color: yellow;
}
.group:hover .group-hover\:banana {
  color: yellow;
}
.hover\:banana:hover {
  color: yellow;
}
.focus\:banana:focus {
  color: yellow;
}

@variants 指令 可以獲得更多的資訊。


建立自定義變化模式

你可以藉由撰寫自定義的變化模式插件建立你自己的狀態變化模式,如果 Tailwind 預設不支援的話。

舉例來說,這個簡單的插件新增 required pseudo-class 變化模式的支援:

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

module.exports = {
  plugins: [
    plugin(function({ addVariant, e }) {
      addVariant('required', ({ modifySelectors, separator }) => {
        modifySelectors(({ className }) => {
          return `.${e(`required${separator}${className}`)}:required`
        })
      })
    })
  ]
}

新增變化模式 中可以獲得更多關於撰寫變化模式插件的資訊。


預設的變化模式參考

受限於檔案大小的考量,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']
  }
}