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では、 Next.js 経験が豊富なフロントエンドエンジニアを募集しています

弊社では Next.js の知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違う Gaji-Labo を味わいに来ませんか?

Next.js の設計・実装を得意とするフロントエンドエンジニア募集要項

もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!

求人応募してみる!


投稿者 Morita Sou

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