CSSだけで作る、ノイズと走査線が揺らぐグリッチテキストアニメーション

ビジュアル

CSSだけで作る、ノイズと走査線が揺らぐグリッチテキストアニメーション

投稿日2026/03/12

更新日2026/3/12

サイバー感やデジタル演出を取り入れたいとき、定番なのが「グリッチエフェクト」です。文字が一瞬崩れたり、色がズレたり、走査線が流れることで、画面にノイズ的なリアリティを与えることができます。

このアニメーションはJavaScriptを使わず、CSSのみで構成されています。疑似要素による文字の複製と clip-path を組み合わせることで、本物の信号エラーのような揺らぎを再現しています。

この記事では、CSSだけで作るグリッチテキストの仕組みとカスタマイズ方法をわかりやすく解説します。

Preview プレビュー

Code コード

<div class="kumonosu-main-wrapper">
	<div class="kumonosu-glitch-container">
		<div class="kumonosu-glitch-text" data-text="GLITCH">GLITCH</div>
		<div class="kumonosu-scanline"></div>
	</div>
</div>
* {
	margin: 0;
	padding: 0;
	box-sizing: border-box;
}
body {
	background: #000;
	font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.kumonosu-main-wrapper {
	min-height: 100vh;
	display: flex;
	justify-content: center;
	align-items: center;
	position: relative;
	overflow: hidden;
	width: 100%;
}
.kumonosu-main-wrapper::before {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background: repeating-linear-gradient(0deg, rgb(255 255 255 / .03) 0, rgb(255 255 255 / .03) 1px, transparent 1px, transparent 2px);
	pointer-events: none;
	animation: kumonosu-noise 0.5s infinite;
	z-index: 1;
}
.kumonosu-glitch-container {
	position: relative;
	padding: 40px;
	display: flex;
	justify-content: center;
	align-items: center;
	z-index: 2;
}
.kumonosu-glitch-container::before {
	content: '';
	position: absolute;
	top: -20px;
	left: -20px;
	right: -20px;
	bottom: -20px;
	background: radial-gradient(circle at 30% 50%, rgb(233 69 96 / .2) 0%, transparent 50%);
	filter: blur(40px);
	animation: kumonosu-glowPulse 3s infinite;
	z-index: -1;
}
.kumonosu-glitch-text {
	font-size: 20vw;
	font-weight: 900;
	color: #fff;
	text-shadow: 2px 2px 4px rgb(0 0 0 / .3), 0 0 20px rgb(233 69 96 / .5);
	position: relative;
	display: inline-block;
	animation: kumonosu-glitch-skew 4s infinite;
	letter-spacing: 10px;
	white-space: nowrap;
}
.kumonosu-glitch-text::before,
.kumonosu-glitch-text::after {
	content: attr(data-text);
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background: transparent;
}
.kumonosu-glitch-text::before {
	animation: kumonosu-glitch-1 0.8s infinite linear alternate-reverse;
	color: #e94560;
	text-shadow: 2px 0 0 #4e9eff, -2px 0 0 lime;
	z-index: -1;
}
.kumonosu-glitch-text::after {
	animation: kumonosu-glitch-2 0.8s infinite linear alternate-reverse;
	color: #4e9eff;
	text-shadow: 2px 0 0 #e94560, -2px 0 0 #ff0;
	z-index: -2;
}
.kumonosu-scanline {
	position: absolute;
	top: -50%;
	left: 0;
	width: 100%;
	height: 200%;
	background: linear-gradient(to bottom, transparent 50%, rgb(0 0 0 / .3) 50%);
	background-size: 100% 4px;
	pointer-events: none;
	animation: kumonosu-scanline-anim 8s linear infinite;
	z-index: 10;
}
@keyframes kumonosu-glitch-skew {
	0%, 100% {
		transform: skew(0deg)
	}
	2% {
		transform: skew(2deg)
	}
	4% {
		transform: skew(-2deg)
	}
	6% {
		transform: skew(1deg)
	}
	8% {
		transform: skew(-1deg)
	}
	10%, 90% {
		transform: skew(0deg)
	}
}
@keyframes kumonosu-glitch-1 {
	0%, 100% {
		clip-path: inset(0 0 0 0);
		transform: translate(0);
		opacity: .8
	}
	10% {
		clip-path: inset(20% 0 30% 0);
		transform: translate(-5px, 3px);
		opacity: 1
	}
	30% {
		clip-path: inset(40% 0 40% 0);
		transform: translate(-5px, 5px);
		opacity: 1
	}
	50% {
		clip-path: inset(30% 0 50% 0);
		transform: translate(-3px, 3px);
		opacity: .9
	}
	80% {
		clip-path: inset(15% 0 70% 0);
		transform: translate(4px, -4px);
		opacity: 1
	}
}
@keyframes kumonosu-glitch-2 {
	0%, 100% {
		clip-path: inset(0 0 0 0);
		transform: translate(0);
		opacity: .8
	}
	20% {
		clip-path: inset(30% 0 50% 0);
		transform: translate(-5px, 3px);
		opacity: 1
	}
	40% {
		clip-path: inset(40% 0 40% 0);
		transform: translate(-5px, 5px);
		opacity: .9
	}
	70% {
		clip-path: inset(50% 0 30% 0);
		transform: translate(4px, -4px);
		opacity: .8
	}
}
@keyframes kumonosu-noise {
	0%, 100% {
		transform: translate(0, 0)
	}
	10% {
		transform: translate(-0.5%, -0.5%)
	}
	20% {
		transform: translate(0.5%, 0.5%)
	}
	40% {
		transform: translate(0.5%, -0.5%)
	}
}
@keyframes kumonosu-scanline-anim {
	0% {
		transform: translateY(-20%)
	}
	100% {
		transform: translateY(20%)
	}
}
@keyframes kumonosu-glowPulse {
	0%, 100% {
		opacity: .5;
		transform: scale(1)
	}
	50% {
		opacity: .8;
		transform: scale(1.1)
	}
}
@media (max-width:768px) {
	.kumonosu-glitch-text {
		letter-spacing: 5px
	}
}
@media (max-width:480px) {
	.kumonosu-glitch-text {
		letter-spacing: 3px;
		font-size: 25vw;
	}
}
.kumonosu-glitch-text:hover {
	animation: kumonosu-glitch-skew 1s infinite
}

Explanation 詳しい説明

仕様

このアニメーションは、1つのテキスト要素を基準に疑似要素で文字を複製し、それぞれを異なる動きでズラすことでグリッチ表現を作っています。

主な仕組みは次の通りです。

・::before と ::after で文字を複製
・clip-path で表示領域を断片的に分割
・translate によるズレ演出
・text-shadow によるRGB分離表現
・repeating-linear-gradient によるノイズ背景
・スキャンラインを別レイヤーで常時移動

文字本体は安定した状態を保ち、複製レイヤーのみを動かすことで、読みやすさを維持したままグリッチ感を演出しています。

カスタム

見た目の印象はCSSの値を変更するだけで大きく調整できます。

主なカスタマイズポイントは次の通りです。

・文字サイズは .kumonosu-glitch-text の font-size
・文字間隔は letter-spacing
・グリッチの強さは translate の移動量
・ノイズ密度は repeating-linear-gradient のサイズ
・RGBカラーは text-shadow の色
・発光感は text-shadow のぼかし量
・スキャンライン速度は animation-duration

data-text の内容を変更すれば、HTMLを書き換えずに表示テキストを同期できます。

注意点

グリッチ表現は複数レイヤーを同時に描画するため、環境によっては負荷が増える場合があります。

注意点は次の通りです。

・clip-path アニメーションは描画コストが高め
・大きなフォントサイズではGPU負荷が上がる
・text-shadow の多用はモバイルで重くなる場合がある
・長文テキストには不向き
・常時アニメーションのため省電力環境では注意

実運用ではタイトルやヒーローセクションなど、限定された範囲で使用するとパフォーマンスと演出のバランスが取りやすくなります。

まとめ

このグリッチテキストは、CSSのみで複数レイヤーを制御し、ノイズ・色ズレ・走査線を組み合わせたサイバー演出を実現したアニメーションです。

JavaScriptなしでも印象的なビジュアルを作れるため、ヒーロータイトルやローディング演出、ブランドロゴなどに最適です。シンプルな構造ながら拡張性も高く、デザイン次第で幅広い表現に応用できます。

Together 一緒に読まれている記事