UnoCSSは、高速で柔軟なユーティリティファーストのCSS(Atomic CSS)エンジンです。Tailwind CSSやWindi CSSの影響を受けていますが、より高速でカスタマイズ性に優れた特徴を持っています。この記事では、UnoCSSの基本から実践的な使い方までをご紹介します。

UnoCSSとは

UnoCSS(ウノシーエスエス)は、Anthony Fu氏によって開発された「オンデマンド」で動作するAtomic CSSエンジンです。大きな特徴は以下の通りです:

  • 完全カスタマイズ可能: コアユーティリティが存在せず、すべての機能はプリセットで提供
  • 超高速: パース、AST、スキャンなしで動作し、Tailwind CSS JITやWindi CSSより5倍以上高速
  • 軽量: 依存関係がなく、約6KB(minify + brotli圧縮時)
  • 柔軟性: 必要な機能だけを選択して導入可能
  • 多様な統合: Vite、Webpack、PostCSS、CLI、VS Code、ESLintなどと連携可能

Tailwind CSSのパフォーマンス問題とカスタマイズの難しさを解決するために開発されました。実際に使用されているユーティリティのみをオンデマンドで生成するため、無駄なCSSがなく効率的です。

導入方法

1. インストール

UnoCSSをViteプロジェクトに導入する場合を例に説明します:

# npm を使用する場合
npm install -D unocss

# yarn を使用する場合
yarn add -D unocss

# pnpm を使用する場合
pnpm add -D unocss

2. Viteの設定

vite.config.ts(または.js)ファイルを作成または編集します:

import UnoCSS from 'unocss/vite'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [
    UnoCSS(),
    // その他のプラグイン
  ],
})

3. 設定ファイルの作成

uno.config.ts(または.js)ファイルを作成します:

import { defineConfig } from 'unocss'
// 必要なプリセットをインポート
import presetUno from '@unocss/preset-uno'
import presetAttributify from '@unocss/preset-attributify'
import presetIcons from '@unocss/preset-icons'

export default defineConfig({
  presets: [
    presetUno(), // Tailwind CSS互換のプリセット
    presetAttributify(), // 属性モードのプリセット
    presetIcons(), // アイコンのプリセット
  ],
  // カスタムルールや設定をここに追加
})

4. エントリーポイントでのインポート

アプリケーションのメインエントリーファイルで以下を追加します:

import 'virtual:uno.css'

基本的な使い方

ユーティリティクラスの使用

UnoCSSは、Tailwind CSSと同じような記法でHTML要素にクラスを適用します:

<div class="m-4 p-2 text-blue-500 bg-gray-100 rounded-lg shadow-md">
  Hello UnoCSS
</div>

このコードは以下のようにCSSに変換されます:

.m-4 {
  margin: 1rem;
}
.p-2 {
  padding: 0.5rem;
}
.text-blue-500 {
  --un-text-opacity: 1;
  color: rgba(59, 130, 246, var(--un-text-opacity));
}
.bg-gray-100 {
  --un-bg-opacity: 1;
  background-color: rgba(243, 244, 246, var(--un-bg-opacity));
}
.rounded-lg {
  border-radius: 0.5rem;
}
.shadow-md {
  --un-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
  box-shadow: var(--un-ring-offset-shadow, 0 0 #0000), var(--un-ring-shadow, 0 0 #0000), var(--un-shadow);
}

属性化モード (Attributify Mode)

複数のクラスを適用する代わりに、属性として直接スタイルを指定できます:

<!-- 通常のクラスを使用した場合 -->
<button class="bg-blue-400 hover:bg-blue-500 text-sm text-white font-mono font-light py-2 px-4 rounded border-2 border-blue-200 dark:bg-blue-500 dark:hover:bg-blue-600">
  ボタン
</button>

<!-- 属性化モードを使用した場合 -->
<button
  bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600"
  text="sm white"
  font="mono light"
  p="y-2 x-4"
  border="2 rounded blue-200"
>
  ボタン
</button>

実践的な設定と使用例

1. カスタムルールの定義

独自のユーティリティを定義できます:

// uno.config.ts
import { defineConfig } from 'unocss'
import presetUno from '@unocss/preset-uno'

export default defineConfig({
  presets: [
    presetUno(),
  ],
  rules: [
    // 静的ルール
    ['text-brand', { color: '#1e293b' }],

    // 動的ルール
    [/^m-(\d+)$/, ([, d]) => ({ margin: `${d / 4}rem` })],
    [/^text-size-(\d+)$/, ([, size]) => ({ 'font-size': `${size}px` })],
  ],
})

2. ショートカットの定義

よく使うクラスの組み合わせをショートカットとして定義できます:

// uno.config.ts
import { defineConfig } from 'unocss'

export default defineConfig({
  shortcuts: {
    // 基本ボタン
    'btn': 'py-2 px-4 font-semibold rounded-lg shadow-md',
    // 緑のボタン
    'btn-green': 'text-white bg-green-500 hover:bg-green-700',
    // カードコンポーネント
    'card': 'bg-white rounded-lg shadow-md p-4 m-2',
    // ヘッダー
    'header': 'bg-gray-100 border-b py-4 sticky top-0',
  },
  // 動的ショートカット
  shortcuts: [
    [/^btn-(.*)$/, ([, c]) => `bg-${c}-400 text-${c}-100 py-2 px-4 rounded-lg`],
  ],
})

3. テーマのカスタマイズ

ブランドカラーやブレークポイントなどを設定できます:

// uno.config.ts
import { defineConfig } from 'unocss'

export default defineConfig({
  theme: {
    colors: {
      'brand': {
        'primary': '#3b82f6',
        'secondary': '#10b981',
        'accent': '#f97316',
      },
    },
    breakpoints: {
      'sm': '640px',
      'md': '768px',
      'lg': '1024px',
      'xl': '1280px',
      '2xl': '1536px',
    },
  },
})

4. バリアントの活用

:hover:focusなどの状態に応じたスタイル変更ができます:

<button class="bg-blue-500 hover:bg-blue-700 focus:ring-2 dark:bg-blue-600">
  ボタン
</button>

5. アイコンの使用

@unocss/preset-iconsを使うと、アイコンをCSSで実装できます:

// uno.config.ts
import { defineConfig } from 'unocss'
import presetIcons from '@unocss/preset-icons'

export default defineConfig({
  presets: [
    presetIcons({
      scale: 1.2,
      cdn: 'https://esm.sh/',
    }),
  ],
})
<!-- Material Designのアカウントアイコン -->
<div class="i-mdi-account text-3xl text-blue-500"></div>

<!-- Carbonのチャートアイコン -->
<button class="i-carbon-chart p-2 bg-gray-100 hover:bg-gray-200 rounded-full"></button>

アイコンを使うには、対応するアイコンセットをインストールする必要があります:

# Material Design Icons
npm install -D @iconify-json/mdi

# Carbon Icons
npm install -D @iconify-json/carbon

実践的なコンポーネント例

カードコンポーネント

<div class="max-w-sm mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl m-4">
  <div class="md:flex">
    <div class="md:shrink-0">
      <img class="h-48 w-full object-cover md:h-full md:w-48" src="image.jpg" alt="カード画像">
    </div>
    <div class="p-8">
      <div class="uppercase tracking-wide text-sm text-indigo-500 font-semibold">カテゴリー</div>
      <a href="#" class="block mt-1 text-lg leading-tight font-medium text-black hover:underline">タイトルがここに入ります</a>
      <p class="mt-2 text-slate-500">詳細なコンテンツがここに表示されます。複数行のテキストが入ります。</p>
    </div>
  </div>
</div>

ナビゲーションバー

<nav class="bg-white shadow-md px-6 py-4">
  <div class="flex items-center justify-between">
    <div class="flex items-center space-x-4">
      <div class="text-2xl font-bold text-blue-600">ロゴ</div>
      <div class="hidden md:flex space-x-4">
        <a href="#" class="text-gray-700 hover:text-blue-600">ホーム</a>
        <a href="#" class="text-gray-700 hover:text-blue-600">特徴</a>
        <a href="#" class="text-gray-700 hover:text-blue-600">料金</a>
        <a href="#" class="text-gray-700 hover:text-blue-600">お問い合わせ</a>
      </div>
    </div>
    <div>
      <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
        ログイン
      </button>
    </div>
  </div>
</nav>

フォーム

<form class="max-w-md mx-auto bg-white p-6 rounded-lg shadow-md">
  <div class="mb-4">
    <label class="block text-gray-700 text-sm font-bold mb-2" for="username">
      ユーザー名
    </label>
    <input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="username" type="text" placeholder="ユーザー名">
  </div>
  <div class="mb-6">
    <label class="block text-gray-700 text-sm font-bold mb-2" for="password">
      パスワード
    </label>
    <input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="password" type="password" placeholder="******************">
  </div>
  <div class="flex items-center justify-between">
    <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" type="button">
      サインイン
    </button>
    <a class="inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800" href="#">
      パスワードをお忘れですか?
    </a>
  </div>
</form>

UnoCSS の便利機能

1. インスペクタ

開発時に localhost:5173/__unocss にアクセスすると、UnoCSSのインスペクタが表示されます。生成されたCSSやクラスの一覧をリアルタイムで確認できます。

2. バリアントグループ

複数のユーティリティに同じバリアントを適用する場合、グループ化して記述できます:

<!-- 通常の書き方 -->
<div class="hover:bg-blue-500 hover:text-white hover:font-bold">
  ホバーすると変化
</div>

<!-- バリアントグループを使用 -->
<div class="hover:(bg-blue-500 text-white font-bold)">
  ホバーすると変化
</div>

3. CSSディレクティブ

@applyディレクティブを使用して、CSS内でユーティリティを適用できます:

.my-button {
  @apply bg-blue-500 text-white py-2 px-4 rounded-lg;
}

.my-button:hover {
  @apply bg-blue-700;
}

実践的なヒント

1. コンポーネントライブラリとの組み合わせ

Vue、React、SvelteなどのUIコンポーネントとUnoCSSを組み合わせる場合、各フレームワークに合わせた設定が必要です:

Reactの場合

// vite.config.js
import React from '@vitejs/plugin-react'
import UnoCSS from 'unocss/vite'

export default {
  plugins: [
    UnoCSS(),
    React(),
  ],
}

Vueの場合

// vite.config.js
import Vue from '@vitejs/plugin-vue'
import UnoCSS from 'unocss/vite'

export default {
  plugins: [
    UnoCSS(),
    Vue(),
  ],
}

2. レスポンシブデザイン

ブレークポイントプレフィックスを使用してレスポンシブなデザインを実装できます:

<div class="text-center md:text-left lg:text-right">
  スクリーンサイズによってテキストの配置が変わります
</div>

<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
  <div class="bg-blue-100 p-4 rounded">アイテム 1</div>
  <div class="bg-blue-200 p-4 rounded">アイテム 2</div>
  <div class="bg-blue-300 p-4 rounded">アイテム 3</div>
  <div class="bg-blue-400 p-4 rounded">アイテム 4</div>
</div>

3. ダークモード対応

dark:プレフィックスを使用してダークモード用のスタイルを定義できます:

<div class="bg-white text-black dark:bg-gray-800 dark:text-white">
  ダークモードに対応したコンテンツ
</div>

まとめ

UnoCSSはAtomic CSSエンジンとして、高速で柔軟なWeb制作を可能にします。Tailwind CSSの使い勝手の良さを継承しながらも、より高速でカスタマイズ性に優れているため、モダンなWeb開発の選択肢として注目されています。

主な利点:

  • オンデマンド生成による高速性
  • 豊富なカスタマイズオプション
  • 軽量で効率的なCSSの生成
  • 様々なフレームワークとの互換性
  • 拡張性の高い設計

特にViteを使用したプロジェクトでは導入も簡単で、既存のTailwind CSSプロジェクトからの移行もスムーズです。新しいプロジェクトでは、UnoCSSの採用を検討する価値があるでしょう。

実践的な使用例や設定方法を参考に、ぜひUnoCSSを活用したWeb制作にチャレンジしてみてください。

参考リソース

カテゴリー: WEB