画像で塗った文字

見出しテキストを background-clip: text で写真やアニメグラデにくり抜き、背景をゆっくり動かして文字の中で景色が流れて見える表現です。picsum画像とCSSグラデを重ね、文字の輪郭の中だけに動く絵を閉じ込めます。インパクトのあるヒーロー見出しに向いています。

#typography#background-clip#image#text

ライブデモ

使用例(お題: アイドルグループ Sakura)

この技法を「アイドルグループ Sakura」というテーマのダミーサイトで実際に使った例です。

HTML
<div class="page">
  <header class="nav">
    <div class="brand"><span class="petal"></span>Sakura</div>
    <span class="tag">MUSIC VIDEO</span>
  </header>

  <section class="hero">
    <p class="eyebrow">3rd SINGLE「春風ランウェイ」</p>
    <h1 class="imgfill">春風<br>ランウェイ</h1>
    <p class="lead">桜が魅せる、春のミュージックビデオ。<br>満開のステージを、文字の中に閉じ込めて。</p>
    <a class="btn">フルMVを再生</a>
  </section>
</div>
CSS
/* Sakura:画像で塗った見出しが主役(MV告知) */
* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: "Yu Gothic", "Hiragino Sans", "Segoe UI", sans-serif;
  background:
    radial-gradient(600px 320px at 50% -10%, #ffe3ec 0%, transparent 60%),
    linear-gradient(165deg, #fff5f8 0%, #ffe2ee 100%);
  color: #5a3a46;
  min-height: 400px;
  overflow: hidden;
}
.page { padding: 16px 26px; }

.nav { display: flex; align-items: center; justify-content: space-between; }
.brand { display: flex; align-items: center; gap: 9px; font-weight: 800; font-size: 16px; color: #e8638c; }
.petal { width: 14px; height: 14px; background: #ffd1e0; border-radius: 50% 0 50% 50%; transform: rotate(45deg); box-shadow: 0 0 8px rgba(232,99,140,0.4); }
.tag { font-size: 11px; color: #e8638c; letter-spacing: 0.2em; font-weight: 700; border: 1px solid rgba(232,99,140,0.4); padding: 4px 10px; border-radius: 14px; }

.hero { text-align: center; padding: 26px 6px 0; }
.eyebrow { font-size: 11px; letter-spacing: 0.18em; color: #c97a93; font-weight: 700; }

/* 画像クリップ見出し本体:写真+ピンクグラデを文字でくり抜く */
.imgfill {
  margin-top: 14px;
  font-size: clamp(40px, 9vw, 72px);
  font-weight: 900; line-height: 1.02; letter-spacing: 0.02em;
  background-image:
    linear-gradient(120deg, rgba(255,140,185,0.55), rgba(255,209,224,0.25)),
    url("https://picsum.photos/600/400?random=37");
  background-size: 180% 180%;
  background-position: 0% 50%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* 文字の中で景色をゆっくり動かす */
  animation: pan 9s ease-in-out infinite alternate;
  filter: drop-shadow(0 8px 18px rgba(232,99,140,0.3));
}
@keyframes pan {
  to { background-position: 100% 50%; }
}

.lead { margin-top: 20px; font-size: 13.5px; line-height: 1.8; color: #8a6573; }
.btn {
  display: inline-block; margin-top: 22px;
  background: #e8638c; color: #fff;
  padding: 11px 26px; border-radius: 24px; font-size: 13px; font-weight: 700;
  cursor: pointer; box-shadow: 0 10px 24px rgba(232,99,140,0.35);
}
.btn:hover { background: #f178a0; }

@media (prefers-reduced-motion: reduce) {
  .imgfill { animation: none; }
}
JavaScript
// 画像読み込み失敗時は桜グラデのみで見出しを成立させる
(function () {
  const title = document.querySelector('.imgfill');
  if (!title) return; // null安全

  // 背景画像を事前読み込みして可否を判定
  const url = 'https://picsum.photos/600/400?random=37';
  const probe = new Image();
  probe.onerror = () => {
    // 失敗時:画像レイヤーを外し、ピンクグラデだけで塗る
    title.style.backgroundImage =
      'linear-gradient(120deg, #ff8cb9, #ffd1e0)';
  };
  probe.src = url;
})();

コード

HTML
<main class="stage">
  <p class="kicker">IMAGE FILL</p>
  <!-- 見出しを画像+グラデでくり抜き、背景が中で動いて見える -->
  <h1 class="fill-title" aria-label="TRAVEL">TRAVEL</h1>
  <p class="caption">background-clip: text で写真をくり抜き</p>
</main>
CSS
/* 全体リセットと暗い背景 */
* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --bg-0: #0a0c14;
  --bg-1: #12172b;
  --dim: #8b93b8;
  /* くり抜きに使う写真(picsum)。seedで安定した風景を取得 */
  --photo: url("https://picsum.photos/seed/travel77/1200/600");
}

body {
  min-height: 360px;
  display: grid;
  place-items: center;
  font-family: "Segoe UI", "Helvetica Neue", system-ui, sans-serif;
  background:
    radial-gradient(900px 420px at 50% -20%, #1c2444 0%, transparent 60%),
    linear-gradient(160deg, var(--bg-0) 0%, var(--bg-1) 100%);
  color: #fff;
  overflow: hidden;
}

.stage { text-align: center; padding: 24px; width: 100%; }

.kicker {
  font-size: 12px;
  letter-spacing: 0.5em;
  font-weight: 700;
  color: var(--dim);
  margin-bottom: 16px;
  padding-left: 0.5em; /* レタースペース分の視覚補正 */
}

/* 画像+アニメグラデを文字でクリップする本体 */
.fill-title {
  font-size: clamp(72px, 19vw, 170px);
  font-weight: 900;
  line-height: 1;
  letter-spacing: 0.01em;
  /* 写真の上に動くグラデを重ね、文字内で景色が流れて見える */
  background-image:
    linear-gradient(100deg,
      rgba(255, 93, 143, 0.55) 0%,
      rgba(94, 234, 212, 0.0) 35%,
      rgba(94, 234, 212, 0.0) 65%,
      rgba(120, 115, 245, 0.55) 100%),
    var(--photo);
  background-size: 220% 100%, 160% auto;
  background-position: 0% 50%, 50% 50%;
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* 文字の存在感を出す影と縁 */
  filter: drop-shadow(0 10px 30px rgba(0, 0, 0, 0.5));
  /* 背景をゆっくり動かして文字の中で動いて見せる */
  animation: drift 14s ease-in-out infinite alternate;
}

/* グラデと写真を別速度でパン/ズームさせる */
@keyframes drift {
  0%   { background-position: 0% 50%, 35% 45%; background-size: 220% 100%, 160% auto; }
  50%  { background-position: 100% 50%, 65% 55%; background-size: 220% 100%, 190% auto; }
  100% { background-position: 0% 50%, 45% 50%; background-size: 220% 100%, 170% auto; }
}

.caption {
  margin-top: 18px;
  font-size: 14px;
  color: var(--dim);
  letter-spacing: 0.04em;
}

/* モーション控えめ設定への配慮(任意) */
@media (prefers-reduced-motion: reduce) {
  .fill-title { animation: none; }
}
JavaScript
// 画像くり抜き見出し:picsum読み込み失敗時はグラデにフォールバック
(function () {
  const title = document.querySelector('.fill-title');
  if (!title) return; // null安全

  // CSS変数からpicsumのURLを取り出す
  const raw = getComputedStyle(document.documentElement).getPropertyValue('--photo');
  const m = raw.match(/url\(["']?(.*?)["']?\)/);
  const src = m && m[1];
  if (!src) return;

  // 事前読み込みして成否を判定
  const img = new Image();
  img.onerror = function () {
    // 失敗時:写真を彩度の高いグラデに差し替え(見た目を維持)
    document.documentElement.style.setProperty(
      '--photo',
      'linear-gradient(120deg, #ff5d8f 0%, #b07bff 45%, #5eead4 100%)'
    );
  };
  img.src = src;
})();

🤖 AIエージェント用プロンプト

このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「画像で塗った文字」の効果を追加してください。

# 追加してほしい効果
画像で塗った文字(タイポグラフィ)
見出しテキストを background-clip: text で写真やアニメグラデにくり抜き、背景をゆっくり動かして文字の中で景色が流れて見える表現です。picsum画像とCSSグラデを重ね、文字の輪郭の中だけに動く絵を閉じ込めます。インパクトのあるヒーロー見出しに向いています。

# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】

# 参考実装(この見た目・挙動を再現してください)
【HTML】
<main class="stage">
  <p class="kicker">IMAGE FILL</p>
  <!-- 見出しを画像+グラデでくり抜き、背景が中で動いて見える -->
  <h1 class="fill-title" aria-label="TRAVEL">TRAVEL</h1>
  <p class="caption">background-clip: text で写真をくり抜き</p>
</main>

【CSS】
/* 全体リセットと暗い背景 */
* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --bg-0: #0a0c14;
  --bg-1: #12172b;
  --dim: #8b93b8;
  /* くり抜きに使う写真(picsum)。seedで安定した風景を取得 */
  --photo: url("https://picsum.photos/seed/travel77/1200/600");
}

body {
  min-height: 360px;
  display: grid;
  place-items: center;
  font-family: "Segoe UI", "Helvetica Neue", system-ui, sans-serif;
  background:
    radial-gradient(900px 420px at 50% -20%, #1c2444 0%, transparent 60%),
    linear-gradient(160deg, var(--bg-0) 0%, var(--bg-1) 100%);
  color: #fff;
  overflow: hidden;
}

.stage { text-align: center; padding: 24px; width: 100%; }

.kicker {
  font-size: 12px;
  letter-spacing: 0.5em;
  font-weight: 700;
  color: var(--dim);
  margin-bottom: 16px;
  padding-left: 0.5em; /* レタースペース分の視覚補正 */
}

/* 画像+アニメグラデを文字でクリップする本体 */
.fill-title {
  font-size: clamp(72px, 19vw, 170px);
  font-weight: 900;
  line-height: 1;
  letter-spacing: 0.01em;
  /* 写真の上に動くグラデを重ね、文字内で景色が流れて見える */
  background-image:
    linear-gradient(100deg,
      rgba(255, 93, 143, 0.55) 0%,
      rgba(94, 234, 212, 0.0) 35%,
      rgba(94, 234, 212, 0.0) 65%,
      rgba(120, 115, 245, 0.55) 100%),
    var(--photo);
  background-size: 220% 100%, 160% auto;
  background-position: 0% 50%, 50% 50%;
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* 文字の存在感を出す影と縁 */
  filter: drop-shadow(0 10px 30px rgba(0, 0, 0, 0.5));
  /* 背景をゆっくり動かして文字の中で動いて見せる */
  animation: drift 14s ease-in-out infinite alternate;
}

/* グラデと写真を別速度でパン/ズームさせる */
@keyframes drift {
  0%   { background-position: 0% 50%, 35% 45%; background-size: 220% 100%, 160% auto; }
  50%  { background-position: 100% 50%, 65% 55%; background-size: 220% 100%, 190% auto; }
  100% { background-position: 0% 50%, 45% 50%; background-size: 220% 100%, 170% auto; }
}

.caption {
  margin-top: 18px;
  font-size: 14px;
  color: var(--dim);
  letter-spacing: 0.04em;
}

/* モーション控えめ設定への配慮(任意) */
@media (prefers-reduced-motion: reduce) {
  .fill-title { animation: none; }
}

【JavaScript】
// 画像くり抜き見出し:picsum読み込み失敗時はグラデにフォールバック
(function () {
  const title = document.querySelector('.fill-title');
  if (!title) return; // null安全

  // CSS変数からpicsumのURLを取り出す
  const raw = getComputedStyle(document.documentElement).getPropertyValue('--photo');
  const m = raw.match(/url\(["']?(.*?)["']?\)/);
  const src = m && m[1];
  if (!src) return;

  // 事前読み込みして成否を判定
  const img = new Image();
  img.onerror = function () {
    // 失敗時:写真を彩度の高いグラデに差し替え(見た目を維持)
    document.documentElement.style.setProperty(
      '--photo',
      'linear-gradient(120deg, #ff5d8f 0%, #b07bff 45%, #5eead4 100%)'
    );
  };
  img.src = src;
})();

# 外部ライブラリ
なし(追加ライブラリ不要)

# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。