💨

React + Tailwind CSSでホバー時のスタイルを適用する方法

2024/05/15に公開
3

こんにちは、shootaceanです。
React + Tailwind CSSでホバー時のスタイルを適用する方法を紹介します。

更新履歴
  • 2024-05-16 : CSS Custom Propertyを利用した方法を追記 ( ご提供 : @honey32 様 )
    • MouseEventを利用した方法よりも断然こっちが良い…!

結論

CSS Custom Propertyを利用して、ホバー時のスタイルを適用する方法が一番シンプルで良いです。
JavaScriptの onMouseEnter / onMouseLeave でホバー状態を制御して、適用するスタイルを切り替える。

(もし、他の実装方法があれば教えてください🙏)

理由

理由としては下記の2点です。

  1. TailwindCSSのJITでは folor-[${color}] ( color = #FFFFFF ) のように動的なカラーコードを指定すると、ビルド時に値が確定されていないため色指定が反映されない
  2. style属性のインラインスタイルでは :hover などの擬似要素を使用できない

上記の理由から、インラインスタイル、TailwindCSSのどちらも利用できないため、他の方法を探す必要があります。

検証コード

https://codesandbox.io/p/devbox/hover-style-with-react-tailwind-9flyrx?embed=1&file=%2Fsrc%2FApp.tsx

App.tsx
import { useState } from "react";

function App() {
  const [color, setColor] = useState<string>("#000000");
  // Pattern : MouseEvent
  // const [isHover, setIsHover] = useState<boolean>(false);
  return (
    <div className="p-4">
      <p
        // not working
        // className={`hover:bg-[${color}]`}
        // Pattern : CSS Custome Property
        className="hover:bg-[--bg-color-hover]"
        style={{ "--bg-color-hover": color }}
        // Pattern : MouseEvent
        // style={{ backgroundColor: isHover ? color : "#FFFFFF" }}
        // onMouseEnter={() => setIsHover(true)}
        // onMouseLeave={() => setIsHover(false)}
      >
        Hover Me
      </p>
      <input
        type="color"
        value={color}
        onChange={(e) => setColor(e.target.value)}
      />
    </div>
  );
}

export default App;

Appendix

記事を書く中での学びと疑問

Discussion

Honey32Honey32

CSS 変数を使えば、動的 / 静的の間をうまく取り持つことができるので、Tailwind でもその方法が使えると思います!

Emotion ドキュメント | Best Practice より "Advanced: CSS variables with style" の章

import { useState } from "react";

function App() {
  const [color, setColor] = useState<string>("#000000");
  const [isHover, setIsHover] = useState<boolean>(false);
  return (
    <div className="p-4">
      <p
        className={`hover:bg-[var(--bg-color-hover)]`} 
        style={{ "--bg-color-hover": color }}
      >
        Hover Me
      </p>
// 以下略

ちなみに、style Prop に CSS 変数を入れようとすると型チェックで弾かれるので、以下のような d.ts ファイルによる拡張が必要です。

import type * as CSS from 'csstype';

declare module 'csstype' {
  interface Properties {
    // CSS 変数を許可
    [index: `--${string}`]: string | number;
  }
}
shootaceanshootacean

なんと…!素晴らしい情報ありがとうございます!
手元で試してみて理解できたら記事に追記させていただこうと思います!