はじめに
こんにちは、もんすんです。
個人で「自分専用のトレンドビューア」を作っているのですが、せっかく自分しか見ないアプリなので、見た目は趣味全開のサイバーパンク調にしました。
そのUIを作るときに Tailwind CSS を v4 にしたのですが、最初に手が止まりました。
「あれ、tailwind.config.ts がない。どこにカスタムカラーを書くんだ?」
v3 までしかちゃんと触ったことがなく、設定といえば tailwind.config.ts(または .js)のイメージでした。
v4 では作法が変わっています。
この記事は、v4 で tailwind.config.ts を使わずに、CSS の中だけでテーマを組み、ネオン風UIを作る実践メモです。
題材は自作の個人アプリ(アプリ名は伏せます)のデザインシステムです。
値はそのまま使えるようにコピペ可で載せています。
対象読者・前提
- Tailwind v3 の経験があり、v4 に移りたい人
- ネオン/グロー系の「光るUI」を CSS で作りたい人
この記事のゴール
- v4 の
@themeでカスタムカラー・フォントを定義できるようになる - グロー/スキャンライン/グリッドなどの「らしさ」を出すユーティリティを作れる
- v4 で動的クラス生成がハマる理由を知る
v4 の最小セットアップ:設定はCSSの中へ
v3 と v4 で、設定の置き場所がこう変わりました。
| v3 | v4 | |
|---|---|---|
| 読み込み | @tailwind base; @tailwind components; @tailwind utilities; |
@import "tailwindcss"; |
| カスタムカラー等 |
tailwind.config.ts の theme.extend
|
CSSの @theme ブロック |
| 設定ファイル | 必須 | 基本的に不要 |
v4 では、グローバルCSSの先頭で読み込み、そのまま @theme でトークンを宣言します。
/* globals.css */
@import "tailwindcss";
@theme {
/* カスタムカラー(--color-* がそのままユーティリティになる) */
--color-cyber-bg: #070b13;
--color-cyber-card: rgba(15, 23, 42, 0.6);
--color-neon-blue: #00f0ff;
--color-neon-cyan: #06b6d4;
--color-neon-pink: #ff007f;
--color-neon-purple: #a855f7;
/* フォント */
--font-orbitron: var(--font-orbitron);
--font-sans: var(--font-sans);
}
ポイントは、@theme 内で --color-cyber-bg と定義すると、bg-cyber-bg / text-cyber-bg / border-cyber-bg といったユーティリティが自動で生えることです。設定ファイルに JS のオブジェクトを書いていた時代より、だいぶ直感的になりました。
<div class="bg-cyber-bg text-neon-blue">ネオンブルーの文字</div>
アニメーションも @theme で定義できる
v4 では @theme の中に @keyframes まで書けます。--animate-* を定義すると animate-* ユーティリティになります。
@theme {
--animate-scanline: scanline 8s linear infinite;
--animate-cyber-pulse: cyber-pulse 2s ease-in-out infinite;
@keyframes scanline {
0% { transform: translateY(-100%); }
100% { transform: translateY(100%); }
}
@keyframes cyber-pulse {
0%, 100% { opacity: 0.8; box-shadow: 0 0 15px rgba(0, 240, 255, 0.2); }
50% { opacity: 1; box-shadow: 0 0 25px rgba(0, 240, 255, 0.5); }
}
}
<div class="animate-cyber-pulse">脈動するカード</div>
設定・キーフレーム・利用が全部 CSS の中で完結します。
“サイバーパンクらしさ”を作るカスタムユーティリティ
トークンだけでは「ネオンが光る」感じは出ません。
@theme の外(通常のCSS)で、雰囲気を作るユーティリティを定義します。
すべてコピペで動きます。
1. グロー(box-shadow)
.glow-cyan-lg { box-shadow: 0 0 20px rgba(0, 240, 255, 0.35); }
.glow-cyan-sm { box-shadow: 0 0 10px rgba(0, 240, 255, 0.2); }
2. 文字グロー(text-shadow)
.text-glow-cyan { text-shadow: 0 0 8px rgba(0, 240, 255, 0.6); }
.text-glow-pink { text-shadow: 0 0 8px rgba(255, 0, 127, 0.6); }
3. CRTスキャンライン(疑似要素で重ねる)
.scanline-bg::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(
rgba(18, 16, 16, 0) 50%,
rgba(0, 240, 255, 0.05) 50%
);
background-size: 100% 4px;
z-index: 10;
pointer-events: none; /* クリックを透過させるのが地味に重要 */
}
pointer-events: none; を忘れると、オーバーレイがクリックを食ってボタンが反応しなくなります。
4. サイバーグリッド背景
.cyber-grid {
background-image:
linear-gradient(rgba(255, 255, 255, 0.01) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.01) 1px, transparent 1px);
background-size: 20px 20px;
}
5. ついでにスクロールバーも光らせる
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: #070b13; }
::-webkit-scrollbar-thumb { background: #1e293b; border-radius: 3px; }
::-webkit-scrollbar-thumb:hover {
background: #00f0ff;
box-shadow: 0 0 8px #00f0ff; /* ホバーで光る */
}
細部ですが、こういう「触ったら光る」が積み重なると一気にそれっぽくなります。
カテゴリごとの色分けと、動的クラスの落とし穴
私のアプリでは、カードのカテゴリごとに左ボーダーの色を変えています。
| カテゴリ | 色 |
|---|---|
| tech | cyan |
| biz | purple |
| x-tech | pink |
| digest | amber |
ここで v4(というか Tailwind 全般)で必ず踏む落とし穴があります。
クラス名を文字列連結で動的生成すると、ビルド時にパージ(未使用クラスの削除)されて色が出ません。
// ❌ ダメ:文字列を組み立てると、スキャナがクラスを発見できずパージされる
const color = category === 'tech' ? 'cyan' : 'purple';
<div className={`border-l-${color}-400`} /> // border-l-cyan-400 が消える
// ✅ 正解:完全なクラス名をそのまま書く(マップで持つ)
const BORDER: Record<string, string> = {
tech: 'border-l-cyan-400',
biz: 'border-l-purple-400',
'x-tech':'border-l-pink-400',
digest: 'border-l-amber-400',
};
<div className={BORDER[category]} />
Tailwind はソースを静的にスキャンして使われているクラスを集めます。
「完全な文字列として存在するクラスしか拾えない」
これを忘れると「ローカルでは出てたのに本番で色が消える」になります。
どうしても動的にしたい場合は safelist を使いますが、まずは「完全なクラス名で持つ」のが王道かと思います。
ハマりどころまとめ
-
フォントは CSS変数直書きより、ユーティリティ(
font-orbitron等)で当てる-
@themeに登録しておけばクラスで使えます
-
-
モバイルファーストで作る
- 私のアプリは
max-w-mdで約390px幅を基準にしています - スマホで見るツールなら、まずこの幅で破綻しないことが最優先
- 私のアプリは
- 動的クラスはパージされる(再掲・最重要)
- スキャンライン等の疑似要素オーバーレイは
pointer-events: none;を忘れない
まとめ
Tailwind v4 は、設定が「JSの設定ファイル」から「CSSの中の @theme」へ移りました。
最初は戸惑いますが、慣れると色・フォント・アニメーションが1つのCSSファイルに集約されて見通しが良いです。
- カスタムカラーは
@themeの--color-*→ 自動でユーティリティ化 - グロー/スキャンライン等は通常CSSのユーティリティで「らしさ」を足す
- 動的クラス生成はパージで死ぬ → 完全なクラス名で持つ
ダークテーマで光らせるUIは、コスパよく「作り込んだ感」が出るのでおすすめです。
