image-treatment について
image-treatmentは、Webインターフェースの画像をデザインするスキルです。CSSフィルター、ブレンドモード、マスク、オーバーレイ、SVGフィルター、レスポンシブ画像の扱い、表示確認を解説します。
主な機能
- 01CSSフィルターとブレンドモード
- 02デュオトーンと画像マスク
- 03レイヤー背景とオーバーレイ
- 04レスポンシブ画像のバリエーション
- 05SVGフィルターと視覚効果
- 06アクセシビリティとスクリーンショット確認
活用シーン
- 01写真にデュオトーンを適用
- 02ヒーロー画像上の文字を読みやすくする
- 03レスポンシブな画像グリッドとトリミングを作成
- 04画面サイズごとの画像処理を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ arnavpuri/ designskills --skill image-treatmentインストール後、Claude Code で/image-treatmentを入力して読み込まれたか確認します。
詳細
画像の加工
CSS フィルター、ブレンドモード、マスク、SVG フィルターを使用して、画像に見事な視覚効果を適用します。
前提条件
- ブランドカラー(デュオトーンとオーバーレイの色はカラーシステムから選択)、スタイルの類型、画像の方向性については、
.agents/design-context.md(design-contextを参照)を確認してください。以下の色には、共通の--brand-*/--gray-*スケールを使用します。 - 雰囲気と目的(エディトリアル、製品、マーケティング、アート)を特定してください。
- 元画像がまだない場合は、
image-generationスキル(python <image-generation>/scripts/gemini-generate.py)で作成し、ここで加工してください。ファイルに加工を適用した状態で保存する必要がある場合(ソーシャル画像、メール、OG 画像)は、CSS ではなく Pillow を使用してください。
ステップ 1:CSS フィルターの組み合わせ
個別のフィルター
| フィルター | 範囲 | 効果 |
|---|---|---|
| brightness() | 0-2+ | 暗くする(< 1)または明るくする(> 1) |
| contrast() | 0-2+ | コントラストを下げる(< 1)または上げる(> 1) |
| saturate() | 0-3+ | 彩度を下げる(0)または鮮やかにする(> 1) |
| grayscale() | 0-1 | 色を取り除く |
| sepia() | 0-1 | 暖かみのあるビンテージ調にする |
| hue-rotate() | 0-360deg | すべての色相を変更する |
| blur() | 0-20px+ | ガウスぼかし |
フィルタープリセットのレシピ
.filter-vintage { filter: sepia(0.3) contrast(1.1) brightness(1.05) saturate(0.9); }
.filter-cool { filter: saturate(0.85) contrast(1.1) brightness(1.02) hue-rotate(-10deg); }
.filter-bw { filter: grayscale(1) contrast(1.4) brightness(1.05); }
.filter-dreamy { filter: brightness(1.1) contrast(0.9) saturate(1.2) blur(0.5px); }
.filter-faded { filter: contrast(0.85) brightness(1.1) saturate(0.7); }
.filter-moody { filter: brightness(0.85) contrast(1.2) saturate(0.8); }
.filter-vivid { filter: contrast(1.15) saturate(1.4) brightness(1.02); }
フィルターを使ったホバー効果
.image-card img { filter: grayscale(0.8) brightness(0.9); transition: filter 0.4s ease; }
.image-card:hover img { filter: grayscale(0) brightness(1); }
ステップ 2:ブレンドモードのテクニック
よく使われるブレンドモード
| モード | 効果 | 用途 |
|---|---|---|
| multiply | 暗くする(白は消える) | 色の着色、白い背景の除去 |
| screen | 明るくする(黒は消える) | グロー効果 |
| overlay | コントラストを高める | 色のオーバーレイ |
| soft-light | 控えめなオーバーレイ | 穏やかな着色 |
| color | 色相と彩度を適用し、輝度を保持する | 写真の着色 |
| luminosity | このレイヤーの明るさと、下にあるレイヤーの色相・彩度を使用する | テクスチャの再着色 |
画像へのカラーオーバーレイ
.image-container { position: relative; }
.image-container::after {
content: ''; position: absolute; inset: 0;
background: var(--brand-500); mix-blend-mode: multiply; opacity: 0.6;
}
ステップ 3:画像のデュオトーン効果
画像の明部を一方の色に、暗部をもう一方の色に割り当てます。
CSS のみで作るデュオトーン
グレースケール画像をハイライト色に乗算します(白 → ハイライト、黒 → 黒)。次に、シャドウ色で暗部を明るくします(黒 → シャドウ)。すべての RGB チャンネルで、ハイライトはシャドウよりも明るくする必要があります。
.duotone { position: relative; isolation: isolate; background: #e2b94c; /* highlight */ }
.duotone img { display: block; width: 100%; filter: grayscale(1) contrast(1.2); mix-blend-mode: multiply; }
.duotone::after {
content: ''; position: absolute; inset: 0; pointer-events: none;
background: #1a1a2e; /* shadow */ mix-blend-mode: lighten;
}
SVG フィルターによるデュオトーン(正確に色を割り当て、あらゆる要素で使用可能)
tableValues は、シャドウからハイライトまでの各チャンネル値を 0-1 で表します(16 進数の値 ÷ 255):#1a1a2e → #e2b94c。
<svg width="0" height="0" aria-hidden="true" style="position:absolute">
<filter id="duotone-gold" color-interpolation-filters="sRGB">
<feColorMatrix type="matrix" values="0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0"/>
<feComponentTransfer>
<feFuncR type="table" tableValues="0.102 0.886"/>
<feFuncG type="table" tableValues="0.102 0.725"/>
<feFuncB type="table" tableValues="0.180 0.298"/>
</feComponentTransfer>
</filter>
</svg>
<img src="photo.jpg" alt="…" style="filter: url(#duotone-gold)">
よく使われるデュオトーンの組み合わせ
| シャドウ色 | ハイライト色 | 印象 |
|---|---|---|
| #1a1a2e | #e2b94c | 高級感、ゴールド+ネイビー |
| #0d1b2a | #3498db | テクノロジー、クールブルー |
| #2d1b4e | #ff6b6b | クリエイティブ、大胆 |
| #1b3a2a | #a7f3d0 | 自然、グリーン |
ステップ 4:画像のマスキング
clip-path の図形
.clip-circle { clip-path: circle(50%); }
.clip-rounded { clip-path: inset(0 round 1rem); }
.clip-diagonal { clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%); }
.clip-hexagon { clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%); }
グラデーションフェード用の mask-image
.image-fade-bottom {
mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
-webkit-mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
}
.image-vignette {
mask-image: radial-gradient(ellipse 70% 70% at center, black 50%, transparent 100%);
-webkit-mask-image: radial-gradient(ellipse 70% 70% at center, black 50%, transparent 100%);
}
テキスト形状のマスク
.image-text-mask {
background-image: url('photo.jpg'); background-size: cover;
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
background-clip: text; font-size: 8rem; font-weight: 900;
color: transparent; /* fallback if background-clip: text is unsupported */
}
表示サイズの装飾的なテキストに限って使用してください。文字の下にある写真は、ページの背景色に対して 3:1 のコントラストを保つ必要があります。また、スクリーンリーダー向けに、要素には実際のテキストを含めてください。
ステップ 5:背景画像のテクニック
背景全体を覆う
.hero-bg {
background: url('hero.jpg') center/cover no-repeat;
min-height: 80vh;
}
固定/視差背景
.parallax-section {
background: url('bg.jpg') center/cover no-repeat;
background-attachment: fixed;
min-height: 60vh;
}
@media (hover: none), (prefers-reduced-motion: reduce) {
.parallax-section { background-attachment: scroll; } /* iOS ignores fixed; parallax can trigger vestibular issues */
}
複数の背景レイヤー
.layered-bg {
background:
linear-gradient(to bottom, rgba(0,0,0,0.4), rgba(0,0,0,0.7)),
url('pattern.svg') repeat center / 64px 64px,
url('photo.jpg') no-repeat center / cover;
}
ステップ 6:画像オーバーレイのパターン
グラデーションオーバーレイ(テキストの読みやすさ向上)
.image-overlay-gradient { position: relative; }
.image-overlay-gradient::after {
content: ''; position: absolute; inset: 0;
background: linear-gradient(to top, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.3) 40%, transparent 100%);
}
.image-overlay-gradient .content { position: relative; z-index: 1; color: white; }
画像上のテキストは、その背後にある最も明るいピクセルに対しても、WCAG のコントラスト比(4.5:1、または24px以上/太字で18.66px以上の場合は3:1)を満たす必要があります。画像の平均ではなく、レンダリング後のスクリーンショットでテキストの背後にある領域を確認し、基準を満たすまでオーバーレイを強めてください。
ホバー時に表示するオーバーレイ
.card-image { position: relative; overflow: hidden; }
.card-image .overlay {
position: absolute; inset: 0;
background: oklch(from var(--brand-500) l c h / 0.85);
display: grid; place-items: center; opacity: 0; transition: opacity 0.3s ease;
}
.card-image:hover .overlay { opacity: 1; }
ステップ 7:画像グリッドとコラージュのレイアウト
メイソンリー風グリッド
.image-grid-masonry { columns: 3; column-gap: 1rem; }
.image-grid-masonry img { display: block; width: 100%; margin-bottom: 1rem; border-radius: 0.5rem; break-inside: avoid; }
/* Note: columns flow top-to-bottom, so DOM/reading order runs down each column, not across rows */
@media (max-width: 768px) { .image-grid-masonry { columns: 2; } }
@media (max-width: 480px) { .image-grid-masonry { columns: 1; } }
CSS グリッドコラージュ
.image-collage {
display: grid; grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 200px); gap: 0.5rem;
}
.image-collage img:nth-child(1) { grid-column: 1 / 3; grid-row: 1 / 3; }
.image-collage img { width: 100%; height: 100%; object-fit: cover; border-radius: 0.5rem; }
ステップ 8:レスポンシブ画像のアートディレクション
解像度の切り替え(同じトリミングで複数のサイズ)
w 記述子には各ファイルの実際のピクセル幅を記述します。sizes は画像が画面上でどの幅で表示されるかをブラウザーに伝え、レイアウト前に適切な画像を選べるようにします。sizes がない場合、ブラウザーは 100vw として扱います。
<img src="card-800.jpg"
srcset="card-400.jpg 400w, card-800.jpg 800w, card-1200.jpg 1200w, card-1600.jpg 1600w"
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 400px"
alt="Team reviewing designs at a whiteboard" width="800" height="600"
loading="lazy" decoding="async">
アートディレクションとモダン形式(<picture>)
ブラウザーは一致した最初の<source> を使用するため、メディアクエリーの順に、次に形式の順に並べます(AVIF を WebP より先にします)。各 source には独自の srcset/sizes を指定します。ブレークポイントごとにアスペクト比を変える場合は、<source> の width/height で対応します。
<picture>
<source media="(max-width: 640px)" type="image/avif"
srcset="hero-mobile-640.avif 640w, hero-mobile-1280.avif 1280w" sizes="100vw" width="1280" height="1600">
<source media="(max-width: 640px)" type="image/webp"
srcset="hero-mobile-640.webp 640w, hero-mobile-1280.webp 1280w" sizes="100vw" width="1280" height="1600">
<source type="image/avif" srcset="hero-1600.avif 1600w, hero-2400.avif 2400w" sizes="100vw">
<source type="image/webp" srcset="hero-1600.webp 1600w, hero-2400.webp 2400w" sizes="100vw">
<img src="hero-1600.jpg" alt="Describe what the hero shows" width="1600" height="900"
fetchpriority="high" decoding="async">
</picture>
主なルール
- レイアウトシフトを防ぐため、(固有のアスペクト比を示す)
width属性とheight属性を必ず指定します。CSS を使えば、width: 100%; height: autoで引き続き流動的な表示にできます。 - ファーストビューより下の画像には
loading="lazy"を使用します。LCP/ヒーロー画像は遅延読み込みしないでください。既定のまま eager 読み込みにし、fetchpriority="high"を追加します。 - デコードによってレンダリングがブロックされないよう、
decoding="async"を使用します。 - 形式:AVIF(最もファイルサイズが小さく、現在の主要ブラウザーすべてでサポートされています)→ WebP →
<img src>の JPEG フォールバック。透明部分やシャープなエッジが必要なグラフィックにのみ PNG/SVG を使用します。まずは AVIF の品質を約50~65、WebP を約75~80に設定するのがおすすめです。 altには画像の目的を記述します。装飾画像にはalt=""を使用します。
バリエーションの生成
from PIL import Image # pip install Pillow (AVIF built in since Pillow 11.2; check features.check("avif"))
src = Image.open("hero.png").convert("RGB")
for w in (640, 1280, 1600, 2400):
im = src.resize((w, round(src.height * w / src.width)), Image.LANCZOS)
im.save(f"hero-{w}.webp", quality=78)
im.save(f"hero-{w}.avif", quality=55)
im.save(f"hero-{w}.jpg", quality=82, optimize=True, progressive=True)
ステップ 9:高度な効果のための SVG フィルター
すりガラス
.frosted-glass { backdrop-filter: blur(12px) saturate(180%); background: rgba(255,255,255,0.7); }
@supports not (backdrop-filter: blur(1px)) { .frosted-glass { background: rgba(255,255,255,0.92); } } /* keep text readable */
ノイズ/粒状テクスチャ
<svg width="0" height="0" aria-hidden="true" style="position:absolute">
<filter id="noise">
<feTurbulence type="fractalNoise" baseFrequency="0.65" numOctaves="3" stitchTiles="stitch"/>
<feColorMatrix type="saturate" values="0"/>
<feBlend in="SourceGraphic" mode="multiply"/>
</filter>
</svg>
ドロップシャドウ(形状に沿った影)
.shaped-shadow { filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2)); }
ステップ 10:Object-Fit と Object-Position
| 値 | 動作 |
|---|---|
| cover | コンテナーを埋め、はみ出した部分をトリミングします(最も一般的) |
| contain | 全体を収めますが、余白ができる場合があります |
| fill | 引き伸ばして埋めます(歪みます) |
| scale-down | contain と同様ですが、拡大はしません |
.card-image { width: 100%; height: 200px; object-fit: cover; object-position: center; }
.portrait { object-fit: cover; object-position: center top; }
.thumbnail { aspect-ratio: 1; object-fit: cover; border-radius: 0.75rem; }
クイックリファレンス
- 写真に手早く効果を加えるには CSS の
filterを使用します(brightness、contrast、saturate を組み合わせます)。 - 画像にカラーオーバーレイを重ねるには
mix-blend-mode: multiplyを使用します。 - デュオトーン=グレースケール画像+2色のブレンドレイヤーです。
- 幾何学的なマスクには
clip-path、グラデーションによるフェードにはmask-imageを使用します。 - モバイルでは
background-attachment: fixedを必ず無効にします(@media (hover: none))。 - オーバーレイを重ねる場合、画像上のテキストを読みやすくするには、下から上へのグラデーションを使用します。
- アートディレクション(ブレークポイントごとに異なるトリミング)には
<picture>を使用します。 - コンテンツ画像には
width、height、alt、srcset、sizesを必ず指定し、遅延読み込みはファーストビューより下の画像にのみ適用します。 - 画像コンテナーの表示を統一するには、
object-fit: coverとaspect-ratioを組み合わせます。 - CSS では実現できない効果には、SVG フィルター(noise、goo、displacement)を使用します。
処理結果を確認する
ページをレンダリングしてスクリーンショットを撮影し(npx playwright screenshot --full-page "file://$PWD/index.html" out.png、モバイルでは --viewport-size=375,800、ダークモードでは --color-scheme=dark も使用)、Read で画像を確認します。どの幅でも object-fit/clip-path によって顔や商品がトリミングされていないこと、画像上のテキストが最も条件の厳しい箇所でもコントラスト基準を満たしていること、デュオトーン/フィルターがブランドのイメージを損なわず、濁った印象になっていないこと、ブレンドモードやフィルターに対応していない環境でも表示が崩れていないことを確認します。ブラウザーで適切な srcset の候補が読み込まれていること(img.currentSrc)と、ヒーロー画像が遅延読み込みされていないことを確認します。