🌈

Tailwind CSS でカスタムクラスに bg-opacity ができなかった話

に公開

こんにちは
PortalKeyのしゃりです。
弊社はcssライブラリにTailwind CSSを使っていますが、カスタム色として作成したbg-primaryに対しBackground Opacityであるbg-opacityが効かず困っていました。
解決方法と原因が分かり、jsの機能含めて自分にとっての発見が多かったので記事にしました。

環境

  • TypeScript: v5.8.3
  • React: v16.8.0
  • Tailwind CSS: v3.4.17
  • OS: Ubuntu-22.04 on windows11

経緯

弊社自前実施のprimaryclassがある。

style.ts
  const style = {
    "--pk-primary-color": "#252525",
   } as React.CSSProperties
tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
  theme: {
    extend: {
      colors: {
        primary: "var(--pk-primary-color)"
      }
    }
  }
}

実際に使ってみたら問題発生。
bg-[#25255] bg-opacity-30と書かないと透明にならなかった。

Compornent.tsx
// 背景色は付くが、透明にならない
className=`bg-primary bg-opaity-30`
className=`bg-primary/30`

// 30%透明になる
className=`bg-[#25255] bg-opacity-30`
className=`bg-white bg-opacity-30`

解決方法

tailwind.config.jscolors
- primary: primary: "var(--pk-primary-color)"
+ primary: "rgb(from var(--pk-primary-color) r g b / <alpha-value>)"

で前述のどのパターンでも透明にできた。
これ自体はTailwindのissue9143の一番最後のコメントにて紹介されていた。自分にとっては神の啓示にも等しかったのにdescriptionに比べてリアクションがほとんど無いのが悲しい。

なお、TailWindのメンバーからv4.0で改善する旨が宣言されていた。
どうやらrgbで書かれる想定で実装されてるみたい。
つまり今回の問題の原因は、primaryをカラーコードで書かいていたことだった。
https://github.com/tailwindlabs/tailwindcss/issues/9143#issuecomment-1946755547

Our documentation does explain how to do this (see here), however this assumes that you're using rgb colors.

Going to close this issue for now as there are workarounds available in the current version of Tailwind, and it's something we plan to change in v4.0 🤙


解説

var(--[variable])

変数variableを呼び出ししてるだけ

rgb(from ...)

https://developer.mozilla.org/ja/docs/Web/CSS/color_value/rgb

rgb(from green r g b / 0.5)
rgb(from #0000FF calc(r + 40) calc(g + 40) b)
rgb(from hwb(120deg 10% 20%) r g calc(b + 200))

rgb(from color ...でcolorの色をr, g, bとして個別に取り出せる。
color部分はカラーコードでもrgb値でも良く、変数を経由しても良さげ。

<alpha-value>

jsにも<alpha-value>はあるが、ここで重要なのはTailwind v3.1で実装されたプレースホルダー機能の<alpha-value>である。

  • CSS標準の<alpha-value>:rgba()のa部分を指定するCSS仕様
    jsの<alpha-value>はrgbaのaの部分で透明度を指定できるcssである。
    styleプロパティで透明度を指定する場合は背景色を指定するbackground-colorにて、rgbaのaを指定する。
    実際にbg-white bg-opacity-30を開発者モードで確認すると、以下のようになる。

    rgba(255, 255, 255, 0.3)
    background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
    
  • Tailwind CSS の<alpha-value>:v3.1で実装されたプレースホルダー機能
    talwindではBackground Opacityクラスが用意されている。しかし、本来はcssプロパティにそんなものは無く上の項目で紹介したrgbaのaで指定する仕組みとなっている。
    TailWindではbg-bule-30といった書き方をすることで--tw-bg-opacityを0.3に置き換え、透明度を調節しているものと思われる。

    そしてその--tw-bg-opacity<alpha-value>に使われている。

    https://tailwindcss.com/blog/tailwindcss-v3-1

    Instead of writing a function that receives that opacityValue argument, you can just write a string with an <alpha-value> placeholder, and Tailwind will replace that placeholder with the correct alpha value based on the utility.

    If you haven't seen any of this before, check out our updated Using CSS variables documentation for more details.

おまけ

tailwindで色のカスタムクラスの書き方が人に寄り違い、それぞれで使える解決方法が違う様子。

最初に紹介したissue9143でも、他の躓き方とその解決策が紹介されていたりした。

今回のパターンを解決することはできなかったものだが、さらに別の解決方法が紹介されているissueもあった。
https://github.com/tailwindlabs/tailwindcss/discussions/10347

tailwind.config.js
"primary": "rgb(var(--pk-primary-color) / var(--opacity))",
"primary": "rgb(from var(--pk-primary-color) r g b / var(--opacity)",

当記事のやり方でも解決しない場合は上述のissueを眺めてみると良いかも?

まとめ

少なくとも日本語で同様の問題と解決を示している記事が見つからなかったので、これが誰か役に立つと良いなぁ。

PortalKey Tech Blog

Discussion