ShopifyテーマにTailwind v4を入れるときは、tw: プレフィックスで名前空間を切っておくと後で泣かない
PRODUCTS
TOPICS
テーマ側にもともと書かれている .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 に吐き出すイメージになる。
4. 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に検出されないから、ビルド結果に出てこない → 気づきやすい
特にShopifyは、あとからアプリを足したり、マーケ側の人がスニペットだけ差し替えたり、とにかく触られる機会が多い。
「どのCSSがどこから来てるのか」が不透明になりやすいので、プレフィックスで責任範囲を区切っておくのは本当にコストが低い。
結び
Shopifyのテーマ開発にTailwindを混ぜるとき、一番のリスクは「Tailwindが全部を乗っ取ってくる」ことではなくて「どこで何が上書きされたのか分からないまま壊れる」ことだと思う。
Tailwind v4 の @import "tailwindcss" prefix(tw); は、そのリスクを正面から減らしてくれる。Tailwindのユーティリティを tw: 名前空間に閉じ込めることで、テーマ側のCSS・外部アプリのCSS・TailwindのCSSがちゃんと住み分けできるようになる。
Shopifyテーマをベースに、必要なところだけTailwindのスピード感で作りたい。そんなときは、まずはプレフィックスから始めておくと後から泣かずに済む。