iT邦幫忙

2021 iThome 鐵人賽

DAY 10
0
Modern Web

TailwindCSS - 從零開始系列 第 10

TailwindCSS 從零開始 - 設定自己想要的 TailwindCSS 樣式 Variant

tailwindcss

前面有提到 TailwindCSS 在所有的 DOM 元素前面幾乎都可以使用偽類變體來控制,但幾乎也就代表了沒有全部的元素都可以這樣做,那如果專案需要設定效果,但 TailwindCSS 沒有支援怎麼辦。

那就自己用 CSS 刻阿!然後這篇就到這裡結束了(被揍)

貼心的 TailwindCSS 也提供可以客製化的方式給開發者。

使用 Variant 來設定自己想要的樣式

基本上許多常用的效果 TailwindCSS 都已經幫開發者設定好,那為什麼要可以自訂呢?

因為還是有許多較少使用的樣式,沒有被設定。因為較少使用,所以要用到的時候,會發現我打了樣式,卻沒有出現效果...

例如:

我想在 hover 效果的時候使用 border-dashed 雙外框線效果,就沒有出現。

demo: https://codepen.io/hnzxewqw/pen/poeBpoK

雖然我也可以每次要用的時候再去翻文件就好,但就是每次要寫就要去找一次,有點麻煩。

可能常寫也會記得啦!但如果可以都不要寫不是更好(誤)...

建構屬於自己的設定檔

預設設定檔

在文件中有一個指令

npx tailwindcss init

會將專案根目錄建立一個最基本的 tailwind.config.js 檔案,也就是一開始安裝的時候出現的那支,會看到內容都是空的。

// tailwind.config.js
module.exports = {
  purge: [],
  darkMode: false, // 或 'media' 或 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}

完整的設定檔

如果想看到 TailwindCSS 完整的設定檔,可以輸入指令

npx tailwindcss init --full

這時候就會看到 TailwindCSS 完整的預設配置檔,因礙於篇幅關係就不再放到文章中,可點選連結查看。

建議覆蓋預設配置檔的內容

雖然得到完整的預設配置檔,可以改成專案需求的樣式,但官方文件建議只在需要客製化地方,使用覆蓋的方式去取代原本預設的樣式,會是比較推薦的做法,避免一次引入太多沒使用到的樣式,讓 CSS 變得很肥。

官方有給一個使用覆蓋預設樣式的範例:

// `tailwind.config.js` 範例檔案
const colors = require('tailwindcss/colors')

module.exports = {
  theme: {
    colors: {
      gray: colors.coolGray,
      blue: colors.lightBlue,
      red: colors.rose,
      pink: colors.fuchsia,
    },
    fontFamily: {
      sans: ['Graphik', 'sans-serif'],
      serif: ['Merriweather', 'serif'],
    },
    extend: {
      spacing: {
        '128': '32rem',
        '144': '36rem',
      },
      borderRadius: {
        '4xl': '2rem',
      }
    }
  },
  variants: {
    extend: {
      borderColor: ['focus-visible'],
      opacity: ['disabled'],
    }
  }
}

可以看見此範例覆蓋了以下幾個內容:

  1. 主題 theme 下有兩個子項目:字型 fontFamily 與延伸區塊 extend 改變 間距 spacing 以及 邊框弧度 borderRadius
  2. 變化模式 variants 的項目:邊框線條 borderColor透明度 opacity

更改 tailwind.config.js 的 Variants 內容

本篇重點在 variants 區塊,超級多屬性!!

tailwind.config.js

variants: {
    accessibility: ['responsive', 'focus-within', 'focus'],
    alignContent: ['responsive'],
    alignItems: ['responsive'],
    alignSelf: ['responsive'],
    animation: ['responsive'],
    appearance: ['responsive'],
    backdropBlur: ['responsive'],
    backdropBrightness: ['responsive'],
    backdropContrast: ['responsive'],
    backdropDropShadow: ['responsive'],
    backdropFilter: ['responsive'],
    backdropGrayscale: ['responsive'],
    backdropHueRotate: ['responsive'],
    backdropInvert: ['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'],
    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'],
  },

找到 borderStyle 屬性,因為剛剛我想在 hover 時使用 border-dashed,但此屬性預設,沒有這 hover 效果。預設如下:

borderStyle: ['responsive'],

又看到其他屬性有加上 hoverfocus 的偽類值,所以我也照樣照句,把 hover 加入到 borderStyle 中。

新增後會變這樣:

borderStyle: ['responsive','hover'],

這時候再回到 HTML 上就會發現智能提示會出現之前想要設定的 border-dashed 樣式!

html

HTML

 <div class="container sm:mx-auto">
  <button
    class="
        flex
        sm:mx-auto
        rounded
        py-2
        px-3
        m-2
        bg-yellow-300
        text-black
        hover:text-white
        hover:bg-green-500
        focus:outline-none
        border-black border-2
        hover:border-red-900 hover:border-dashed hover:border-8
        "
  >
    Click Me
  </button>
  <br />
  <p class="text-center">
    <code class="bg-pink-200 p-2 text-red-500">border-dashed</code>沒有效果
  </p>
</div>

重新編譯後,滑鼠移動到畫面上,也會出現一樣的效果。
no hover

before

hover
after

如果要用覆蓋的方式,可以寫在 variants 屬性內,也會達到一樣的效果。

tailwind.config.js

module.exports = {
    purge: {
        enabled: true,
        content: ["./*.html"],
    },
    darkMode: false, // or 'media' or 'class'
    theme: {
        extend: {},
    },
    variants: {
        extend: {
            borderStyle: ["responsive", "hover"],
        },
    },
    plugins: [],
};

以上筆記客製化 variants 變化模式如何新增效果在預設設定檔中,或是覆蓋想要改變的樣式,自己一開始用會全部展開修改,因為太多屬性,還要去翻找文件有時候滿麻煩的,但相信未來熟稔之後,應該就可以用覆蓋的方式來寫了。

參考資料


上一篇
TailwindCSS 從零開始 - 偽類變體 Pseudo-Class Variants
下一篇
TailwindCSS 從零開始 - 讓 Variants 成為偽類的強大神器
系列文
TailwindCSS - 從零開始30

尚未有邦友留言

立即登入留言