404ページ 中級

グリッチ404

「404」がノイズとともに揺れ、RGBがずれるサイバーなグリッチ404。テック系やゲーム、音楽系サイトの世界観に合う、強い印象を残すエラーページです。動きで“壊れた感”を演出します。

#404#error#glitch#cyber

ライブデモ

使用例(お題: SaaS FlowDesk)

この技法を「SaaS FlowDesk」というテーマのダミーサイトで実際に使った例です。

HTML
<!-- FlowDesk:テック系のグリッチ404 -->
<section class="nfg">
  <div class="nfg-inner">
    <p class="nfg-404" data-text="404">404</p>
    <h1 class="nfg-title" data-text="PAGE NOT FOUND">PAGE NOT FOUND</h1>
    <p class="nfg-sub">// requested resource was not found on this server</p>
    <button class="nfg-btn" type="button">RETURN TO DASHBOARD</button>
  </div>
  <div class="nfg-scan" aria-hidden="true"></div>
</section>
CSS
/* FlowDesk(SaaS/テック):グリッチ404の再スキン */
* { box-sizing: border-box; }
body { margin: 0; font-family: "JetBrains Mono", "Segoe UI", monospace; }

.nfg { position: relative; width: 100%; min-height: 380px; display: grid; place-content: center; text-align: center; padding: 30px 26px; overflow: hidden; background: #080a14; color: #dfe5ff; }
.nfg-inner { position: relative; z-index: 2; }
.nfg-404 { position: relative; margin: 0; font-size: 110px; font-weight: 900; line-height: 1; letter-spacing: .02em; color: #eef1ff; }
.nfg-404::before, .nfg-404::after { content: attr(data-text); position: absolute; inset: 0; }
.nfg-404::before { color: #4f6bff; left: 2px; animation: nfg-g1 2.4s steps(2) infinite; }
.nfg-404::after { color: #22d3ee; left: -2px; animation: nfg-g2 3s steps(2) infinite; }
@keyframes nfg-g1 { 0%,100% { clip-path: inset(0 0 85% 0); transform: translate(0,0); } 20% { clip-path: inset(40% 0 30% 0); transform: translate(-3px,1px); } 40% { clip-path: inset(70% 0 5% 0); transform: translate(3px,-1px); } 60% { clip-path: inset(10% 0 60% 0); transform: translate(-2px,0); } 80% { clip-path: inset(50% 0 20% 0); transform: translate(2px,1px); } }
@keyframes nfg-g2 { 0%,100% { clip-path: inset(60% 0 10% 0); transform: translate(0,0); } 25% { clip-path: inset(20% 0 55% 0); transform: translate(3px,-1px); } 50% { clip-path: inset(80% 0 5% 0); transform: translate(-3px,1px); } 75% { clip-path: inset(30% 0 40% 0); transform: translate(2px,0); } }
.nfg-title { margin: 6px 0 0; font-size: 18px; font-weight: 700; letter-spacing: .3em; color: #8ea3ff; position: relative; }
.nfg-title::after { content: attr(data-text); position: absolute; inset: 0; color: #22d3ee; mix-blend-mode: screen; animation: nfg-shift 2s steps(3) infinite; opacity: .7; }
@keyframes nfg-shift { 0%,100% { transform: translate(0,0); } 33% { transform: translate(-2px,0); } 66% { transform: translate(2px,0); } }
.nfg-sub { margin: 16px 0 24px; font-size: 12.5px; color: #5f6a9a; letter-spacing: .04em; }
.nfg-btn { font: inherit; font-size: 13px; font-weight: 700; letter-spacing: .1em; color: #080a14; background: #4f6bff; border: none; padding: 12px 24px; border-radius: 8px; cursor: pointer; transition: filter .15s ease, transform .15s ease; }
.nfg-btn:hover { filter: brightness(1.1); transform: translateY(-2px); }
.nfg-scan { position: absolute; inset: 0; z-index: 1; pointer-events: none; background: repeating-linear-gradient(0deg, rgba(255,255,255,.03) 0 1px, transparent 1px 3px); animation: nfg-scanmove 8s linear infinite; }
@keyframes nfg-scanmove { from { background-position-y: 0; } to { background-position-y: 100px; } }

@media (prefers-reduced-motion: reduce) { .nfg-404::before, .nfg-404::after, .nfg-title::after, .nfg-scan, .nfg-btn { animation: none; transition: none; } }

実装ガイド

使いどころ

テック・ゲーム・音楽系など、サイバーな世界観の404に。「404」がノイズとともに揺れ、RGBがずれる強い印象のエラーページです。

実装時の注意点

data-text を持たせた擬似要素を2層重ね、色をずらして clip-path アニメーションで切り刻みます。走査線(scanline)を repeating-linear-gradient で重ねて画面の“壊れ”感を演出。

対応ブラウザ

clip-path・mix-blend-mode・擬似要素アニメーションは全モダンブラウザ対応。

よくある失敗

グリッチが激しすぎると可読性と快適性を損なうため強度はほどほどに。reduced-motion では必ず静止させる(点滅は健康配慮上も重要)。等幅フォントが読み込めない環境のフォールバックを指定。

応用例

ホバーで一瞬グリッチ、配色のブランド対応、404以外(メンテナンス画面等)への流用、効果音(任意)との組み合わせなどに展開できます。

コード

HTML
<!-- グリッチ404 -->
<section class="nfg">
  <div class="nfg-inner">
    <p class="nfg-404" data-text="404">404</p>
    <h1 class="nfg-title" data-text="PAGE NOT FOUND">PAGE NOT FOUND</h1>
    <p class="nfg-sub">// 接続先のリソースが見つかりませんでした</p>
    <button class="nfg-btn" type="button">RETURN HOME</button>
  </div>
  <div class="nfg-scan" aria-hidden="true"></div>
</section>
CSS
* { box-sizing: border-box; }
body { margin: 0; font-family: "JetBrains Mono", "Segoe UI", monospace; }

.nfg { position: relative; width: 100%; min-height: 380px; display: grid; place-content: center; text-align: center; padding: 30px 26px; overflow: hidden; background: #07080d; color: #d8f5ff; }
.nfg-inner { position: relative; z-index: 2; }

.nfg-404 { position: relative; margin: 0; font-size: 110px; font-weight: 900; line-height: 1; letter-spacing: .02em; color: #eafcff; }
.nfg-404::before, .nfg-404::after { content: attr(data-text); position: absolute; inset: 0; }
.nfg-404::before { color: #ff2e6e; left: 2px; animation: nfg-g1 2.4s steps(2) infinite; }
.nfg-404::after { color: #21d4fd; left: -2px; animation: nfg-g2 3s steps(2) infinite; }
@keyframes nfg-g1 { 0%,100% { clip-path: inset(0 0 85% 0); transform: translate(0,0); } 20% { clip-path: inset(40% 0 30% 0); transform: translate(-3px,1px); } 40% { clip-path: inset(70% 0 5% 0); transform: translate(3px,-1px); } 60% { clip-path: inset(10% 0 60% 0); transform: translate(-2px,0); } 80% { clip-path: inset(50% 0 20% 0); transform: translate(2px,1px); } }
@keyframes nfg-g2 { 0%,100% { clip-path: inset(60% 0 10% 0); transform: translate(0,0); } 25% { clip-path: inset(20% 0 55% 0); transform: translate(3px,-1px); } 50% { clip-path: inset(80% 0 5% 0); transform: translate(-3px,1px); } 75% { clip-path: inset(30% 0 40% 0); transform: translate(2px,0); } }

.nfg-title { margin: 6px 0 0; font-size: 18px; font-weight: 700; letter-spacing: .3em; color: #8be9ff; position: relative; }
.nfg-title::after { content: attr(data-text); position: absolute; inset: 0; color: #ff2e6e; mix-blend-mode: screen; animation: nfg-shift 2s steps(3) infinite; opacity: .7; }
@keyframes nfg-shift { 0%,100% { transform: translate(0,0); } 33% { transform: translate(-2px,0); } 66% { transform: translate(2px,0); } }

.nfg-sub { margin: 16px 0 24px; font-size: 12.5px; color: #5f7a8a; letter-spacing: .04em; }
.nfg-btn { font: inherit; font-size: 13px; font-weight: 700; letter-spacing: .12em; color: #07080d; background: #21d4fd; border: none; padding: 12px 24px; border-radius: 8px; cursor: pointer; transition: filter .15s ease, transform .15s ease; }
.nfg-btn:hover { filter: brightness(1.1); transform: translateY(-2px); }

/* 走査線 */
.nfg-scan { position: absolute; inset: 0; z-index: 1; pointer-events: none; background: repeating-linear-gradient(0deg, rgba(255,255,255,.03) 0 1px, transparent 1px 3px); animation: nfg-scanmove 8s linear infinite; }
@keyframes nfg-scanmove { from { background-position-y: 0; } to { background-position-y: 100px; } }

@media (prefers-reduced-motion: reduce) { .nfg-404::before, .nfg-404::after, .nfg-title::after, .nfg-scan, .nfg-btn { animation: none; transition: none; } }

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

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

# 追加してほしい効果
グリッチ404(404ページ)
「404」がノイズとともに揺れ、RGBがずれるサイバーなグリッチ404。テック系やゲーム、音楽系サイトの世界観に合う、強い印象を残すエラーページです。動きで“壊れた感”を演出します。

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

# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- グリッチ404 -->
<section class="nfg">
  <div class="nfg-inner">
    <p class="nfg-404" data-text="404">404</p>
    <h1 class="nfg-title" data-text="PAGE NOT FOUND">PAGE NOT FOUND</h1>
    <p class="nfg-sub">// 接続先のリソースが見つかりませんでした</p>
    <button class="nfg-btn" type="button">RETURN HOME</button>
  </div>
  <div class="nfg-scan" aria-hidden="true"></div>
</section>

【CSS】
* { box-sizing: border-box; }
body { margin: 0; font-family: "JetBrains Mono", "Segoe UI", monospace; }

.nfg { position: relative; width: 100%; min-height: 380px; display: grid; place-content: center; text-align: center; padding: 30px 26px; overflow: hidden; background: #07080d; color: #d8f5ff; }
.nfg-inner { position: relative; z-index: 2; }

.nfg-404 { position: relative; margin: 0; font-size: 110px; font-weight: 900; line-height: 1; letter-spacing: .02em; color: #eafcff; }
.nfg-404::before, .nfg-404::after { content: attr(data-text); position: absolute; inset: 0; }
.nfg-404::before { color: #ff2e6e; left: 2px; animation: nfg-g1 2.4s steps(2) infinite; }
.nfg-404::after { color: #21d4fd; left: -2px; animation: nfg-g2 3s steps(2) infinite; }
@keyframes nfg-g1 { 0%,100% { clip-path: inset(0 0 85% 0); transform: translate(0,0); } 20% { clip-path: inset(40% 0 30% 0); transform: translate(-3px,1px); } 40% { clip-path: inset(70% 0 5% 0); transform: translate(3px,-1px); } 60% { clip-path: inset(10% 0 60% 0); transform: translate(-2px,0); } 80% { clip-path: inset(50% 0 20% 0); transform: translate(2px,1px); } }
@keyframes nfg-g2 { 0%,100% { clip-path: inset(60% 0 10% 0); transform: translate(0,0); } 25% { clip-path: inset(20% 0 55% 0); transform: translate(3px,-1px); } 50% { clip-path: inset(80% 0 5% 0); transform: translate(-3px,1px); } 75% { clip-path: inset(30% 0 40% 0); transform: translate(2px,0); } }

.nfg-title { margin: 6px 0 0; font-size: 18px; font-weight: 700; letter-spacing: .3em; color: #8be9ff; position: relative; }
.nfg-title::after { content: attr(data-text); position: absolute; inset: 0; color: #ff2e6e; mix-blend-mode: screen; animation: nfg-shift 2s steps(3) infinite; opacity: .7; }
@keyframes nfg-shift { 0%,100% { transform: translate(0,0); } 33% { transform: translate(-2px,0); } 66% { transform: translate(2px,0); } }

.nfg-sub { margin: 16px 0 24px; font-size: 12.5px; color: #5f7a8a; letter-spacing: .04em; }
.nfg-btn { font: inherit; font-size: 13px; font-weight: 700; letter-spacing: .12em; color: #07080d; background: #21d4fd; border: none; padding: 12px 24px; border-radius: 8px; cursor: pointer; transition: filter .15s ease, transform .15s ease; }
.nfg-btn:hover { filter: brightness(1.1); transform: translateY(-2px); }

/* 走査線 */
.nfg-scan { position: absolute; inset: 0; z-index: 1; pointer-events: none; background: repeating-linear-gradient(0deg, rgba(255,255,255,.03) 0 1px, transparent 1px 3px); animation: nfg-scanmove 8s linear infinite; }
@keyframes nfg-scanmove { from { background-position-y: 0; } to { background-position-y: 100px; } }

@media (prefers-reduced-motion: reduce) { .nfg-404::before, .nfg-404::after, .nfg-title::after, .nfg-scan, .nfg-btn { animation: none; transition: none; } }

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

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