clsx の使い方

A tiny (239B) utility for constructing className strings conditionally.

v2.1.1/週MITユーティリティ
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

clsx の使い方 — className文字列を条件付きで組み立てる軽量ユーティリティ

一言でいうと

clsx は、CSSクラス名の文字列を条件付きで動的に組み立てるための超軽量(239B gzip)ユーティリティです。classnames パッケージのより高速・軽量な代替として広く使われています。

どんな時に使う?

  • Reactコンポーネントで、propsや状態に応じてクラス名を切り替えたい時isActivedisabled などの条件でクラスを付け外しするケース
  • Tailwind CSSで複数のユーティリティクラスを条件付きで組み合わせたい時 — 長いクラス文字列を可読性高く管理したいケース
  • テンプレートリテラルでの三項演算子の乱用を避けたい時`btn ${isActive ? 'btn-active' : ''} ${isDisabled ? 'btn-disabled' : ''}` のような可読性の低いコードを改善したいケース

インストール

# npm
npm install clsx

# yarn
yarn add clsx

# pnpm
pnpm add clsx

clsx の基本的な使い方

最も典型的なReactコンポーネントでの使用パターンを示します。

import { clsx } from 'clsx';

type ButtonProps = {
  variant?: 'primary' | 'secondary';
  isDisabled?: boolean;
  isLoading?: boolean;
  className?: string;
  children: React.ReactNode;
};

const Button: React.FC<ButtonProps> = ({
  variant = 'primary',
  isDisabled = false,
  isLoading = false,
  className,
  children,
}) => {
  return (
    <button
      className={clsx(
        'btn',
        variant === 'primary' && 'btn-primary',
        variant === 'secondary' && 'btn-secondary',
        isDisabled && 'btn-disabled',
        isLoading && 'btn-loading',
        className
      )}
      disabled={isDisabled || isLoading}
    >
      {children}
    </button>
  );
};

// 使用例
<Button variant="primary" isLoading>送信中...</Button>
// => <button class="btn btn-primary btn-loading" disabled>送信中...</button>

ポイント: false && 'btn-disabled'false を返しますが、clsx は falsy な値をすべて無視するため、余計な空白やクラス名が混入しません。

よく使うAPI・パターン

1. 文字列の可変長引数

最もシンプルなパターンです。論理AND(&&)と組み合わせて条件付きクラスを実現します。

import { clsx } from 'clsx';

const isActive = true;
const isHidden = false;

clsx('foo', 'bar', isActive && 'active', isHidden && 'hidden');
//=> 'foo bar active'

2. オブジェクト記法

キーがクラス名、値が真偽値のオブジェクトを渡します。classnames パッケージと同じ記法です。

import { clsx } from 'clsx';

const isOpen = true;
const isAnimating = false;

clsx({
  'modal': true,
  'modal--open': isOpen,
  'modal--animating': isAnimating,
  'modal--dark': true,
});
//=> 'modal modal--open modal--dark'

3. 配列の利用

配列を渡すことも可能です。ネストした配列もフラットに展開されます。

import { clsx } from 'clsx';

const baseClasses = ['text-base', 'font-medium'];
const conditionalClasses = ['p-4', false && 'hidden', 'rounded'];

clsx(baseClasses, conditionalClasses);
//=> 'text-base font-medium p-4 rounded'

4. 混合パターン(文字列 + オブジェクト + 配列)

すべての入力形式を自由に混在させることができます。

import { clsx } from 'clsx';

const size = 'lg';

clsx(
  'btn',
  ['px-4', 'py-2'],
  { 'btn-lg': size === 'lg', 'btn-sm': size === 'sm' },
  'rounded'
);
//=> 'btn px-4 py-2 btn-lg rounded'

5. clsx/lite — 文字列専用の超軽量版

文字列引数しか使わない場合、さらに軽量な clsx/lite(140B gzip)を利用できます。Tailwind CSSとの組み合わせで特に有用です。

import { clsx } from 'clsx/lite';

const isActive = true;
const isPrimary = false;

clsx('text-base', isActive && 'text-blue-500', isPrimary && 'font-bold');
//=> 'text-base text-blue-500'

// ⚠️ オブジェクトや配列は無視される
clsx({ foo: true });
//=> ''

類似パッケージとの比較

項目clsxclassnamesobj-str
サイズ (gzip)239B283B96B
文字列入力
オブジェクト入力
配列入力
ネスト対応
軽量版 (lite)✅ (140B)
パフォーマンス⚡ 高速標準⚡ 高速
TypeScript型定義同梱@types/classnames が必要

結論: classnames からの移行先として clsx は完全なドロップインリプレースメントです。APIの互換性があるため、インポートを変えるだけで移行できます。

注意点・Tips

falsy な値の扱い

falsenullundefined0NaN、空文字列 '' はすべて無視されます。単独の true も無視されます。

clsx(true, false, '', null, undefined, 0, NaN);
//=> ''

これにより、&& 演算子で安全に条件分岐できます。

default export と named export の両方に対応

// どちらでもOK
import clsx from 'clsx';
import { clsx } from 'clsx';

プロジェクト内で統一しておくことを推奨します。named export の方がTree Shakingとの相性が明示的です。

Tailwind CSS IntelliSense との連携

VS Codeで Tailwind CSS IntelliSense を使っている場合、settings.json に以下を追加すると clsx() 内でもクラス名の自動補完が効くようになります。

{
  "tailwindCSS.experimental.classRegex": [
    ["clsx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
  ]
}

clsx/lite を使うべきタイミング

Tailwind CSSのプロジェクトで、オブジェクト記法や配列を一切使わず文字列のみで組み立てている場合は clsx/lite に切り替えるとバンドルサイズをさらに約100B削減できます。ただし、オブジェクトや配列を渡しても無視されるだけでエラーにはならないため、意図しないバグの原因になりえます。チーム内でルールを明確にしておきましょう。

数値の 0 に注意

const count = 0;
clsx('items', count && 'has-items');
//=> 'items'  ← count が 0 (falsy) なので 'has-items' は付かない。意図通り。

// ただし数値をそのまま渡すと無視される
clsx('items', count);
//=> 'items'  ← 0 は falsy なので無視される

数値をクラス名として使いたいケースはほぼありませんが、動的な値を渡す際は型に注意してください。

まとめ

clsx は、CSSクラス名の条件付き組み立てという頻出パターンを、わずか239Bで解決する定番ユーティリティです。classnames と完全互換のAPIを持ちながら、より軽量・高速に動作します。React + Tailwind CSS の組み合わせでは特に重宝するので、まだ使っていなければぜひ導入を検討してみてください。