グリッチテキストローダー
サイバーパンク風のグリッチエフェクトがかかったテキストのローディング画面。
INITIALIZING PROTOCOLS…
サイバーパンク風のグリッチエフェクト(ノイズ効果)を取り入れた、テキストベースのローディングアニメーションです。システムが起動していくような緊迫感や未来的な雰囲気を演出したい場合に最適です。
ユースケースと特徴 (Use Cases & Features)
-
SF/サイバーパンク風のWebサイトの初期ローディング画面。
-
ゲームやポートフォリオサイトのシーン切り替え・トランジション。
-
CSSのclip-pathとtransformを駆使し、複雑なJavaScriptを用いずに高速なグリッチアニメーションを実現。
デザインとUXのポイント (Design & UX)
-
色収差(Chromatic Aberration): シアン(
#00fff9)とマゼンタ(#ff00c1)の影を微妙にずらすことで、古いブラウン管モニターや破損したディスプレイのような視覚効果を再現しています。 -
スキャンライン(走査線): 背景全体に薄い横線のグラデーションを重ねることで、アナログなモニターの質感を付与しています。
-
ランダムな動きの模倣:
clip-pathとtransformを不規則に変化させるキーフレームを作成し、本物のバグのようなランダム性を表現しています。
カスタマイズ方法 (Customization Guide)
-
テキストの変更: HTML内の
data-text属性と、タグの中身のテキストを両方変更してください(例:data-text="LOADING...")。 -
配色の変更: シアンとマゼンタのカラーコード(
#00fff9,#ff00c1)を、プロジェクトのテーマカラーに合わせて変更することで、異なるテイストのグリッチを作成できます。 -
スピードの調整: CSSの
animationに設定されている秒数(例:2s,3s)を変更することで、グリッチの激しさを調整可能です。
実装コード (Implementation)
<div class="glitch-loader-container flex flex-col items-center justify-center min-h-[400px] w-full bg-[#050510] rounded-xl overflow-hidden relative border border-slate-800">
<!-- Scanline Overlay -->
<div class="scanlines"></div>
<div class="glitch-wrapper mb-8 relative z-20">
<div class="glitch-text text-4xl sm:text-6xl" data-text="SYSTEM_BOOT">SYSTEM_BOOT</div>
</div>
<div class="progress-bar-container w-48 sm:w-64 h-2 bg-slate-900 border border-slate-700 relative z-20 overflow-hidden">
<div class="progress-bar-fill h-full bg-[#00fff9] relative"></div>
</div>
<div class="mt-4 text-[#ff00c1] text-xs font-mono tracking-widest z-20 blink-text">
INITIALIZING PROTOCOLS...
</div>
</div>
<style>
.scanlines {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(
to bottom,
rgba(255,255,255,0),
rgba(255,255,255,0) 50%,
rgba(0,0,0,0.2) 50%,
rgba(0,0,0,0.2)
);
background-size: 100% 4px;
z-index: 10;
pointer-events: none;
}
.glitch-text {
font-family: 'Courier New', Courier, monospace;
font-weight: 800;
color: #fff;
position: relative;
letter-spacing: 0.1em;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.3);
animation: glitch-skew 2s infinite linear alternate-reverse;
}
.glitch-text::before,
.glitch-text::after {
content: attr(data-text);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #050510;
z-index: -1;
}
.glitch-text::before {
left: 2px;
text-shadow: -2px 0 #ff00c1;
animation: glitch-anim-1 2s infinite linear alternate-reverse;
}
.glitch-text::after {
left: -2px;
text-shadow: -2px 0 #00fff9, 2px 2px #ff00c1;
animation: glitch-anim-2 3s infinite linear alternate-reverse;
}
@keyframes glitch-skew {
0% { transform: skew(0deg); }
2% { transform: skew(-10deg); }
4% { transform: skew(10deg); }
6% { transform: skew(0deg); }
90% { transform: skew(0deg); }
92% { transform: skew(5deg); }
94% { transform: skew(-5deg); }
96% { transform: skew(0deg); }
}
@keyframes glitch-anim-1 {
0% { clip-path: inset(20% 0 80% 0); transform: translate(-2px, 1px); }
10% { clip-path: inset(50% 0 10% 0); transform: translate(2px, -1px); }
20% { clip-path: inset(80% 0 5% 0); transform: translate(-2px, 2px); }
30% { clip-path: inset(10% 0 60% 0); transform: translate(2px, -2px); }
40% { clip-path: inset(30% 0 20% 0); transform: translate(-2px, 1px); }
50% { clip-path: inset(90% 0 5% 0); transform: translate(2px, -1px); }
60% { clip-path: inset(40% 0 40% 0); transform: translate(-2px, 2px); }
70% { clip-path: inset(70% 0 20% 0); transform: translate(2px, -2px); }
80% { clip-path: inset(5% 0 80% 0); transform: translate(-2px, 1px); }
90% { clip-path: inset(60% 0 10% 0); transform: translate(2px, -1px); }
100% { clip-path: inset(20% 0 50% 0); transform: translate(-2px, 2px); }
}
@keyframes glitch-anim-2 {
0% { clip-path: inset(10% 0 60% 0); transform: translate(2px, -1px); }
10% { clip-path: inset(80% 0 5% 0); transform: translate(-2px, 2px); }
20% { clip-path: inset(30% 0 40% 0); transform: translate(2px, -2px); }
30% { clip-path: inset(5% 0 90% 0); transform: translate(-2px, 1px); }
40% { clip-path: inset(60% 0 10% 0); transform: translate(2px, -1px); }
50% { clip-path: inset(20% 0 30% 0); transform: translate(-2px, 2px); }
60% { clip-path: inset(90% 0 5% 0); transform: translate(2px, -2px); }
70% { clip-path: inset(40% 0 50% 0); transform: translate(-2px, 1px); }
80% { clip-path: inset(70% 0 20% 0); transform: translate(2px, -1px); }
90% { clip-path: inset(15% 0 65% 0); transform: translate(-2px, 2px); }
100% { clip-path: inset(50% 0 10% 0); transform: translate(2px, -2px); }
}
.progress-bar-fill {
box-shadow: 0 0 10px #00fff9, 0 0 20px #00fff9;
animation: progress-anim 4s infinite, progress-glitch 2s infinite;
}
@keyframes progress-anim {
0% { width: 0%; }
30% { width: 45%; }
50% { width: 45%; }
70% { width: 85%; }
90% { width: 100%; }
100% { width: 100%; }
}
@keyframes progress-glitch {
0%, 100% { transform: translateX(0); opacity: 1; }
10% { transform: translateX(-2px); opacity: 0.8; }
15% { transform: translateX(2px); opacity: 1; }
20% { transform: translateX(0); opacity: 0.9; }
}
.blink-text {
animation: blink 1s step-end infinite;
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
</style> ブラウザ対応状況 (Browser Support)
-
モダンブラウザ(Chrome, Firefox, Safari, Edge)で動作します。
-
clip-path: inset(...)プロパティを利用しているため、一部の古いブラウザでは四角形でのクリッピングが正確に行われない場合がありますが、アニメーションの破綻は生じません。