ShopifyテーマにTailwind v4を入れるときは、tw: プレフィックスで名前空間を切っておくと後で泣かない
PRODUCTS
TOPICS
Shopifyのテーマ側にもともと書かれている .grid や .button と、Tailwindの .grid や .flex がぶつかってしまい、気づいたら他のセクションが勝手に壊れている。触ってない場所までデザインが変わるので本当にこわい。
この記事では、Tailwind CSS v4 の prefix を使ってTailwindのユーティリティクラスを安全に名前空間化する方法をまとめる。プレフィックスとしてtw:を付けておくだけで、ShopifyテーマとTailwindが干渉しなくなる。実際のセットアップ例とLiquidでの使い方まで紹介する。
1. なぜ prefix が必要なのか
Shopifyのテーマ(Liquid)はあらかじめCSSがかなり書き込まれている。
例えばこんなものが普通に出てくる。
- .grid
- .flex
- .button
- .badge
さらに、外部アプリを入れるとそのアプリが読み込むCSSでも同じような汎用クラス名が追加される。
Tailwindも同じように .grid .flex のような短いクラスを使うので、どっちが最終的に効くかは読み込み順と詳細度しだいになる。これがやっかいで、特にありがちなのは次のような状況。
- セクションAを少し調整しただけなのにストア内の別ページのボタン配置がずれる
- テーマの .grid の想定だったレイアウトがTailwindの .grid に上書きされて段組みが変わる
- Tailwind側で flex の前提を崩された結果アプリのUIが壊れる
つまり「Tailwindを入れた瞬間から既存CSSと同居バトルが始まる」という状態になりやすい。
この事故を防ぐ一番シンプルな方法がTailwind側だけプレフィックスを付けて名前空間を分けてしまうという考え方。
2. Tailwind v4 での prefix の書き方
Tailwind v3 まではtailwind.config.js (あるいは tailwind.config.ts) に prefix: 'tw-' のように書いてtw-flex tw-p-4 という形にすることが多かった。
Tailwind v4 ではもっと素直な書き方が用意されていてCSSのエントリーポイントでこう書くだけでいい。
@import "tailwindcss" prefix(tw);これでTailwindが出力するユーティリティクラスは全部 tw: 始まりになる。
例えば
- flex → tw:flex
- p-4 → tw:p-4
- grid-cols-2 → tw:grid-cols-2
この状態だとShopifyテーマや外部アプリが .flex .grid を自由に定義しても、Tailwind側は tw:flex tw:grid といった別物として扱われる。CSSの衝突そのものを避けられるので既存スタイルを壊さずにTailwindを安心して導入できる。
3. Shopifyテーマ × Tailwind v4 の実際のセットアップ
ここでは、ShopifyのテーマにTailwind v4を入れてtw: プレフィックスを付けて運用する例を書いていく。
前提として用意しているファイルはこんな構成。
- assets/tailwind.input.css
- assets/tailwind.output.css (ビルド後に生成されるCSS。テーマで読み込むやつ)
- tailwind.config.ts (Tailwindの設定)
- Liquidテンプレート (sections/*.liquid など) からは tw: 付きのクラス名を使う
まずは tailwind.input.css の例から。
@config "../tailwind.config.ts";
@import "tailwindcss" prefix(tw);
@plugin "@tailwindcss/typography";
/* プロジェクト共通のトークン */
@theme {
--font-sans: "Inter", sans-serif;
--font-interTight: "Inter Tight", sans-serif;
--font-notoSansJP: "Noto Sans JP", sans-serif;
/* fluidな余白スケール */
--spacing-d4m2: clamp(0.25rem, 0.125rem + 0.25vw, 0.5rem);
--spacing-d8m4: clamp(0.5rem, 0.25rem + 0.5vw, 1rem);
--spacing-d12m8: clamp(0.75rem, 0.5rem + 0.5vw, 1rem);
--spacing-d16m12: clamp(1rem, 0.75rem + 0.5vw, 1.5rem);
--spacing-d20m16: clamp(1.25rem, 1rem + 0.5vw, 2rem);
--spacing-d24m16: clamp(1.5rem, 1rem + 0.5vw, 2rem);
--spacing-d32m24: clamp(2rem, 1.5rem + 0.5vw, 3rem);
--spacing-d40m32: clamp(2.5rem, 2rem + 0.5vw, 4rem);
--spacing-d48m36: clamp(3rem, 2rem + 0.5vw, 4rem);
--spacing-d64m48: clamp(4rem, 3rem + 0.5vw, 6rem);
--spacing-d80m64: clamp(5rem, 4rem + 0.5vw, 8rem);
--spacing-d96m72: clamp(6rem, 4rem + 0.5vw, 9rem);
--spacing-d120m96: clamp(8rem, 6rem + 0.5vw, 12rem);
}いくつかポイントがある。
@import "tailwindcss" prefix(tw);
ここで Tailwind のユーティリティ全部に tw: プレフィックスを付けている
@theme { ... }
Tailwind v4 から入った書き方で共通のトークン(フォント、余白スケールなど)をまとめて定義できる
Shopifyの各セクション/スニペットで同じトークンを使い回せるのでブランドとしてのルールを崩しにくくなる
このあとに Tailwind CLI でこのCSSをビルドして出力を assets/tailwind.output.css に吐き出すイメージになる。
tailwind.config.ts の最小構成
Tailwindに「どのファイルをスキャンすればいいか」を教える設定。
Shopifyテーマの場合はLiquidがメインなので、そのパスを指定しておく。
// tailwind.config.ts
import type { Config } from "tailwindcss";
const config: Config = {
content: [
"./layout/**/*.liquid",
"./sections/**/*.liquid",
"./snippets/**/*.liquid",
"./templates/**/*.{liquid,json}",
"./assets/**/*.{js,ts}",
],
};
export default config;content 配列の中に Liquid のパスを入れておくと、Tailwindはその中で実際に使っているクラスだけを拾ってビルドしてくれる。ここで tw:flex のようなプレフィックス付きクラスもちゃんと検出されるので余計なユーティリティは出力されない。
つまりビルド後のCSSが肥大化しにくい。これはテーマ運用ではかなり大事なポイント。
5. Liquid側での使い方
実際のセクションではHTMLクラスに tw: 付きのユーティリティを並べていく。
例えばヒーローセクションの例はこんな感じ。
<div class="tw:grid tw:grid-cols-2 tw:gap-d16m12">
<div class="tw:flex tw:flex-col">
<p class="tw:text-28-24 tw:font-interTight tw:font-medium text-stone-900">
Designing the whitespace of everyday life with coffee.
</p>
<h1 class="tw:text-20-16">コーヒーに関わる時間ごと、デザインする</h1>
<span class="tw:flex tw:items-center tw:gap-2">
{{ 'icon-rectangle.svg' | inline_asset_content }}
EST 2024
</span>
</div>
<div>
<img
src="{{ 'img-hero-slide-1.png' | asset_url }}"
width="768"
height="410"
alt=""
>
</div>
</div>見てわかる通りTailwindのユーティリティは tw: が付いている。
一方で、Shopifyテーマ側や自前CSSのクラス (例: hero-section, text-stone-900 のようなテーマ用の命名) は必要ならそのまま素のクラス名で共存できる。役割が分かれているので後から読む人にも優しい。
6. ビルドと開発の回し方
開発中は Shopify CLI と Tailwind CLI を同時に走らせておくと快適。
例えば package.json のスクリプトはこうしておくとわかりやすい。
{
"scripts": {
"dev": "concurrently \"shopify theme dev -s your-store\" \"npx @tailwindcss/cli -i ./assets/tailwind.input.css -o ./assets/tailwind.output.css --watch\""
}
}やっていることはシンプルで、
- Shopify CLI でローカルテーマをプレビューしながら
- Tailwind CLI で tailwind.input.css から tailwind.output.css を生成し続ける
テーマの theme.liquid や layout 側で tailwind.output.css を読み込むようにしておけば、編集して保存するたびに反映される。
7. 運用で感じた良さ
この tw: プレフィックス運用には、実際に使うと分かる地味なメリットがいくつかある。
- 既存テーマや外部アプリのCSSと、Tailwindのクラスがケンカしない
- Liquidの断片だけ切り出して見ても「どこがTailwindか」が一目で分かる
- tw: が付いているクラスだけgrepすれば、Tailwind依存の箇所を一気に洗い出してリファクタできる
- tw: を付け忘れた場合はTailwindに検出されないから、ビルド結果に出てこない → 気づきやすい
さらに、テーマ側の base.css に書いていた細かなレイアウトや調整用スタイルをすべて Tailwind に寄せることで、ビルド時に不要なCSSがまとめて整理されるようになった。結果として CSS の総量がシンプルになり、読み込みパフォーマンスも安定して向上した。
Shopify のテーマは後からコードが足されやすいので、こうした自動的な“整理整頓”の恩恵は大きい。
また、Shopifyは特にあとからアプリを足したりマーケ側の人がスニペットだけ差し替えたりと、とにかく触られる機会が多い。「どのCSSがどこから来てるのか」が不透明になりやすいので、プレフィックスで責任範囲を区切っておくのは本当にコストが低い。
むすび
Shopifyのテーマ開発にTailwindを混ぜるとき、一番のリスクは「Tailwindが全部を乗っ取ってくる」ことではなくて「どこで何が上書きされたのか分からないまま壊れる」ことだと思う。
Tailwind v4 の @import "tailwindcss" prefix(tw); というシンプルな指定は、その不安をかなり減らしてくれる。Tailwindのユーティリティを tw: 名前空間に閉じ込めておくことで、テーマのCSS・外部アプリのCSS・TailwindのCSSがそれぞれ安全に共存できるようになる。
Shopifyテーマをベースに、必要なところだけTailwindのスピード感で作りたい。プレフィックスを付けるだけで、あとから泣かずに済む。
参考:この記事の設計や Tailwind 運用は、弊社が運営しているPASS COFFEE(https://passcoffee.jp)でも同様の構成で実装しています。