Windi CSSはTailwind CSSと互換性を持ちながら、より高速でより多くの機能を提供するユーティリティファーストのCSSフレームワークです。このガイドでは、Windi CSSの特徴や導入方法、さらに実践的な使い方について解説します。
目次
- Windi CSSとは
- Windi CSSの特徴
- 開発環境構築
- 基本的な使い方
- 高度な機能
- 各フレームワークとの連携
- 実践的なコンポーネント作成例
- 注意点
1. Windi CSSとは
Windi CSSは、Tailwind CSS 2.0と互換性を持つ次世代のユーティリティファーストCSSフレームワークです。ユーティリティファーストとは、あらかじめ用意された様々なCSSユーティリティクラスを組み合わせてデザインを構築するアプローチです。
特筆すべき点として、Windi CSSの公式サイトによると、プロジェクトは現在サンセット(終了)ステータスとなっており、新規プロジェクトでは代替手段を検討することが推奨されています。 しかし、その独自機能や高速性から依然として利用価値は高いフレームワークです。
2. Windi CSSの特徴
速度
- オンデマンド生成: 使用するユーティリティクラスのみをコンパイルするため、初期ロードや開発時のホットリロードが非常に高速です
- Tailwind CSSと比較して20〜100倍高速と言われています
Tailwind CSS互換性
- Tailwind CSS 2.0と完全互換性があります
- 既存のTailwind CSSプロジェクトから簡単に移行できます
独自機能
以下のような独自機能が提供されています:
バリアントグループ
<!-- 通常のTailwind CSS -->
<div class="bg-white dark:hover:bg-gray-800 dark:hover:font-medium dark:hover:text-white"/>
<!-- Windi CSSのバリアントグループ記法 -->
<div class="bg-white dark:hover:(bg-gray-800 font-medium text-white)"/>
値の自動推論
<!-- 具体的な値を指定可能 -->
<div class="p-5px mt-[0.3px]"></div>
<!-- 色の指定も柔軟 -->
<button class="bg-hex-b2a8bb"></button>
<button class="bg-[hsl(211.7,81.9%,69.6%)]"></button>
<!-- グリッドも直感的に指定可能 -->
<div class="grid-cols-[auto,1fr,30px]"></div>
重要プレフィックス
<!-- !をつけるとimportant指定になる -->
<div class="text-red-400 !text-green-300">Green</div>
ショートカット機能
// windi.config.js
export default {
theme: {
/* ... */
},
shortcuts: {
'btn': 'py-2 px-4 font-semibold rounded-lg shadow-md',
'btn-green': 'text-white bg-green-500 hover:bg-green-700',
},
}
<div class="btn hover:btn-green"></div>
レスポンシブ設計の拡張
<div class="p-1 md:p-2 <lg:p-3"></div>
3. 開発環境構築
Windi CSSは様々なフレームワークやビルドツールと連携できます。ここでは、Viteを使った環境構築手順を紹介します。
Vite + Windi CSS
# Viteプロジェクトの作成
npm init @vitejs/app # または yarn create @vitejs/app
# Vue、Reactなど好みのフレームワークを選択
# Windi CSSのインストール
npm i vite-plugin-windicss -D # または yarn add vite-plugin-windicss -D
vite.config.jsの設定:
// vite.config.js
import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue' // または React等
import WindiCSS from "vite-plugin-windicss"
export default defineConfig({
plugins: [
Vue(),
WindiCSS(),
],
})
メインファイルでのインポート:
// main.js (Vue)
import { createApp } from 'vue'
import App from './App.vue'
import "windi.css" // この行を追加
createApp(App).mount('#app')
// または React の場合
// main.jsx
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import "windi.css" // インポート
4. 基本的な使い方
Windi CSSの基本的な使い方はTailwind CSSとほぼ同じです。HTMLタグにクラス名として各種ユーティリティを適用します。
基本的なスタイリング例
<!-- テキスト色と背景色 -->
<div class="text-gray-800 bg-gray-100">
基本的なテキスト
</div>
<!-- サイズとパディング、マージン -->
<div class="w-full max-w-md mx-auto my-8 p-6">
中央揃えの要素
</div>
<!-- フレックスボックス -->
<div class="flex items-center justify-between">
<span>左側の要素</span>
<span>右側の要素</span>
</div>
<!-- グリッド -->
<div class="grid grid-cols-2 gap-4">
<div>アイテム1</div>
<div>アイテム2</div>
<div>アイテム3</div>
<div>アイテム4</div>
</div>
<!-- レスポンシブデザイン -->
<div class="text-sm md:text-base lg:text-lg">
画面サイズに応じて変わるテキスト
</div>
5. 高度な機能
設定ファイルの作成
プロジェクトルートにwindi.config.js
またはwindi.config.ts
ファイルを作成します。TypeScriptを使う場合は、型チェックのためにdefineConfig
関数を使用することが推奨されています。
// windi.config.js
import { defineConfig } from 'windicss/helpers'
import colors from 'windicss/colors'
export default defineConfig({
darkMode: 'class', // ダークモードの設定
theme: {
extend: {
colors: {
primary: colors.blue[500],
secondary: colors.pink[500],
// カスタムカラーの追加
brand: {
100: '#f0f4f8',
900: '#1a365d',
}
},
fontFamily: {
sans: ['Noto Sans JP', 'sans-serif'],
},
spacing: {
'128': '32rem',
}
},
},
plugins: [
require('windicss/plugin/typography'),
require('windicss/plugin/forms'),
],
// ショートカットの設定
shortcuts: {
'btn': 'py-2 px-4 font-semibold rounded-lg shadow-md',
'btn-primary': 'text-white bg-blue-500 hover:bg-blue-700',
},
})
AttributifyモードとJIT(Just-In-Time)コンパイル
Windi CSSはAttributifyモードもサポートしており、クラス名ではなく属性としてスタイルを適用できます。
<!-- 通常のクラス使用法 -->
<div class="text-red-400 p-4 m-3">Hello</div>
<!-- Attributifyモード -->
<div text="red-400" p="4" m="3">Hello</div>
設定方法:
// windi.config.js
export default defineConfig({
attributify: true,
})
6. 各フレームワークとの連携
Windi CSSは多くのフレームワークやビルドツールと連携可能です。
Vue CLI との連携
# Vue CLIプラグインとしてインストール
vue add windicss
vue.config.jsの設定:
// vue.config.js
module.exports = {
pluginOptions: {
windicss: {
// 設定オプション
},
},
}
Nuxt.js との連携
# インストール
yarn add nuxt-windicss -D
# または npm i nuxt-windicss -D
nuxt.config.jsの設定:
// nuxt.config.js
export default {
buildModules: [
'nuxt-windicss',
],
// Nuxt 3の場合はmodules配列に追加
// modules: ['nuxt-windicss'],
// 追加設定
windicss: {
scan: {
dirs: ['./'],
exclude: [
'node_modules',
'dist',
'.git',
'.nuxt',
],
},
preflight: {
alias: {
// Nuxt専用のエイリアス
'nuxt-link': 'a',
'nuxt-img': 'img',
},
},
},
}
7. 実践的なコンポーネント作成例
カードコンポーネント
<div class="bg-white rounded-lg shadow-md overflow-hidden max-w-md mx-auto">
<img class="w-full h-48 object-cover" src="sample-image.jpg" alt="カード画像">
<div class="p-6">
<h3 class="font-bold text-xl mb-2 text-gray-800">カードタイトル</h3>
<p class="text-gray-600 mb-4">
これはカードの説明文です。ここにテキストが入ります。
</p>
<div class="flex justify-between items-center">
<button class="btn btn-primary">詳細を見る</button>
<span class="text-sm text-gray-500">2025.05.03</span>
</div>
</div>
</div>
レスポンシブナビゲーション
<nav class="bg-gray-800 text-white p-4">
<div class="container mx-auto flex justify-between items-center">
<div class="text-xl font-bold">ロゴ</div>
<!-- モバイルメニューボタン -->
<div class="block md:hidden">
<button class="p-2">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16m-7 6h7"></path>
</svg>
</button>
</div>
<!-- デスクトップメニュー -->
<div class="hidden md:flex space-x-4">
<a href="#" class="hover:text-gray-300">ホーム</a>
<a href="#" class="hover:text-gray-300">サービス</a>
<a href="#" class="hover:text-gray-300">ブログ</a>
<a href="#" class="hover:text-gray-300">お問い合わせ</a>
</div>
</div>
</nav>
フォーム要素
<form class="max-w-md mx-auto p-6 bg-white 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="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
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="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
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="submit">
ログイン
</button>
<a class="inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800" href="#">
パスワードを忘れた?
</a>
</div>
</form>
8. 注意点
サンセットステータス
Windi CSSは現在サンセット(終了)ステータスとなっています。公式サイトでも「We recommend new projects to consider alternatives」(新規プロジェクトでは代替手段を検討することを推奨)と記載されています。長期的なプロジェクトでは、TailwindCSS v3など代替ソリューションを検討することも視野に入れると良いでしょう。
セーフリスト
動的クラス名は自動的に検出されないため、次のような場合は設定ファイルでセーフリストに追加する必要があります:
<!-- 動的クラスは検出されない -->
<div :class="{ ['p-'+size]: true}">
<!-- セーフリストに追加する必要あり -->
セーフリストの設定:
// windi.config.js
export default defineConfig({
safelist: 'p-1 p-2 p-3 p-4',
// または配列で指定
// safelist: ['p-1', 'p-2', 'p-3', 'p-4']
})
動的に生成する場合:
// windi.config.js
function range(size, startAt = 1) {
return Array.from(Array(size).keys()).map(i => i + startAt)
}
export default defineConfig({
safelist: [
range(10).map(i => `p-${i}`), // p-1からp-10まで
range(10).map(i => `m-${i}`), // m-1からm-10まで
],
})
まとめ
Windi CSSは、Tailwind CSSの互換性を持ちながら、より高速な開発体験と独自の便利機能を提供するCSSフレームワークです。バリアントグループや値の自動推論など、開発効率を高める多くの機能が魅力です。
現在はサンセットステータスになっていますが、特にViteやNuxt.jsなどとの組み合わせでは爆速な開発体験を提供します。小〜中規模のプロジェクトや、開発速度が重視されるプロジェクトでは依然として強力な選択肢となります。
実際のプロジェクトでは、これらの知識を活用して、効率的で美しいWebサイトを構築していきましょう。