テクニック

CSS文字グラデーション実装ガイド|対応状況と読みやすさの担保

この記事の対象: 見出しやロゴタイプにグラデーションを使いたい制作者
読了時間: 約12分

文字にグラデーションをかける実装は background-clip: text の一択と言っていい状態が続いています。書き方自体は5行で終わるのに、実際に案件へ入れると別のところで詰まります。効かなかったときに文字が消える、見出しなのにコントラストが取れていない、選択したときに文字が読めなくなる。この3つは実装した本人が気づきにくく、公開後に指摘されがちな箇所です。

この記事では、コピーしてそのまま動く実装を先に置いたうえで、フォールバック・コントラスト・選択時表示・印刷までを含めた「納品できる形」に組み立てます。素のCSSだけで完結します。JavaScriptもライブラリも使いません。


前提と環境

この記事のコードはCMSやフレームワークに依存しません。HTMLとCSSが書ければどこでも動きます。設置先ごとの置き場所だけ先に整理しておきます。

環境 置き場所
静的サイト assets/css/style.css など、既存のCSSファイル末尾
WordPress(ブロックテーマ) 子テーマの style.css、または assets/css/ に分けて functions.php から wp_enqueue_style()
WordPress(クラシックテーマ) 子テーマの style.css
Shopify(Online Store 2.0) assets/ に独自CSSを置いて layout/theme.liquid の </head> 直前で読み込む。Dawn系なら base.css は直接触らない

Shopifyの場合、テーマの base.css を直接編集するとテーマ更新で消えます。独自ファイルを別に作って読み込む形にしてください。

{{ 'custom-gradient-text.css' | asset_url | stylesheet_tag }}

layout/theme.liquid の </head> の直前に置きます。ファイル名は自分の命名規則に合わせて変えてください。

WordPressで子テーマから読み込む場合は次の形です。

<?php
// 子テーマの functions.php に追記
add_action( 'wp_enqueue_scripts', function () {
    wp_enqueue_style(
        'gradient-text',
        get_stylesheet_directory_uri() . '/assets/css/gradient-text.css',
        array(),
        filemtime( get_stylesheet_directory() . '/assets/css/gradient-text.css' )
    );
}, 20 );

filemtime() を第4引数に渡しているのは、CSSを更新したときにブラウザのキャッシュを自動で切るためです。バージョン文字列を手で書き換える運用は必ず忘れます。ファイルが存在しないと filemtime() が警告を出すので、パスは実際に置いた場所と一致させてください。


background-clip: text の基本形

background-clip: text の基本形

まず動く最小コード

/* gradient-text.css */
.grad-text {
  /* 1. フォールバック色(後述。必ず先に書く) */
  color: #6d28d9;

  /* 2. グラデーションを背景として敷く */
  background-image: linear-gradient(90deg, #6d28d9 0%, #db2777 100%);

  /* 3. 背景を文字の形で切り抜く */
  -webkit-background-clip: text;
  background-clip: text;

  /* 4. 文字自体を透明にして背景を見せる */
  -webkit-text-fill-color: transparent;
  color: transparent;
}

HTML側はこれだけです。

<h2 class="grad-text">グラデーションのかかった見出し</h2>

変更するのは3か所です。

  • .grad-text — クラス名。既存の命名規則に合わせる
  • linear-gradient() の2色 — サイトのブランドカラーに置き換える
  • color: #6d28d9 — グラデーションの濃いほうの色を入れる(理由は後述)

なぜこの4行が必要なのか

処理の流れとしては、背景を敷いて、文字の形で切り抜いて、文字自体を透明にする、という3段階です。順番に意味があります。

background-clip: text が文字を塗るまで
背景を敷く要素全体にグラデーションを描画
文字型で切り抜くbackground-clip: text で字形の内側だけ残す
文字を透明に塗りを消して背景を露出させる

3段目の「文字を透明にする」を忘れると、背景の上に元の文字色が乗るだけで何も変わりません。逆にここだけ先に効いてしまうと、文字が消えます。この事故が起きる条件は後半のフォールバックの章でまとめます。

-webkit-background-clip と -webkit-text-fill-color を併記しているのは、WebKit系ブラウザが長くベンダープレフィックス付きの実装を持っていたためです。現在の主要ブラウザはプレフィックスなしの background-clip: text を解釈しますが、プレフィックス付きも同時に受け付けます。両方書いても副作用はないので、古い端末が残る案件では併記が安全です。自分が対象にするブラウザで足りているかは、MDNの background-clip のページか caniuse.com で「text」の項目を確認してください。バージョンによって差が出る部分なので、記憶で断定しないほうがいい箇所です。

背景のサイズを文字に合わせる

linear-gradient は要素のボックス全体に敷かれます。見出しが2行に折り返すと、1行目と2行目でグラデーションの位置が変わります。文字数の違う見出しを並べたときに色味が揃わないのはこれが原因です。

行ごとに同じグラデーションを繰り返したい場合は、display: inline にして各行をボックスとして扱わせる方法があります。

.grad-text--per-line {
  color: #6d28d9;
  background-image: linear-gradient(90deg, #6d28d9 0%, #db2777 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;

  /* インラインにすると行ごとに背景が分かれる */
  display: inline;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

box-decoration-break: clone は、複数行に分かれた要素の背景を行ごとに複製する指定です。これがないと折り返し後の行に背景の続きが割り当てられ、行末が中途半端な色になります。見出しを display: inline にするとマージンの効き方が変わるので、外側にラッパーの <h2> や <div> を置いて、内側の <span> にこのクラスを当てるほうが崩れません。

<h2 class="section-title">
  <span class="grad-text--per-line">2行に折り返しても<br>色が揃う見出し</span>
</h2>

効かない環境での見え方を先に決める

文字が消える条件

background-clip: text に対応していないブラウザで、-webkit-text-fill-color: transparent だけが効いてしまうと、文字が背景と同化して読めなくなります。実務上、これが最大のリスクです。

安全側に倒すなら、@supports で対応環境だけに透明化を適用します。

/* gradient-text.css */

/* ベース:どの環境でも読める状態 */
.grad-text {
  color: #6d28d9;
}

/* 対応環境だけグラデーションに差し替える */
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .grad-text {
    background-image: linear-gradient(90deg, #6d28d9 0%, #db2777 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
}

@supports の条件に or で両方書いているのは、プレフィックス付きしか解釈しないブラウザを取りこぼさないためです。片方だけだと、実際には表示できる環境でフォールバックのベタ塗りになります。

この書き方にすると、対応していない環境では color: #6d28d9 のベタ塗りで表示されます。文字が消えることはありません。フォールバック色にはグラデーションの濃いほうの色を入れるのが原則です。淡いほうを入れると、フォールバックしたときに背景とのコントラストが落ちます。

フォールバックの設計:どちらに倒すか

@supports で囲う(推奨)

  • 非対応環境はベタ塗りで読める
  • 濃い色を指定すればコントラストも保てる
  • 記述量は3行増えるだけ

囲わず直接指定

  • 非対応環境で文字が消える可能性
  • 気づくのは公開後になりやすい
  • 問い合わせフォームの見出しなら実害が出る

装飾のための実装で本文が読めなくなるのは、費用対効果として明確に赤字です。3行の追加で防げるので囲っておくべきです。

画像を背景にする場合の注意

background-image にはグラデーションだけでなく画像も指定できます。文字の中に写真を透かす表現はここで作れます。

.grad-text--photo {
  color: #1f2937;
}

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .grad-text--photo {
    /* 画像パスは自分の環境に合わせる */
    background-image: url("../img/texture.jpg");
    background-size: cover;
    background-position: center;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
}

画像の場合、読み込み失敗時に文字が透明のまま残ります。グラデーションと違って外部リソースに依存するので、background-color を保険として下に敷いておくと安全です。

    background-color: #1f2937;
    background-image: url("../img/texture.jpg");

背景色を先に書いておけば、画像が404でもその色で文字が塗られます。画像パスの ../img/texture.jpg は、CSSファイルからの相対パスです。WordPressのテーマ内なら ../images/、Shopifyなら {{ 'texture.jpg' | asset_url }} をLiquid側で書き出す形になるので、環境に応じて書き換えてください。

写真を透かす場合、字形の細い部分に写真のディテールが入ると輪郭が読み取れなくなります。ウエイトの太いフォントを選ぶ、写真側に filter: contrast() をかけて中間調を潰す、といった調整が前提になります。細身の明朝体でこの表現をやると、ほぼ確実に読めません。


読みやすさをどう担保するか

コントラストの測り方が変わる

グラデーション文字のコントラスト比は、通常の測定ツールでは正しく出ません。文字色が一定でないため、ツールが「どの色を測るか」を判断できないからです。実際、透明色として扱われて測定不能になるケースもあります。

判断の基準はシンプルにできます。

グラデーションで使う全ての色が、単独で背景に対して基準を満たすこと。

グラデーションの両端が基準を満たしていても、途中の色が満たさなければその部分は読みにくくなります。linear-gradient は2色を線形補間するので、両端が満たせば中間も概ね満たしますが、色相が大きく離れる組み合わせ(青→黄など)では途中で明度が跳ねます。中間色を1つ拾って測るのが確実です。

中間色の拾い方は、DevToolsで対象要素のスクリーンショットを撮り、カラーピッカーで文字の中央付近を吸い取るのが早いです。3色以上の linear-gradient を使っている場合は、色停止点(カラーストップ)ごとに測ります。停止点の色さえ基準を満たしていれば、その間の補間は両端の内側に収まります。

WCAGの基準は次の通りです。

対象 AAの基準 AAAの基準
通常サイズの文字 4.5:1 7:1
大きい文字(18pt / 太字14pt以上) 3:1 4.5:1

見出しに使う場合は「大きい文字」の基準が適用されるので、3:1を下回らなければ最低限は満たします。ただし見出しは読み飛ばされる前提の要素ではなく、ページの構造を伝える役割があります。3:1ぎりぎりを狙うより、4.5:1を確保したうえでグラデーションの幅を狭くするほうが実務的です。

幅を狭くする、が答えになることが多い

コントラストを保ちながらグラデーション感を出す一番確実な方法は、明度差ではなく色相差でグラデーションを作ることです。

/* 明度は近く、色相だけ動かす */
background-image: linear-gradient(90deg, #6d28d9 0%, #db2777 100%);

紫と赤紫はどちらも白背景に対して十分暗く、コントラストが保たれたまま色の変化が見えます。一方、次のような指定は途中で読みにくくなります。

/* 途中で明度が上がりすぎる例 */
background-image: linear-gradient(90deg, #1e3a8a 0%, #fbbf24 100%);

濃紺から黄色へのグラデーションは、右端に近づくほど白背景とのコントラストが落ちます。デザインカンプ上では見栄えがしても、実装後にアクセシビリティ指摘が入る典型パターンです。

判断を早くするための目安を置いておきます。

  • グラデーションの2色をグレースケールに変換して見比べる。明度差が大きいなら、暗いほうに寄せる
  • 白背景なら両端とも明度50%以下、黒背景なら両端とも明度60%以上を目安にする
  • 迷ったら背景色を持つ要素の中に置く。白背景直置きが一番シビアになる

明度を揃えたまま色の変化を出したいなら、oklch() で色を指定する方法もあります。明度(L)を固定して色相(H)だけ動かせば、知覚上の明るさを保ったままグラデーションが作れます。

/* 明度を 45% に固定し、色相だけ動かす */
background-image: linear-gradient(
  90deg,
  oklch(45% 0.2 300) 0%,
  oklch(45% 0.2 350) 100%
);

oklch() は人間の知覚に近い色空間なので、L値が同じなら見た目の明るさもほぼ揃います。従来の #rrggbb や hsl() は、同じ数値でも色相によって体感の明るさが変わるため、この揃え方ができません。ただし対応ブラウザは限られる時期があったので、フォールバックのHEX指定を先に書いてから上書きする形にしてください。

適用範囲は見出しとロゴタイプまで

本文にグラデーションをかけるのは避けてください。行数が増えるほど色の変化が細切れになり、可読性が落ちます。適用の目安は次の通りです。

対象 判断
ヒーローのキャッチコピー 使ってよい。文字が大きく短い
セクション見出し(h2) 使ってよい。1〜2行に収まる範囲で
リード文(2〜3行) 慎重に。フォントサイズが18px未満なら避ける
本文 使わない
ボタンのラベル 使わない。押せることが伝わらなくなる
フォームのラベル・エラー文 使わない。読み落としが直接損失になる
ナビゲーションのリンク 使わない。ホバーとカレント表示が作れない

ボタンのラベルにグラデーションを使うと、ホバーやフォーカスで色を変える手段がなくなります。状態変化を色で伝える要素とは相性が悪い、と覚えておくと判断が早いです。グローバルナビも同じ理由で外します。現在地を示す色の変化が効かなくなり、代わりに下線やウエイトで表現することになりますが、それなら最初からグラデーションを使わないほうが早いです。


選択時の表示を潰さない

何が起きるか

-webkit-text-fill-color: transparent を指定した文字を範囲選択すると、多くのブラウザで選択範囲の背景色だけが表示され、文字が見えなくなります。文字が透明なままで、その下にグラデーションではなく選択ハイライトが描かれるためです。

見出しをコピーしようとしたユーザーが、選択した瞬間に文字を見失う。地味ですが実際に起きます。

対処

::selection で選択時だけ塗りを戻します。

.grad-text::selection {
  -webkit-text-fill-color: #ffffff;
  color: #ffffff;
  background-color: #6d28d9;
}

/* Firefox 系のために moz プレフィックスも併記 */
.grad-text::-moz-selection {
  -webkit-text-fill-color: #ffffff;
  color: #ffffff;
  background-color: #6d28d9;
}

background-color に指定した色と color の白で、選択時のコントラストを確保します。ここの背景色はサイトの選択色に合わせて変えてください。既にサイト全体で ::selection を定義しているなら、その色を流用します。

子要素を含む見出しでは、親だけでなく子にも当てる必要があります。::selection は継承されないためです。

.grad-text::selection,
.grad-text *::selection {
  -webkit-text-fill-color: #ffffff;
  color: #ffffff;
  background-color: #6d28d9;
}

.grad-text *::selection を足しておけば、見出しの中に <span> や <em> が入っても崩れません。

印刷時も同じ問題が起きる

印刷プレビューで見出しが白く抜ける現象も、原因は同じです。多くのブラウザは印刷時に背景画像を出力しません。background-clip: text の中身は背景画像なので、印刷すると文字が消えます。

@media print {
  .grad-text {
    -webkit-text-fill-color: #000000;
    color: #000000;
    background-image: none;
  }
}

印刷時はグラデーションを諦めて黒ベタに戻します。カタログサイトや資料請求のあるサイトでは、この5行を入れておくと後で問い合わせが減ります。色は本文色に合わせてください。

なお、ユーザーが印刷ダイアログで「背景のグラフィック」を有効にすれば背景画像も出力されますが、既定はオフです。既定の状態で壊れないほうを正とします。この @media print は、PDF出力(ブラウザの「PDFに保存」)でも同じように効きます。見積書や資料をHTMLで作ってPDF化する運用があるなら、必ず入れてください。


実務で使える完成形

ここまでの内容を1ファイルにまとめます。これをコピーして色とクラス名だけ変えれば、そのまま納品できる状態です。

/* ==========================================================
   グラデーション文字
   変更するのは --grad-from / --grad-to / --grad-fallback の3つ
   ========================================================== */
.grad-text {
  --grad-from: #6d28d9;      /* グラデーション開始色 */
  --grad-to: #db2777;        /* グラデーション終了色 */
  --grad-fallback: #6d28d9;  /* 非対応環境の色。濃いほうを入れる */
  --grad-select-bg: #6d28d9; /* 選択時の背景色 */

  color: var(--grad-fallback);
}

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .grad-text {
    background-image: linear-gradient(
      90deg,
      var(--grad-from) 0%,
      var(--grad-to) 100%
    );
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
}

/* 選択時に文字を見失わせない */
.grad-text::selection,
.grad-text *::selection {
  -webkit-text-fill-color: #ffffff;
  color: #ffffff;
  background-color: var(--grad-select-bg);
}

.grad-text::-moz-selection,
.grad-text *::-moz-selection {
  -webkit-text-fill-color: #ffffff;
  color: #ffffff;
  background-color: var(--grad-select-bg);
}

/* 印刷時はベタ塗りに戻す */
@media print {
  .grad-text {
    -webkit-text-fill-color: #000000;
    color: #000000;
    background-image: none;
  }
}

/* 2行以上に折り返す見出し用 */
.grad-text--inline {
  display: inline;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

カスタムプロパティに切り出してあるので、配色違いを増やすときは変数の上書きだけで済みます。

/* 別の配色パターンを足す例 */
.grad-text--blue {
  --grad-from: #1d4ed8;
  --grad-to: #0891b2;
  --grad-fallback: #1d4ed8;
  --grad-select-bg: #1d4ed8;
}
<h2 class="grad-text grad-text--blue">別配色の見出し</h2>

クラスを2つ当てるだけです。CSSの記述量が増えないので、案件でパターンが増えても管理が破綻しません。

ダークモードを持つサイトでは、変数の上書きだけで色を切り替えられます。実装本体には手を入れません。

@media (prefers-color-scheme: dark) {
  .grad-text {
    --grad-from: #a78bfa;
    --grad-to: #f472b6;
    --grad-fallback: #a78bfa;  /* 暗い背景では明るいほうを入れる */
    --grad-select-bg: #a78bfa;
  }
}

フォールバック色の原則が反転する点だけ注意してください。白背景では濃いほう、暗い背景では明るいほうが正解です。「濃い色を入れる」と機械的に覚えていると、ダークモードで文字が沈みます。

この「変数だけ差し替えれば増やせる」形は、編集者が触っても崩れない仕組みを作るときの基本形です。WordPressでブロックパターン側に持たせる場合は、次の記事の考え方がそのまま使えます。


アニメーションさせる場合

アニメーションさせる場合

グラデーションを動かす実装もよく求められます。ライブラリは不要です。

.grad-text--anim {
  --grad-from: #6d28d9;
  --grad-to: #db2777;
  --grad-fallback: #6d28d9;
  color: var(--grad-fallback);
}

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .grad-text--anim {
    background-image: linear-gradient(
      90deg,
      var(--grad-from) 0%,
      var(--grad-to) 50%,
      var(--grad-from) 100%
    );
    background-size: 200% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    animation: grad-slide 6s linear infinite;
  }
}

@keyframes grad-slide {
  from { background-position: 0% 50%; }
  to   { background-position: 200% 50%; }
}

/* 動きを減らす設定の環境では止める */
@media (prefers-reduced-motion: reduce) {
  .grad-text--anim {
    animation: none;
  }
}

background-size: 200% 100% で背景を要素の2倍幅にし、background-position をずらすことで動いて見せています。グラデーションの色を「開始色→終了色→開始色」の3点にしているのは、ループの継ぎ目で色が飛ばないようにするためです。2色だけだと1周した瞬間に色がジャンプします。

prefers-reduced-motion のブロックは省略しないでください。前庭障害のあるユーザーにとって、動き続ける要素は実害があります。OSの設定を読むだけなので、3行で対応できます。

アニメーション速度の 6s は、見出しで使うなら長めが無難です。2秒程度にすると視線が文字に留まらず、読ませたい見出しなのに読まれないという逆転が起きます。

パフォーマンス面では、background-position のアニメーションは合成だけで完結しないため、transform や opacity のアニメーションより負荷がかかります。1画面に1〜2個までにとどめてください。見出しが並ぶ一覧ページで全件に当てると、スクロール中のカクつきとして表面化します。ファーストビューの1本だけに当てるのが現実的な落としどころです。


うまくいかないとき

文字が消えて何も見えない

-webkit-text-fill-color: transparent が効いていて background-clip: text が効いていない状態です。原因は3つのどれかです。

  • background-image を指定していない。background-color だけでは切り抜けません
  • 親要素で background-image を指定して、子要素に background-clip: text を書いている。同じ要素に両方必要です
  • CSSの読み込み順で background-image: none が後から上書きしている

DevToolsで対象要素を選び、Computedタブで background-image に値が入っているかを見てください。none なら1つ目か3つ目です。

グラデーションが見出しごとにバラバラ

linear-gradient が要素幅に対して描画されるため、文字数が違えば色の配分も変わります。全ての見出しで同じ色遷移にしたいなら、background-size を固定値で指定します。

.grad-text--fixed {
  background-size: 400px 100%;
  background-repeat: no-repeat;
}

400px は見出しの想定最大幅に合わせて変えてください。no-repeat を付けないと、この幅を超えた分でグラデーションが繰り返されます。逆に想定幅より短い見出しでは、グラデーションの途中までしか使われません。短い見出しと長い見出しが混在する一覧では、この固定幅が別の不揃いを生みます。揃えたいのが「同じ見出しレベル同士」なのか「ページ全体」なのかを決めてから使ってください。

折り返した2行目の色がおかしい

box-decoration-break: clone と display: inline の組み合わせで解決します。前述の .grad-text--inline クラスを併用してください。ただし display: inline にすると padding-top / padding-bottom が周囲のレイアウトに影響しなくなるので、余白は外側のラッパー要素で取ります。

疑似要素(::before / ::after)の内容にかからない

::before や ::after は独立した要素として扱われるため、親の background-clip: text は継承されません。疑似要素にも同じ指定を書くか、装飾記号は透明化の対象外にするか、どちらかを選びます。

.grad-text::before {
  content: "―";
  -webkit-text-fill-color: var(--grad-fallback);
  color: var(--grad-fallback);
}

疑似要素だけベタ塗りに戻す書き方です。装飾の線や記号は単色のほうが締まって見えることが多いので、無理にグラデーションを通す必要はありません。

text-shadow が効かない

background-clip: text を使っている要素に text-shadow を指定すると、影が文字の上に描画されて背景を隠します。文字が透明なので、影だけが見えてしまう形です。

影を付けたい場合は filter: drop-shadow() を使います。

.grad-text--shadow {
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
}

drop-shadow() は描画結果の形に対して影を付けるため、切り抜かれた文字の形に沿った影になります。数値は影の水平・垂直オフセットとぼかし半径です。ただし filter は要素に新しいスタッキングコンテキストを作るので、position: sticky の見出しや、z-index で重なり順を制御している要素に当てると重なりが変わることがあります。効かせたい範囲だけに別クラスで当ててください。

文字の縁取り(ストローク)を併用したい

-webkit-text-stroke は -webkit-text-fill-color: transparent と併用できます。塗りがグラデーション、縁が単色という表現になります。

.grad-text--stroke {
  -webkit-text-stroke: 1px #1f2937;
}

ただし -webkit-text-stroke は字形の中心線を基準に内外へ太らせるため、線を太くすると字の内側が潰れます。日本語の漢字では画数が多い字ほど早く潰れるので、1px前後にとどめるのが安全です。縁取りを主役にしたいなら、グラデーション側を諦めて縁だけの表現にするほうがきれいに収まります。

Shopifyでテーマエディタから色を変えたい

CSSカスタムプロパティをLiquidから書き出せば、テーマエディタで色を設定できます。セクションの {% schema %} に色設定を追加して、セクション内でインラインに書き出す形です。

{%- style -%}
  #shopify-section-{{ section.id }} .grad-text {
    --grad-from: {{ section.settings.grad_from }};
    --grad-to: {{ section.settings.grad_to }};
    --grad-fallback: {{ section.settings.grad_from }};
    --grad-select-bg: {{ section.settings.grad_from }};
  }
{%- endstyle -%}

{% schema %} 側には次を追加します。

{
  "type": "color",
  "id": "grad_from",
  "label": "グラデーション開始色",
  "default": "#6d28d9"
},
{
  "type": "color",
  "id": "grad_to",
  "label": "グラデーション終了色",
  "default": "#db2777"
}

color 型の設定には default を必ず入れてください。空にするとテーマエディタでエラーになります。セレクタを #shopify-section-{{ section.id }} で限定しているのは、同じセクションを複数配置したときに色が混ざらないようにするためです。

Shopifyのセクション周りでつまずくポイントは、次の記事でも扱っています。


公開前に見る5項目

公開前に見る5項目

作業を終える前に、この5つだけ確認してください。DevToolsとブラウザの標準機能で全部できます。

  1. 文字を範囲選択する — 選択時に文字が読めるか
  2. 印刷プレビューを開く(Ctrl/Cmd + P)— 見出しが消えていないか
  3. DevToolsでCSSを無効化する — フォールバック色で読めるか
  4. グラデーションの中間色でコントラストを測る — 見出しなら3:1以上、できれば4.5:1
  5. 見出しを2行に折り返させる — ウィンドウ幅を狭めて色の連続を確認

3番目は、DevToolsのStylesパネルで background-image のチェックを外すだけで確認できます。@supports で囲った実装なら、この操作でフォールバック時の見え方がそのまま再現されます。

この5項目は実機を用意しなくても、手元のブラウザ1つで完結します。所要時間は見出し1種類あたり2〜3分です。デザインの装飾は「動いたら終わり」にしがちな領域ですが、壊れたときに気づくのが公開後になる分、確認のコストは先に払うほうが安く済みます。

サイト公開後に何を測るかまで含めて設計しておくと、装飾の効果も判断材料に乗せられます。


よくある質問

background-clip: text はプレフィックスなしで書いて大丈夫ですか

主要なモダンブラウザはプレフィックスなしの background-clip: text を解釈します。ただし対象ブラウザの範囲は案件ごとに違うので、-webkit-background-clip: text を併記しておくのが実務的です。両方書いても副作用はありません。自分の対象範囲で足りるかは caniuse.com の background-clip の text 項目で確認してください。

グラデーション文字のコントラスト比はどう測ればいいですか

自動測定ツールは文字色が透明のため正しく計算できません。グラデーションで使う色を1つずつ取り出し、背景色に対して個別に測ります。両端の2色に加えて、中間の1色も測ると安全です。見出し(18pt以上または太字14pt以上)なら3:1、通常サイズの文字なら4.5:1が基準になります。

選択したときに文字が見えなくなるのはバグですか

仕様通りの挙動です。文字自体が透明なので、選択ハイライトが背景に描かれても文字の形が現れません。::selection と ::-moz-selection で選択時だけ -webkit-text-fill-color を不透明な色に戻せば解決します。子要素にも当たるよう .クラス名 *::selection を併記してください。

JavaScriptやライブラリは必要ですか

不要です。この記事の実装はすべて素のCSSで完結します。グラデーションのアニメーションも @keyframes と background-position で実現できるため、外部ライブラリを読み込む理由はありません。読み込みが1本増えるとレンダリング開始が遅れるので、CSSで済むものはCSSで済ませます。

本文にもグラデーションを使っていいですか

避けてください。行数が増えると1行あたりの色変化が細切れになり、可読性が明確に落ちます。適用範囲はヒーローのキャッチコピー、セクション見出し、ロゴタイプまでにとどめ、本文・ボタンラベル・フォームのラベル・ナビゲーションのリンクには使わないのが安全です。

スクリーンリーダーでの読み上げに影響しますか

影響しません。background-clip も -webkit-text-fill-color も見た目の指定で、DOM上のテキストはそのまま残ります。文字を画像に置き換える手法と違い、読み上げ・検索エンジンのクロール・文字列のコピーはいずれも通常どおり機能します。装飾のためにテキストを画像化する必要がないのが、この実装の最大の利点です。


まとめ

background-clip: text 自体は5行で書けますが、納品できる状態にするには4つの追加が要ります。

  • @supports で囲って、非対応環境で文字が消えないようにする
  • フォールバック色にはグラデーションの濃いほうを入れる(暗い背景なら明るいほう)
  • ::selection で選択時の塗りを戻す
  • @media print で印刷時にベタ塗りへ戻す

コントラストについては、グラデーションで使う全ての色が単独で基準を満たすかで判断します。明度差の大きい配色は途中で読みにくくなるので、色相差で変化を作るほうが安全です。装飾を優先して読めなくなった時点で、その実装は失敗しています。

記事中の完成形CSSはカスタムプロパティに切ってあるので、配色パターンを増やすときは変数の上書きだけで済みます。クラスを1つ足すだけで運用できる形にしておくと、案件が長くなっても管理が崩れません。適用先を見出しとロゴタイプに絞り、公開前の5項目を通す。この2つを守るだけで、グラデーション文字は装飾として安全に運用できます。