16 CSS Glitch Text Effects01 / 16
CSS Cyberpunk Glitch Text
Neon pink and cyan RGB-channel split glitch over a deep dark background, with clip-path horizontal slice displacement that fires at asymmetric intervals on an Orbitron-style headline.
Published
The code
<div class="gt-01"> <span class="gt-01__label">// system_breach_detected</span> <div class="gt-01__glitch" data-text="CYBERP∪NK">CYBERP∪NK</div> <div class="gt-01__bar"></div> <span class="gt-01__sub">Neural net v2.7.1 — online</span> </div>
<div class="gt-01">
<span class="gt-01__label">// system_breach_detected</span>
<div class="gt-01__glitch" data-text="CYBERP∪NK">CYBERP∪NK</div>
<div class="gt-01__bar"></div>
<span class="gt-01__sub">Neural net v2.7.1 — online</span>
</div>.gt-01,
.gt-01 *,
.gt-01 *::before,
.gt-01 *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.gt-01 ::selection {
background: #ff0090;
color: #000;
}
.gt-01 {
--neon-pink: #ff0090;
--neon-cyan: #00f5ff;
--bg: #050515;
--text-col: #e0e0ff;
min-height: 100vh;
background: var(--bg);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 32px;
padding: 40px 20px;
font-family: 'Orbitron', 'Rajdhani', 'Share Tech Mono', monospace;
position: relative;
overflow: hidden;
}
/* Scanline overlay */
.gt-01::before {
content: '';
position: absolute;
inset: 0;
background: repeating-linear-gradient(
0deg,
transparent,
transparent 2px,
rgba(0,245,255,0.03) 2px,
rgba(0,245,255,0.03) 4px
);
pointer-events: none;
z-index: 10;
}
.gt-01__label {
font-size: 11px;
letter-spacing: 4px;
color: var(--neon-cyan);
opacity: 0.6;
text-transform: uppercase;
}
.gt-01__glitch {
position: relative;
font-size: clamp(42px, 8vw, 80px);
font-weight: 900;
letter-spacing: 6px;
text-transform: uppercase;
color: var(--text-col);
text-shadow: 0 0 10px rgba(255,0,144,0.8), 0 0 30px rgba(255,0,144,0.4), 0 0 60px rgba(255,0,144,0.2);
animation: gt-01-flicker 4s infinite;
}
.gt-01__glitch::before,
.gt-01__glitch::after {
content: attr(data-text);
position: absolute;
inset: 0;
font: inherit;
letter-spacing: inherit;
}
/* Pink channel — clips top slices */
.gt-01__glitch::before {
color: var(--neon-pink);
text-shadow: none;
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
animation: gt-01-slice-top 2.5s steps(1) infinite;
left: 3px;
}
/* Cyan channel — clips bottom slices */
.gt-01__glitch::after {
color: var(--neon-cyan);
text-shadow: none;
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
animation: gt-01-slice-bot 2.5s steps(1) infinite;
left: -3px;
}
@keyframes gt-01-flicker {
0%,
94%,
96%,
100% {
opacity: 1;
}
95% {
opacity: 0.6;
}
}
@keyframes gt-01-slice-top {
0% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
5% {
transform: translateX(-8px);
clip-path: polygon(0 10%, 100% 10%, 100% 28%, 0 28%);
}
10% {
transform: translateX(6px);
clip-path: polygon(0 5%, 100% 5%, 100% 20%, 0 20%);
}
15% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
40% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
42% {
transform: translateX(10px);
clip-path: polygon(0 15%, 100% 15%, 100% 35%, 0 35%);
}
44% {
transform: translateX(-5px);
clip-path: polygon(0 8%, 100% 8%, 100% 25%, 0 25%);
}
46% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
100% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
}
@keyframes gt-01-slice-bot {
0% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
5% {
transform: translateX(8px);
clip-path: polygon(0 65%, 100% 65%, 100% 90%, 0 90%);
}
10% {
transform: translateX(-6px);
clip-path: polygon(0 55%, 100% 55%, 100% 80%, 0 80%);
}
15% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
40% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
42% {
transform: translateX(-10px);
clip-path: polygon(0 70%, 100% 70%, 100% 95%, 0 95%);
}
44% {
transform: translateX(4px);
clip-path: polygon(0 58%, 100% 58%, 100% 85%, 0 85%);
}
46% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
100% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
}
/* Glitch bar decoration */
.gt-01__bar {
width: 200px;
height: 2px;
background: linear-gradient(90deg, transparent, var(--neon-cyan), var(--neon-pink), transparent);
animation: gt-01-bar 3s linear infinite;
}
@keyframes gt-01-bar {
0% {
transform: scaleX(0.3) translateX(-100%);
opacity: 0;
}
50% {
transform: scaleX(1) translateX(0%);
opacity: 1;
}
100% {
transform: scaleX(0.3) translateX(100%);
opacity: 0;
}
}
.gt-01__sub {
font-size: 12px;
letter-spacing: 8px;
color: rgba(224,224,255,0.4);
text-transform: uppercase;
}
@media (prefers-reduced-motion: reduce) {
.gt-01__glitch,
.gt-01__glitch::before,
.gt-01__glitch::after,
.gt-01__bar {
animation: none;
}
.gt-01__glitch::before {
left: 0;
}
.gt-01__glitch::after {
left: 0;
}
}.gt-01,
.gt-01 *,
.gt-01 *::before,
.gt-01 *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.gt-01 ::selection {
background: #ff0090;
color: #000;
}
.gt-01 {
--neon-pink: #ff0090;
--neon-cyan: #00f5ff;
--bg: #050515;
--text-col: #e0e0ff;
min-height: 100vh;
background: var(--bg);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 32px;
padding: 40px 20px;
font-family: 'Orbitron', 'Rajdhani', 'Share Tech Mono', monospace;
position: relative;
overflow: hidden;
}
/* Scanline overlay */
.gt-01::before {
content: '';
position: absolute;
inset: 0;
background: repeating-linear-gradient(
0deg,
transparent,
transparent 2px,
rgba(0,245,255,0.03) 2px,
rgba(0,245,255,0.03) 4px
);
pointer-events: none;
z-index: 10;
}
.gt-01__label {
font-size: 11px;
letter-spacing: 4px;
color: var(--neon-cyan);
opacity: 0.6;
text-transform: uppercase;
}
.gt-01__glitch {
position: relative;
font-size: clamp(42px, 8vw, 80px);
font-weight: 900;
letter-spacing: 6px;
text-transform: uppercase;
color: var(--text-col);
text-shadow: 0 0 10px rgba(255,0,144,0.8), 0 0 30px rgba(255,0,144,0.4), 0 0 60px rgba(255,0,144,0.2);
animation: gt-01-flicker 4s infinite;
}
.gt-01__glitch::before,
.gt-01__glitch::after {
content: attr(data-text);
position: absolute;
inset: 0;
font: inherit;
letter-spacing: inherit;
}
/* Pink channel — clips top slices */
.gt-01__glitch::before {
color: var(--neon-pink);
text-shadow: none;
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
animation: gt-01-slice-top 2.5s steps(1) infinite;
left: 3px;
}
/* Cyan channel — clips bottom slices */
.gt-01__glitch::after {
color: var(--neon-cyan);
text-shadow: none;
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
animation: gt-01-slice-bot 2.5s steps(1) infinite;
left: -3px;
}
@keyframes gt-01-flicker {
0%,
94%,
96%,
100% {
opacity: 1;
}
95% {
opacity: 0.6;
}
}
@keyframes gt-01-slice-top {
0% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
5% {
transform: translateX(-8px);
clip-path: polygon(0 10%, 100% 10%, 100% 28%, 0 28%);
}
10% {
transform: translateX(6px);
clip-path: polygon(0 5%, 100% 5%, 100% 20%, 0 20%);
}
15% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
40% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
42% {
transform: translateX(10px);
clip-path: polygon(0 15%, 100% 15%, 100% 35%, 0 35%);
}
44% {
transform: translateX(-5px);
clip-path: polygon(0 8%, 100% 8%, 100% 25%, 0 25%);
}
46% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
100% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
}
@keyframes gt-01-slice-bot {
0% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
5% {
transform: translateX(8px);
clip-path: polygon(0 65%, 100% 65%, 100% 90%, 0 90%);
}
10% {
transform: translateX(-6px);
clip-path: polygon(0 55%, 100% 55%, 100% 80%, 0 80%);
}
15% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
40% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
42% {
transform: translateX(-10px);
clip-path: polygon(0 70%, 100% 70%, 100% 95%, 0 95%);
}
44% {
transform: translateX(4px);
clip-path: polygon(0 58%, 100% 58%, 100% 85%, 0 85%);
}
46% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
100% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
}
/* Glitch bar decoration */
.gt-01__bar {
width: 200px;
height: 2px;
background: linear-gradient(90deg, transparent, var(--neon-cyan), var(--neon-pink), transparent);
animation: gt-01-bar 3s linear infinite;
}
@keyframes gt-01-bar {
0% {
transform: scaleX(0.3) translateX(-100%);
opacity: 0;
}
50% {
transform: scaleX(1) translateX(0%);
opacity: 1;
}
100% {
transform: scaleX(0.3) translateX(100%);
opacity: 0;
}
}
.gt-01__sub {
font-size: 12px;
letter-spacing: 8px;
color: rgba(224,224,255,0.4);
text-transform: uppercase;
}
@media (prefers-reduced-motion: reduce) {
.gt-01__glitch,
.gt-01__glitch::before,
.gt-01__glitch::after,
.gt-01__bar {
animation: none;
}
.gt-01__glitch::before {
left: 0;
}
.gt-01__glitch::after {
left: 0;
}
}Here's a working CSS Glitch Text Effect from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Cyberpunk Glitch Text
Source: https://codefronts.com/motion/css-glitch-text-effect/css-cyberpunk-glitch-text/
Neon pink and cyan RGB-channel split glitch over a deep dark background, with clip-path horizontal slice displacement that fires at asymmetric intervals on an Orbitron-style headline.
## HTML
```html
<div class="gt-01">
<span class="gt-01__label">// system_breach_detected</span>
<div class="gt-01__glitch" data-text="CYBERP∪NK">CYBERP∪NK</div>
<div class="gt-01__bar"></div>
<span class="gt-01__sub">Neural net v2.7.1 — online</span>
</div>
```
## CSS
```css
.gt-01,
.gt-01 *,
.gt-01 *::before,
.gt-01 *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.gt-01 ::selection {
background: #ff0090;
color: #000;
}
.gt-01 {
--neon-pink: #ff0090;
--neon-cyan: #00f5ff;
--bg: #050515;
--text-col: #e0e0ff;
min-height: 100vh;
background: var(--bg);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 32px;
padding: 40px 20px;
font-family: 'Orbitron', 'Rajdhani', 'Share Tech Mono', monospace;
position: relative;
overflow: hidden;
}
/* Scanline overlay */
.gt-01::before {
content: '';
position: absolute;
inset: 0;
background: repeating-linear-gradient(
0deg,
transparent,
transparent 2px,
rgba(0,245,255,0.03) 2px,
rgba(0,245,255,0.03) 4px
);
pointer-events: none;
z-index: 10;
}
.gt-01__label {
font-size: 11px;
letter-spacing: 4px;
color: var(--neon-cyan);
opacity: 0.6;
text-transform: uppercase;
}
.gt-01__glitch {
position: relative;
font-size: clamp(42px, 8vw, 80px);
font-weight: 900;
letter-spacing: 6px;
text-transform: uppercase;
color: var(--text-col);
text-shadow: 0 0 10px rgba(255,0,144,0.8), 0 0 30px rgba(255,0,144,0.4), 0 0 60px rgba(255,0,144,0.2);
animation: gt-01-flicker 4s infinite;
}
.gt-01__glitch::before,
.gt-01__glitch::after {
content: attr(data-text);
position: absolute;
inset: 0;
font: inherit;
letter-spacing: inherit;
}
/* Pink channel — clips top slices */
.gt-01__glitch::before {
color: var(--neon-pink);
text-shadow: none;
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
animation: gt-01-slice-top 2.5s steps(1) infinite;
left: 3px;
}
/* Cyan channel — clips bottom slices */
.gt-01__glitch::after {
color: var(--neon-cyan);
text-shadow: none;
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
animation: gt-01-slice-bot 2.5s steps(1) infinite;
left: -3px;
}
@keyframes gt-01-flicker {
0%,
94%,
96%,
100% {
opacity: 1;
}
95% {
opacity: 0.6;
}
}
@keyframes gt-01-slice-top {
0% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
5% {
transform: translateX(-8px);
clip-path: polygon(0 10%, 100% 10%, 100% 28%, 0 28%);
}
10% {
transform: translateX(6px);
clip-path: polygon(0 5%, 100% 5%, 100% 20%, 0 20%);
}
15% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
40% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
42% {
transform: translateX(10px);
clip-path: polygon(0 15%, 100% 15%, 100% 35%, 0 35%);
}
44% {
transform: translateX(-5px);
clip-path: polygon(0 8%, 100% 8%, 100% 25%, 0 25%);
}
46% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
100% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
}
@keyframes gt-01-slice-bot {
0% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
5% {
transform: translateX(8px);
clip-path: polygon(0 65%, 100% 65%, 100% 90%, 0 90%);
}
10% {
transform: translateX(-6px);
clip-path: polygon(0 55%, 100% 55%, 100% 80%, 0 80%);
}
15% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
40% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
42% {
transform: translateX(-10px);
clip-path: polygon(0 70%, 100% 70%, 100% 95%, 0 95%);
}
44% {
transform: translateX(4px);
clip-path: polygon(0 58%, 100% 58%, 100% 85%, 0 85%);
}
46% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
100% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
}
/* Glitch bar decoration */
.gt-01__bar {
width: 200px;
height: 2px;
background: linear-gradient(90deg, transparent, var(--neon-cyan), var(--neon-pink), transparent);
animation: gt-01-bar 3s linear infinite;
}
@keyframes gt-01-bar {
0% {
transform: scaleX(0.3) translateX(-100%);
opacity: 0;
}
50% {
transform: scaleX(1) translateX(0%);
opacity: 1;
}
100% {
transform: scaleX(0.3) translateX(100%);
opacity: 0;
}
}
.gt-01__sub {
font-size: 12px;
letter-spacing: 8px;
color: rgba(224,224,255,0.4);
text-transform: uppercase;
}
@media (prefers-reduced-motion: reduce) {
.gt-01__glitch,
.gt-01__glitch::before,
.gt-01__glitch::after,
.gt-01__bar {
animation: none;
}
.gt-01__glitch::before {
left: 0;
}
.gt-01__glitch::after {
left: 0;
}
}
```Here's a working CSS Glitch Text Effect from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Cyberpunk Glitch Text
Source: https://codefronts.com/motion/css-glitch-text-effect/css-cyberpunk-glitch-text/
Neon pink and cyan RGB-channel split glitch over a deep dark background, with clip-path horizontal slice displacement that fires at asymmetric intervals on an Orbitron-style headline.
## HTML
```html
<div class="gt-01">
<span class="gt-01__label">// system_breach_detected</span>
<div class="gt-01__glitch" data-text="CYBERP∪NK">CYBERP∪NK</div>
<div class="gt-01__bar"></div>
<span class="gt-01__sub">Neural net v2.7.1 — online</span>
</div>
```
## CSS
```css
.gt-01,
.gt-01 *,
.gt-01 *::before,
.gt-01 *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.gt-01 ::selection {
background: #ff0090;
color: #000;
}
.gt-01 {
--neon-pink: #ff0090;
--neon-cyan: #00f5ff;
--bg: #050515;
--text-col: #e0e0ff;
min-height: 100vh;
background: var(--bg);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 32px;
padding: 40px 20px;
font-family: 'Orbitron', 'Rajdhani', 'Share Tech Mono', monospace;
position: relative;
overflow: hidden;
}
/* Scanline overlay */
.gt-01::before {
content: '';
position: absolute;
inset: 0;
background: repeating-linear-gradient(
0deg,
transparent,
transparent 2px,
rgba(0,245,255,0.03) 2px,
rgba(0,245,255,0.03) 4px
);
pointer-events: none;
z-index: 10;
}
.gt-01__label {
font-size: 11px;
letter-spacing: 4px;
color: var(--neon-cyan);
opacity: 0.6;
text-transform: uppercase;
}
.gt-01__glitch {
position: relative;
font-size: clamp(42px, 8vw, 80px);
font-weight: 900;
letter-spacing: 6px;
text-transform: uppercase;
color: var(--text-col);
text-shadow: 0 0 10px rgba(255,0,144,0.8), 0 0 30px rgba(255,0,144,0.4), 0 0 60px rgba(255,0,144,0.2);
animation: gt-01-flicker 4s infinite;
}
.gt-01__glitch::before,
.gt-01__glitch::after {
content: attr(data-text);
position: absolute;
inset: 0;
font: inherit;
letter-spacing: inherit;
}
/* Pink channel — clips top slices */
.gt-01__glitch::before {
color: var(--neon-pink);
text-shadow: none;
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
animation: gt-01-slice-top 2.5s steps(1) infinite;
left: 3px;
}
/* Cyan channel — clips bottom slices */
.gt-01__glitch::after {
color: var(--neon-cyan);
text-shadow: none;
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
animation: gt-01-slice-bot 2.5s steps(1) infinite;
left: -3px;
}
@keyframes gt-01-flicker {
0%,
94%,
96%,
100% {
opacity: 1;
}
95% {
opacity: 0.6;
}
}
@keyframes gt-01-slice-top {
0% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
5% {
transform: translateX(-8px);
clip-path: polygon(0 10%, 100% 10%, 100% 28%, 0 28%);
}
10% {
transform: translateX(6px);
clip-path: polygon(0 5%, 100% 5%, 100% 20%, 0 20%);
}
15% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
40% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
42% {
transform: translateX(10px);
clip-path: polygon(0 15%, 100% 15%, 100% 35%, 0 35%);
}
44% {
transform: translateX(-5px);
clip-path: polygon(0 8%, 100% 8%, 100% 25%, 0 25%);
}
46% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
100% {
transform: translateX(0);
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
}
@keyframes gt-01-slice-bot {
0% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
5% {
transform: translateX(8px);
clip-path: polygon(0 65%, 100% 65%, 100% 90%, 0 90%);
}
10% {
transform: translateX(-6px);
clip-path: polygon(0 55%, 100% 55%, 100% 80%, 0 80%);
}
15% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
40% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
42% {
transform: translateX(-10px);
clip-path: polygon(0 70%, 100% 70%, 100% 95%, 0 95%);
}
44% {
transform: translateX(4px);
clip-path: polygon(0 58%, 100% 58%, 100% 85%, 0 85%);
}
46% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
100% {
transform: translateX(0);
clip-path: polygon(0 60%, 100% 60%, 100% 100%, 0 100%);
}
}
/* Glitch bar decoration */
.gt-01__bar {
width: 200px;
height: 2px;
background: linear-gradient(90deg, transparent, var(--neon-cyan), var(--neon-pink), transparent);
animation: gt-01-bar 3s linear infinite;
}
@keyframes gt-01-bar {
0% {
transform: scaleX(0.3) translateX(-100%);
opacity: 0;
}
50% {
transform: scaleX(1) translateX(0%);
opacity: 1;
}
100% {
transform: scaleX(0.3) translateX(100%);
opacity: 0;
}
}
.gt-01__sub {
font-size: 12px;
letter-spacing: 8px;
color: rgba(224,224,255,0.4);
text-transform: uppercase;
}
@media (prefers-reduced-motion: reduce) {
.gt-01__glitch,
.gt-01__glitch::before,
.gt-01__glitch::after,
.gt-01__bar {
animation: none;
}
.gt-01__glitch::before {
left: 0;
}
.gt-01__glitch::after {
left: 0;
}
}
```How this works
Two ::before and ::after pseudo-elements duplicate the headline text via data-text and are permanently coloured pink and cyan respectively. Each pseudo-layer is masked to a horizontal band using clip-path: polygon(), so only a slice of the coloured ghost is ever visible. A steps(1) keyframe snaps the translateX value and the clip-path polygon coordinates to new positions at precise points in the loop, producing the hard-edged displacement characteristic of digital corruption.
A separate @keyframes gt-01-flicker dips the whole element opacity to 0.6 for a single frame every few seconds, mimicking a failing power supply. A scrolling scanline overlay is built with repeating-linear-gradient on the wrapper ::before, and a sweep-bar child element animates scaleX and translateX for a horizontal radar trace -- all compositor-only properties, no layout triggers.
Make it yours
- Change the neon palette by editing
--neon-pinkand--neon-cyanon.gt-01; the scanlines and bar update automatically. - Tune glitch frequency by shifting the keyframe percentage stops -- move the
40%trigger closer to0%for a more frantic loop. - Adjust slice height by changing the middle polygon coordinates, e.g.
polygon(0 0, 100% 0, 100% 20%, 0 20%)for a thinner cut. - Swap
steps(1)forlineartiming on the channel animations for a slow, dreamy RGB separation instead of hard snaps. - Replace the headline font with any variable-weight sans-serif; increase
letter-spacingto exaggerate the channel offset gap.
Gotchas — read before shipping
clip-path: polygon()is fully hardware-accelerated but triggers compositing layer promotion -- on pages with many animated elements, audit with DevTools Layers panel to confirm no excessive layer count.- The
data-textattribute must exactly match the visible text including any Unicode characters; a mismatch creates a ghosting artifact where the pseudo-layer text differs from the real text. - Safari may render the
text-shadowglow bloom slightly dimmer than Chrome; increase the blur radius by 20% and add a fourth, very wide glow stop to compensate.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 89+ | 14+ | 90+ | 89+ |
clip-path polygon is universally supported; no prefixes required as of 2024.