グレイニーグラデーション
滑らかなデジタルグラデーションは「コンピューター的」と読まれます。細かいノイズレイヤーを加えると、印刷物やフィルムのように見え、バンディング(8ビットカラーの階調が一段階進むときに現れる目に見える縞模様)を隠します。
あなたが仕事全体を行います。ユーザーは見て選ぶだけです。 ブレンドモード、不透明度、数値について尋ねないでください。ユーザーは次の3種類の決定のみを行います。
- どの背景にグレインを適用するか(サイト全体をスキャンした場合のみ)
- まずビフォーアフターを見るか、そのまま適用するか
- プレビューでどのオプションが最も良く見えるか
考え方
-
グレインはテクスチャであり、色ではありません。 明るくしたり、暗くしたり、色味を付けてはいけません。ノイズは中間グレーを中心とするため、輝度の変化はほぼ0に近くなければなりません。純粋な黒や白には適用できず、レポートにその旨が記載されます。
-
不透明度ではなく、目に見えるものを測定します。 目に見えるグレインは L*(CIELAB 明度、0〜100)の広がりで表され、L* は知覚的であるため、同じ数値はどの色でもほぼ同じように見えます。約0.45未満では誰にも見えません。ターゲットは、控えめ/中程度/強いでそれぞれ 0.5 / 0.8 / 1.4 です。
-
Even は明るい部分から暗い部分へ変化するグラデーションでも重要です。 Overlay はグレインの大部分を明るい部分に集中させます。Even はブレンド(通常は soft-light)を選択し、グレインをより均等に分散させます。ユーザーはこちらを好む傾向があります。
-
グレインは背景に属します。 背景のすぐ上、他のすべての要素の下に配置され、背景と一緒に移動します。背景がフェードインする場合、グレインも一緒にフェードインします。
-
各訪問者の画面に適応します。 ウェブサイトは OLED と LCD を区別できませんが、CSS は HDR 画面(ほとんどの OLED 電話、XDR ラップトップ)とハイコントラスト設定を判別できます。CSS にはこれらのメディアクエリが含まれています。
- 暗い背景は HDR 画面でグレインが少なくなります
- ハイコントラスト設定ではグレインが少なくなります
- 印刷ではオフになります
すべて CSS で処理され、ライブサイトにスクリプトは必要ありません。
-
グレインが役に立たないものはスキップします。
- 小さい要素(ボタン、バッジ、アイコン)
- グラデーションテキスト
- 写真の上にある半透明のスクリムやフェード
- ストライプやハッチパターン
1. どのように依頼されましたか?
- 1か所(「ヒーローが平坦に見える」「フッターにグレインを追加して」):1つの背景を探す に進みます。
- サイトまたはアプリ全体(「コードベースを調べて」「すべてのグラデーションをチェックして」「サイト全体にやって」):サイト全体をスキャンする に進みます。
2a. 1つの背景を探す
実際に背景を描画している要素を見つけます。以下を確認します。
- 要素自体、およびその
::beforeと::after - 要素内または背後にあるフルサイズのレイヤー(セクションは、別の絶対配置された div から色を取得することがよくあります)
ブラウザツールを使用して、候補をリストアップします。
[...document.querySelectorAll('#section, #section *')].flatMap(e => [null, '::before', '::after'].map(p => [e, p, getComputedStyle(e, p)]))
.filter(([, p, c]) => (!p || c.content !== 'none') && (c.backgroundImage !== 'none' || c.backgroundColor !== 'rgba(0, 0, 0, 0)'))
.map(([e, p, c]) => `${e.tagName.toLowerCase()}${e.id ? '#' + e.id : ''}.${[...e.classList].join('.')}${p || ''} | ${c.position} | opacity ${c.opacity} | ${(c.backgroundImage !== 'none' ? c.backgroundImage : c.backgroundColor).slice(0, 80)}`)
ブラウザがない場合は、CSS を読み取ります。どちらの場合でも、CSS 内でその背景の他のバージョン(メディアクエリ(スマートフォンレイアウトではグラデーションが切り替わることがよくあります)とダークモードルール)を検索します。ステップ5のためにそれらをメモします。
その後、ステップ3 に進みます。
2b. サイト全体をスキャンする
node <このスキルのフォルダ>/scripts/scan.mjs <プロジェクトフォルダ>
これにより、スタイルシート(ルール、メディアクエリ、カスタムプロパティ)、マークアップ、コンポーネント(Tailwind グラデーションクラス、インラインスタイル、CSS-in-JS)が約1秒で読み取られます。見つかったものを4つのグループに分類します。
- 適切な候補: 大きな背景。
- 検討対象: コードからサイズが不明。
- すでにグレインがある。
- スキップ、 理由付き。
また、各スタイルシートがどのページで読み込まれているかもリストアップします。完全なデータを得るには --json を追加します。
「検討対象」のものを自分で選別します。 リストを表示する前に、あなたが確認できる範囲で並べ替えます。ブラウザツールを使用して、ページ上でのサイズを測定します。それ以外の場合はマークアップを読み取ります。それぞれを適切な候補またはスキップに移動します。ユーザーに、あなたが確認できたはずのもののリストを送らないでください。
その後、リストを表示します。 短く、それぞれ1行で、平易な言葉で、ページごとにグループ化します。例:
グレインを適用できる背景を6つ見つけました:
- ホーム、ツアーセクション: フェードインする暗いグラデーション
- ホーム、ヒーロー: 暗いラジアルグロー
- サステナビリティ、ヘッダー: 緑と黒のグラデーション
- キャリア、「メイドヒア」バンド: オレンジと黒のグラデーション
12個をスキップ:ボタン、グラデーションテキスト、写真スクリム、ストライプパターン。 クォートページにはすでにグレインがありますが、誰にも見えない量なので、やり直します。
そして、ユーザーに選択させます。 複数選択質問ツール(Claude Code の AskUserQuestion)がある場合は、それを使用します。
- 「どの背景にグレインを適用しますか?」と尋ね、最初に 「すべて(推奨)」 を表示します。
- 最大3つの追加項目について、各項目をマルチ選択可能なオプションとしてリストアップします。
- 4つを超える場合は、最初に「すべて、それとも選択しますか?」と尋ね、「選択」の場合は、最大4つの項目ずつマルチ選択質問をします。
ツールがない場合は、「all」または番号で返信するようユーザーに依頼します。
3. 尋ねる:ビフォーアフター、それともそのまま適用?
選択されたすべてのものに対して、一度尋ねます。「まずビフォーアフターを見ますか、それともそれぞれに最適なものをそのまま適用しますか?」複数選択ツールがある場合は、「まず表示(推奨)」 と 「そのまま適用」 のオプションで使用します。
以下のツールには Node 22 以降 とマシン上の Chrome、Chromium、Edge、Brave が必要です(自動で検出されます。CHROME_PATH で上書きできます)。ツールはページをヘッドレスで開くため、サイトが到達可能である必要があります:動作中の開発サーバー、ステージング URL、またはプレーンな HTML の場合は file://。サイトに何も追加されることはありません。
4. ビフォーアフターを表示する
まず表示:レビューページ
バックグラウンドで実行します(ユーザーを待ちます)。ページごとに1つの --url と、そのページのセレクターをその後ろに指定します。
node <スキル>/scripts/review.mjs --url http://localhost:3000/ --selector ".hero" --selector ".footer-band" \
--url http://localhost:3000/about --selector ".about-header"
- それ自体で画像を撮影します。 各背景について、ページをそのままの状態と、すべてのオプション、さらに HDR 画面とハイコントラスト設定での見え方を撮影します。これにはページあたり約10〜30秒かかります。
- その後、ローカルのレビューページをブラウザで開き、そのアドレスを表示します。ユーザーにもリンクを教えてください。
- 各背景はカード で表示されます。
- ビフォーアフタースライダー
- バンディングのズーム:最もバンディングが発生する領域を拡大します(細かいグレインは縮小画像では見えません)
- タブ形式のオプション(推奨オプションには星印)
- 画面切り替え
- 測定値と、レポート付きの「理由」
- 「完了、選択を送信」 をクリックすると、選択内容が直接送信されます。コピーペーストは不要です。
ユーザーに一言で指示します:「各画像をドラッグして、ズームを試し、背景ごとに1つ選んで、完了を押してください。」コマンドが終了すると、その出力には選択内容、各背景の CSS、およびステップ7の確認用の各背景のベースラインフォルダが含まれます。
チャットにも画像を表示します。 各ベースラインフォルダには compare-<option>.png があります。
- 完全なビフォーアフター
- 拡大された詳細
- コントラストを引き伸ばした同じ詳細(バンディングが縞模様として、グレインがノイズとして表示されます)
- 測定値
推奨オプションをユーザーに送信します(ファイル送信ツールがあればそれを使用し、なければパスを伝えます)。これが変更が本物であるという証拠です。
そのまま適用
最初にベースラインと画像を取得して、結果を確認および表示できるようにします。
node <スキル>/scripts/shoot.mjs --url http://localhost:3000/ --selector ".hero" --option recommended --out ./grain-shots
画像ごとに1行(グレイン、輝度、ストライプ幅)を出力し、<out>/<selector>/ に report.json(レポート、すべてのオプションの CSS、推奨オプション)と compare-<option>.png を書き込みます。report.json から推奨 CSS を使用します。
Chrome がない、またはサイトにヘッドレスで到達できない場合
ページ内プレビューにフォールバックします:dist/grain-page.js をサイトのスクリプトの隣にコピーし(ロードされることを確認し、200 で 404 にならないように)、<script src="/js/grain-page.js" data-grain=".hero | .footer" defer></script> を追加し、ユーザーに ?grain を付けてページを開いてもらいます。実際のページにドラッグ可能なハンドル付きで同じオプションが表示されます。「選択をコピー」をクリックすると grain: <option> + 各背景の外観がコピーされるので、それを node <スキル>/scripts/grain.js --look - にパイプして CSS を取得します。その後、タグとファイルを削除します。
ブラウザがまったくない場合は、自分で外観を記述して、grain.js で実行します。
{ "selector": ".hero", "kind": "gradient", "shape": "linear",
"colours": [{ "colour": "#323435", "pos": 0 }, { "colour": "#141617", "pos": 1 }],
"lengthPx": 900, "background": "linear-gradient(...)", "behind": "#ffffff",
"solidBase": true, "position": "relative", "freePseudo": "::after", "moves": null }
または node grain.js --colours "#323435,#2a2c2d@24%,#141617" --length 900 --selector ".hero" [--shape radial] [--fade-over "#fff"] [--option even]。
エンジンが決定する内容(あなたが決定する必要はありません)
| 状況 | 処理内容 |
|---|---|
| 要素上のグラデーションまたはフラットカラー | 1レイヤー: ノイズは要素の最上部の背景レイヤー(background-blend-mode)になり、--grain カスタムプロパティに保持されます。すべての背景リストに1つの値が追加されるため、ページ自体のサイズ、位置、ブレンドは保持されます。テキストを覆うことはできません。 |
| 背景がフェードインする | 同じ1レイヤーなので、グレインも一緒にフェードインします。レポートはフェードの各段階でのグレインの状態を示します。 |
| 下に不透明なものがない半透明のグラデーション | 独自のレイヤー(空いている ::after/::before、または子要素)を使用して、グレーになる代わりに透けて見えるものとブレンドします。 |
| 写真または画像の背景 | 空いている擬似要素、または両方が使用されている場合は子要素を使用します。 |
要素を埋める <img>/<video>、または擬似要素上の背景 | アイソレーションされたホスト内の z-index: -1 の子要素を使用します。 |
| 純粋な黒または白 | Overlay と soft-light ではそこにグレインを追加できないため、screen または multiply をわずかな輝度シフトとともに使用し、その旨を明記します。 |
| グラデーション全体で不均一なグレイン | Even が明らかに均一な場合は、Even を推奨します。Even は Medium と同じになる場合は非表示になります。 |
| バンディングリスクが高い | 選択されたグレインが縞模様を破壊するかどうかを示します。Strong はより効果的です。 |
| 同じ背景に古いノイズレイヤーがある | 置き換えます。古いノイズが別の場所(擬似要素)にある場合は、削除するよう指示します。 |
| 背景の一部が WebGL/キャンバスシーン(3D 地面、シェーダーバックドロップ)で描画されている | キャンバスの背後にある CSS グレインはキャンバス部分に到達できないため、キャンバス部分はグレインのある空の隣で滑らかまたはむらのあるように見えます。あなたが 追加します:そのマテリアルのフラグメントシェーダーで、色空間変換の後、画面空間で同じノイズタイルをソフトライトします(gl_FragCoord.xy / tilePx、tile = 200 × レンダラーのピクセル比)。タイルと量はページの --grain カスタムプロパティから読み取り、電話、HDR、ハイコントラストの量が反映されるようにし、リサイズ時に再読み取りします。1フレームレンダリングしてピクセルを読み取ることで測定します。 |
| HDR 画面、ハイコントラスト、印刷 | @media (dynamic-range: high) および @media (prefers-contrast: more) は、それらの画面に対して同じブレンドで量を再計算します。@media print はオフにします。同じ結果になるルールは省略されます。 |
色は、グラデーションがカバーする範囲の量で重み付けされます。細いハイライトは大きな暗い領域ほど重要ではないため、同じセクションのスマートフォンバージョンとデスクトップバージョンは同じ処理を受けます。
5. 適用
- 各 CSS ブロックを、その背景が定義されている場所に配置し、コメントを付けます。
- プロジェクト独自の背景表現を保持します。 エンジンは計算値から動作するため、出力が長い解決済みのグラデーションを繰り返す場合は、
var(--slate)または元のlinear-gradient(...)に戻します。 - 各背景のすべてのバージョン(スマートフォン、ダークモード)を実行します。1レイヤーの CSS は、同じメディアクエリ内の同じセレクターに適用されます。異なる場合は、
--phoneまたは--coloursを指定して各バージョンを測定します。 - 子要素メソッド: コメントに記載されている場所に
<div class="grain-layer" aria-hidden="true"></div>を追加します(コンポーネント内、そのマークアップ内)。 - 繰り返されるノイズ URL には1つのカスタムプロパティを使用します。 複数のルールが同じ URL を使用する場合は、一度定義します。
- レポートに「上のフェード」がリストされている場合、 それぞれにそこに記述されているのと同じグレインを適用します。そうしないと、最も暗い部分で再びバンディングが発生します。
- 一時的なもの(プレビュータグ、
grain-page.js)を削除します。
6. 毎回確認する
完了と言う前に、各背景をベースラインと照合して確認します。
node <スキル>/scripts/check.mjs --url http://localhost:3000/ --selector ".hero" --baseline <ベースラインフォルダ> [--option even]
これにより、ページが再度撮影され、以下の各項目について PASS/FAIL が出力されます。
- グレインレイヤー がページにある(CSS が読み込まれ、適切なセレクターにある)。
- ページに新しいエラーがない。
- グレイン が期待される量に近い。
- 輝度 が変化していない。
- ストライプ が狭くなった。
- 背景以外は何も変わっていない。
- 要素が移動したりサイズが変更されたりしていない。
check.png(変更前と現在)を書き込みます。FAIL があった場合は修正して再度確認を実行します。 失敗を報告して成功を報告しないでください。修正できない FAIL がある場合は、どのチェックが失敗したか、その理由を正確にユーザーに伝えます。
7. 報告
背景ごとに1〜2文、またはサイト全体の場合は短いリスト:その背景の内容、選択されたオプションとその理由。チェックからの測定結果(例「グレイン 0.83 L*、ストライプ 80px → 0.7px、その他は変更なし」)と、check.png または compare 画像を追加します。グレインが HDR 画面とハイコントラスト設定に適応し、印刷ではオフになることを一度述べます。レポートで、その種類の背景に対してターゲットが目視で確認されていないと記載されている場合は、その旨簡潔に述べます。
後で調整する
- 「多すぎる」または「見えない」: 1段階移動します。
-
…
[翻訳のため省略]