グリッチテキスト

疑似要素でRGBをずらした2枚のコピーを clip-path で切り抜き、デジタルノイズ風のグリッチを作ります。サイバー/テック系の見出しに。

#css#glitch#animation

ライブデモ

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

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

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

  <section class="hero">
    <p class="eyebrow">DIGITAL SINGLE 配信開始</p>
    <h1 class="glitch" data-text="電脳サクラ">電脳サクラ</h1>
    <p class="lead">サイバーな世界で咲き誇る、新曲MVを公開。<br>各配信サービスにて好評配信中。</p>
    <div class="row">
      <span class="chip">▶ MVを見る</span>
      <span class="chip ghost">楽曲をきく</span>
    </div>
  </section>
</div>
CSS
/* Sakura:グリッチ見出しが主役(サイバーMV告知) */
* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: "Yu Gothic", "Segoe UI", sans-serif;
  background:
    radial-gradient(600px 340px at 50% 0%, #2a1224 0%, transparent 60%),
    linear-gradient(165deg, #160a14 0%, #0d060c 100%);
  color: #ffd1e0;
  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: #ffd1e0; }
.petal { width: 14px; height: 14px; background: #ffd1e0; border-radius: 50% 0 50% 50%; transform: rotate(45deg); box-shadow: 0 0 8px #ff5e98; }
.tag { font-size: 11px; color: #6ef0ff; letter-spacing: 0.2em; font-weight: 700; border: 1px solid rgba(110,240,255,0.4); padding: 4px 10px; border-radius: 6px; }

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

/* グリッチ本体:擬似要素でRGBずらしのコピーをclip-pathで切る */
.glitch {
  position: relative;
  display: inline-block;
  margin-top: 18px;
  font-size: clamp(40px, 9.5vw, 70px);
  font-weight: 900; letter-spacing: 0.08em;
  color: #fff0f6;
  text-shadow: 0 0 8px rgba(255,94,152,0.5);
}
.glitch::before, .glitch::after {
  content: attr(data-text);
  position: absolute; left: 0; top: 0;
  width: 100%; height: 100%;
  overflow: hidden;
}
/* シアン側のずれ */
.glitch::before {
  color: #6ef0ff;
  left: 2px;
  text-shadow: -2px 0 #6ef0ff;
  animation: glitch-top 2.6s infinite linear alternate-reverse;
}
/* マゼンタ側のずれ */
.glitch::after {
  color: #ff2e7e;
  left: -2px;
  text-shadow: 2px 0 #ff2e7e;
  animation: glitch-bot 1.9s infinite linear alternate-reverse;
}
@keyframes glitch-top {
  0% { clip-path: inset(0 0 78% 0); }
  25% { clip-path: inset(20% 0 50% 0); }
  50% { clip-path: inset(40% 0 35% 0); }
  75% { clip-path: inset(12% 0 60% 0); }
  100% { clip-path: inset(55% 0 20% 0); }
}
@keyframes glitch-bot {
  0% { clip-path: inset(70% 0 8% 0); }
  25% { clip-path: inset(48% 0 30% 0); }
  50% { clip-path: inset(60% 0 12% 0); }
  75% { clip-path: inset(35% 0 42% 0); }
  100% { clip-path: inset(80% 0 4% 0); }
}

.lead { margin-top: 20px; font-size: 13.5px; line-height: 1.8; color: #c9a3b5; }
.row { margin-top: 18px; display: flex; gap: 12px; justify-content: center; }
.chip {
  font-size: 13px; font-weight: 700; color: #0d060c; background: #ff5e98;
  padding: 9px 20px; border-radius: 22px; cursor: pointer;
}
.chip.ghost { background: transparent; color: #6ef0ff; border: 1px solid #6ef0ff; }
.chip:hover { filter: brightness(1.1); }

@media (prefers-reduced-motion: reduce) {
  .glitch::before, .glitch::after { animation: none; }
}
JavaScript
// ときどき強めのグリッチ(横ずれ)を一瞬入れる
(function () {
  const el = document.querySelector('.glitch');
  if (!el) return; // null安全

  const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  if (reduce) return; // 控えめ設定では追加演出なし

  function burst() {
    // 横方向にわずかにずらして戻す
    el.style.transform = 'translateX(' + (Math.random() * 6 - 3) + 'px)';
    setTimeout(() => { el.style.transform = ''; }, 90);
    // 次のバーストまでランダム待機
    setTimeout(burst, 1500 + Math.random() * 2800);
  }
  setTimeout(burst, 1600);
})();

コード

HTML
<main class="stage">
  <!-- data-text を疑似要素で2枚コピーしてズラす -->
  <h1 class="glitch" data-text="GLITCH">GLITCH</h1>
  <p class="sub">疑似要素のRGBズレ+clipでデジタルノイズ</p>
</main>
CSS
* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  min-height: 360px;
  display: grid;
  place-items: center;
  background: #07070a;
  font-family: "Consolas", "Courier New", monospace;
  overflow: hidden;
  /* 走査線のかすかなオーバーレイ */
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,0.03) 0 1px, transparent 1px 3px);
}

.stage { text-align: center; }

.glitch {
  position: relative;
  font-size: clamp(56px, 17vw, 130px);
  font-weight: 800;
  letter-spacing: 0.06em;
  color: #f4f4f8;
  text-transform: uppercase;
}

/* 2枚のコピーをRGBずらしで重ねる */
.glitch::before,
.glitch::after {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  background: #07070a;
  overflow: hidden;
}

/* シアン側: 左にズレながら上下を切り抜く */
.glitch::before {
  color: #00f0ff;
  left: 2px;
  text-shadow: -2px 0 #00f0ff;
  animation: glitch-cyan 2.6s infinite linear alternate-reverse;
}

/* マゼンタ側: 右にズレる */
.glitch::after {
  color: #ff00c8;
  left: -2px;
  text-shadow: 2px 0 #ff00c8;
  animation: glitch-magenta 1.9s infinite linear alternate-reverse;
}

@keyframes glitch-cyan {
  0%   { clip-path: inset(8% 0 78% 0); transform: translateX(-3px); }
  20%  { clip-path: inset(40% 0 30% 0); transform: translateX(3px); }
  40%  { clip-path: inset(70% 0 10% 0); transform: translateX(-2px); }
  60%  { clip-path: inset(20% 0 60% 0); transform: translateX(2px); }
  80%  { clip-path: inset(55% 0 25% 0); transform: translateX(-3px); }
  100% { clip-path: inset(2% 0 88% 0); transform: translateX(2px); }
}
@keyframes glitch-magenta {
  0%   { clip-path: inset(80% 0 4% 0); transform: translateX(3px); }
  25%  { clip-path: inset(15% 0 68% 0); transform: translateX(-3px); }
  50%  { clip-path: inset(50% 0 28% 0); transform: translateX(2px); }
  75%  { clip-path: inset(30% 0 50% 0); transform: translateX(-2px); }
  100% { clip-path: inset(65% 0 12% 0); transform: translateX(3px); }
}

.sub {
  margin-top: 30px;
  font-size: 12px;
  letter-spacing: 0.2em;
  color: #5a5a6e;
}

@media (prefers-reduced-motion: reduce) {
  .glitch::before, .glitch::after { animation: none; opacity: 0.4; }
}

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

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

# 追加してほしい効果
グリッチテキスト(タイポグラフィ)
疑似要素でRGBをずらした2枚のコピーを clip-path で切り抜き、デジタルノイズ風のグリッチを作ります。サイバー/テック系の見出しに。

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

# 参考実装(この見た目・挙動を再現してください)
【HTML】
<main class="stage">
  <!-- data-text を疑似要素で2枚コピーしてズラす -->
  <h1 class="glitch" data-text="GLITCH">GLITCH</h1>
  <p class="sub">疑似要素のRGBズレ+clipでデジタルノイズ</p>
</main>

【CSS】
* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  min-height: 360px;
  display: grid;
  place-items: center;
  background: #07070a;
  font-family: "Consolas", "Courier New", monospace;
  overflow: hidden;
  /* 走査線のかすかなオーバーレイ */
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,0.03) 0 1px, transparent 1px 3px);
}

.stage { text-align: center; }

.glitch {
  position: relative;
  font-size: clamp(56px, 17vw, 130px);
  font-weight: 800;
  letter-spacing: 0.06em;
  color: #f4f4f8;
  text-transform: uppercase;
}

/* 2枚のコピーをRGBずらしで重ねる */
.glitch::before,
.glitch::after {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  background: #07070a;
  overflow: hidden;
}

/* シアン側: 左にズレながら上下を切り抜く */
.glitch::before {
  color: #00f0ff;
  left: 2px;
  text-shadow: -2px 0 #00f0ff;
  animation: glitch-cyan 2.6s infinite linear alternate-reverse;
}

/* マゼンタ側: 右にズレる */
.glitch::after {
  color: #ff00c8;
  left: -2px;
  text-shadow: 2px 0 #ff00c8;
  animation: glitch-magenta 1.9s infinite linear alternate-reverse;
}

@keyframes glitch-cyan {
  0%   { clip-path: inset(8% 0 78% 0); transform: translateX(-3px); }
  20%  { clip-path: inset(40% 0 30% 0); transform: translateX(3px); }
  40%  { clip-path: inset(70% 0 10% 0); transform: translateX(-2px); }
  60%  { clip-path: inset(20% 0 60% 0); transform: translateX(2px); }
  80%  { clip-path: inset(55% 0 25% 0); transform: translateX(-3px); }
  100% { clip-path: inset(2% 0 88% 0); transform: translateX(2px); }
}
@keyframes glitch-magenta {
  0%   { clip-path: inset(80% 0 4% 0); transform: translateX(3px); }
  25%  { clip-path: inset(15% 0 68% 0); transform: translateX(-3px); }
  50%  { clip-path: inset(50% 0 28% 0); transform: translateX(2px); }
  75%  { clip-path: inset(30% 0 50% 0); transform: translateX(-2px); }
  100% { clip-path: inset(65% 0 12% 0); transform: translateX(3px); }
}

.sub {
  margin-top: 30px;
  font-size: 12px;
  letter-spacing: 0.2em;
  color: #5a5a6e;
}

@media (prefers-reduced-motion: reduce) {
  .glitch::before, .glitch::after { animation: none; opacity: 0.4; }
}

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

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