shadcn/ui で テキスト系のCSS が効かなくなる現象を修正する


こんにちは森田です。
最近 Gaji-Labo では shadcn/ui を使った案件が増えてきています。
shadcn/ui は、Radix & Tailwindを使ったコンポーネントコレクションで、ライブラリではなくコピーして使うことを前提に作られているのが特徴です。

shadcn/ui の CSS は Tailwind CSS で書くのですが、先日そのCSSが効かなくなる現象が起こり、それを解決したのでまとめます。

起こった現象

現象としてはコンポーネントに指定したフォントサイズやフォントカラーなどテキスト系のクラスがうまく効かない現象となっていました。

コード的には以下のように Button コンポーネントにカスタムクラスのテキストサイズやテキストカラーを指定していたのですが、うまく聞きませんでした。

<Button className="text-custom-md text-custom-red">Button</Button>

ブラウザのデベロッパーツールで見てもクラスが見当たらず、なぜかクラスが消えている状態でした。

原因は tailwind-merge

クラスが消える状態から原因を追求したところ tailwind-merge がクラスをマージする際にカスタムクラスを競合したクラスとみなして削除しているようでした。

buttonコンポーネントを見てみるとこのようにユーティリティとして cn 関数が使われています。

import { cn } from "@/lib/utils"

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, asChild = false, ...props }, ref) => {
    const Comp = asChild ? Slot : "button"
    return (
      <Comp
        className={cn(buttonVariants({ variant, size, className }))}
        ref={ref}
        {...props}
      />
    )
  }
)

cn 関数で variants や propsで受け取る className を結合しているようです。
cn はおそらく classnames かと思われます。

で、この cs 関数を呼び出している utils.ts を確認したところ、tailwind-merge を使っていました。

import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

受け取った値を clsx で結合し、tailwind-merge でマージしているようです。

Class groups オプションでカスタムクラスを指定

リポジトリを確認したところ、このようなカスタムクラスが何のプロパティかを tailwind-merge に理解してもらう Class groups オプションが用意されていました。

リポジトリのドキュメントを参考に utils.ts を以下のように拡張しました。

import { type ClassValue, clsx } from "clsx";
import { extendTailwindMerge } from "tailwind-merge";

const customTwMerge = extendTailwindMerge({
  extend: {
    classGroups: {
      "font-size": [
        "text-custom-md",
      ],
    },
  },
});

export function cn(...inputs: ClassValue[]) {
  return customTwMerge(clsx(inputs));
}

これで text-custom-md は font-size のプロパティと tailwind-merge が理解してくれて、クラスが消えなくなりました。

まとめ

tailwind-merge は便利な反面、想定外の挙動をしてしまうことがあるので、それを避けるために設定をしっかり行う必要があります。

これでカスタムクラスを追加しても安心です。
shadcn/ui および Tailwind CSS でのコンポーネント作成はさらに捗りますね。

Gaji-Labo フロントエンドエンジニア向けご案内資料

Gaji-Labo は Next.js, React, TypeScript 開発の実績と知見があります

フロントエンド開発の専門家である私たちが御社の開発チームに入ることで、バックエンドも含めた全体の開発効率が上がります。

「既存のサイトを Next.js に移行したい」
「人手が足りず信頼できるエンジニアを探している」
「自分たちで手を付けてみたがいまいち上手くいかない」

フロントエンド開発に関わるお困りごとがあれば、まずは一度お気軽に Gaji-Labo にご相談ください。

オンラインでのヒアリングとフルリモートでのプロセス支援にも対応しています。

Next.js, React, TypeScript の相談をする!

投稿者 Morita Sou

フロントエンドグループチームマネージャー。
適切な技術提案やプロジェクトを円滑に進めるコミュニケーションを心掛けています。
CMS構築や開発環境の構築・最適化などを得意としています。チームビルティングと採用と開発環境を快適にすることにいつも燃えています。