30 CSS Text Animations15 / 30
CSS Text Hover Glitch Effect Keyframes
Broadcast-corruption typography for gaming and cyber brands: a data-text double-layer glitch with clip-path slice storms and RGB fringes, and a scanline tear where a sweep bar drags the word into stepped chromatic shivers.
Published Updated
The code
<div class="cat-15-group">
<link href="https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,500..900;1,500..900&display=swap" rel="stylesheet">
<section class="cat-15a" aria-label="Glitch slice text hover">
<div class="cat-15a__stage">
<h1 class="cat-15a__word" data-text="OVERDRIVE" tabindex="0">OVERDRIVE</h1>
<p class="cat-15a__sub" aria-hidden="true">hover / focus to corrupt the signal</p>
</div>
</section>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400..800&display=swap" rel="stylesheet">
<section class="cat-15b" aria-label="Scanline glitch text hover">
<div class="cat-15b__stage">
<h1 class="cat-15b__word" tabindex="0">LEVEL UP<span class="cat-15b__scan" aria-hidden="true"></span></h1>
<p class="cat-15b__sub" aria-hidden="true">a sweep bar drags stepped chromatic shivers</p>
</div>
</section>
</div><div class="cat-15-group">
<link href="https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,500..900;1,500..900&display=swap" rel="stylesheet">
<section class="cat-15a" aria-label="Glitch slice text hover">
<div class="cat-15a__stage">
<h1 class="cat-15a__word" data-text="OVERDRIVE" tabindex="0">OVERDRIVE</h1>
<p class="cat-15a__sub" aria-hidden="true">hover / focus to corrupt the signal</p>
</div>
</section>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400..800&display=swap" rel="stylesheet">
<section class="cat-15b" aria-label="Scanline glitch text hover">
<div class="cat-15b__stage">
<h1 class="cat-15b__word" tabindex="0">LEVEL UP<span class="cat-15b__scan" aria-hidden="true"></span></h1>
<p class="cat-15b__sub" aria-hidden="true">a sweep bar drags stepped chromatic shivers</p>
</div>
</section>
</div>.cat-15-group {
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
}
.cat-15-group > section {
flex: 1 1 480px;
min-width: min(100%,360px);
}
.cat-15a,
.cat-15a *,
.cat-15a *::before,
.cat-15a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-15a {
--cyan: #22e3ff;
--mag: #ff2bd6;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: #07060f;
background-image: repeating-linear-gradient(0deg,rgba(255,255,255,.025) 0 1px,transparent 1px 3px);
}
.cat-15a__stage {
text-align: center;
}
.cat-15a__word {
position: relative;
display: inline-block;
font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
font-size: clamp(40px,8.4vw,104px);
font-weight: 900;
letter-spacing: .01em;
color: #f2f6ff;
cursor: crosshair;
}
.cat-15a__word::before,
.cat-15a__word::after {
content: attr(data-text);
position: absolute;
inset: 0;
opacity: 0;
pointer-events: none;
}
.cat-15a__word::before {
text-shadow: -2.5px 0 var(--cyan);
clip-path: inset(0 0 55% 0);
}
.cat-15a__word::after {
text-shadow: 2.5px 0 var(--mag);
clip-path: inset(55% 0 0 0);
}
.cat-15a__word:hover::before,
.cat-15a__word:focus-visible::before {
opacity: .95;
animation: cat-15a-s1 .55s steps(5) infinite;
}
.cat-15a__word:hover::after,
.cat-15a__word:focus-visible::after {
opacity: .95;
animation: cat-15a-s2 .45s steps(4) infinite;
}
.cat-15a__word:focus-visible {
outline: 2px solid var(--cyan);
outline-offset: 8px;
}
.cat-15a__sub {
margin-top: 22px;
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
letter-spacing: .2em;
color: rgba(170,190,230,.4);
}
@keyframes cat-15a-s1 {
0% {
clip-path: inset(0 0 62% 0);
transform: translate(-3px,0);
}
33% {
clip-path: inset(38% 0 28% 0);
transform: translate(2px,-2px);
}
66% {
clip-path: inset(72% 0 4% 0);
transform: translate(-2px,1px);
}
100% {
clip-path: inset(10% 0 74% 0);
transform: translate(3px,0);
}
}
@keyframes cat-15a-s2 {
0% {
clip-path: inset(64% 0 6% 0);
transform: translate(3px,0);
}
33% {
clip-path: inset(6% 0 70% 0);
transform: translate(-2px,2px);
}
66% {
clip-path: inset(42% 0 34% 0);
transform: translate(2px,-1px);
}
100% {
clip-path: inset(78% 0 2% 0);
transform: translate(-3px,0);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-15a__word:hover::before,
.cat-15a__word:hover::after,
.cat-15a__word:focus-visible::before,
.cat-15a__word:focus-visible::after {
animation: none;
opacity: .5;
clip-path: none;
transform: none;
}
}
.cat-15b,
.cat-15b *,
.cat-15b *::before,
.cat-15b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-15b {
--lime: oklch(0.9 0.23 135);
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: #0a0f0a;
}
.cat-15b__stage {
text-align: center;
}
.cat-15b__word {
position: relative;
display: inline-block;
overflow: hidden;
font-family: 'JetBrains Mono',ui-monospace,Menlo,monospace;
font-size: clamp(38px,7.6vw,92px);
font-weight: 800;
letter-spacing: .04em;
color: var(--lime);
padding: .1em .2em;
cursor: crosshair;
}
.cat-15b__scan {
position: absolute;
left: 0;
right: 0;
top: -30%;
height: 22%;
background: linear-gradient(180deg,transparent,rgba(190,255,160,.28),transparent);
opacity: 0;
pointer-events: none;
}
.cat-15b__word:hover,
.cat-15b__word:focus-visible {
animation: cat-15b-shiver .4s steps(2) infinite;
}
.cat-15b__word:hover .cat-15b__scan,
.cat-15b__word:focus-visible .cat-15b__scan {
opacity: 1;
animation: cat-15b-sweep .7s linear infinite;
}
.cat-15b__word:focus-visible {
outline: 2px solid var(--lime);
outline-offset: 6px;
}
.cat-15b__sub {
margin-top: 20px;
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
letter-spacing: .16em;
color: rgba(170,220,170,.4);
}
@keyframes cat-15b-sweep {
to {
top: 110%;
}
}
@keyframes cat-15b-shiver {
0% {
transform: translateX(0);
text-shadow: 2px 0 rgba(255,60,120,.6),-2px 0 rgba(60,200,255,.6);
}
50% {
transform: translateX(2px);
text-shadow: -2px 0 rgba(255,60,120,.6),2px 0 rgba(60,200,255,.6);
}
100% {
transform: translateX(-2px);
text-shadow: 2px 0 rgba(255,60,120,.6),-2px 0 rgba(60,200,255,.6);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-15b__word:hover,
.cat-15b__word:focus-visible {
animation: none;
text-shadow: 2px 0 rgba(255,60,120,.4),-2px 0 rgba(60,200,255,.4);
}
.cat-15b__word:hover .cat-15b__scan,
.cat-15b__word:focus-visible .cat-15b__scan {
animation: none;
opacity: 0;
}
}.cat-15-group {
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
}
.cat-15-group > section {
flex: 1 1 480px;
min-width: min(100%,360px);
}
.cat-15a,
.cat-15a *,
.cat-15a *::before,
.cat-15a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-15a {
--cyan: #22e3ff;
--mag: #ff2bd6;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: #07060f;
background-image: repeating-linear-gradient(0deg,rgba(255,255,255,.025) 0 1px,transparent 1px 3px);
}
.cat-15a__stage {
text-align: center;
}
.cat-15a__word {
position: relative;
display: inline-block;
font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
font-size: clamp(40px,8.4vw,104px);
font-weight: 900;
letter-spacing: .01em;
color: #f2f6ff;
cursor: crosshair;
}
.cat-15a__word::before,
.cat-15a__word::after {
content: attr(data-text);
position: absolute;
inset: 0;
opacity: 0;
pointer-events: none;
}
.cat-15a__word::before {
text-shadow: -2.5px 0 var(--cyan);
clip-path: inset(0 0 55% 0);
}
.cat-15a__word::after {
text-shadow: 2.5px 0 var(--mag);
clip-path: inset(55% 0 0 0);
}
.cat-15a__word:hover::before,
.cat-15a__word:focus-visible::before {
opacity: .95;
animation: cat-15a-s1 .55s steps(5) infinite;
}
.cat-15a__word:hover::after,
.cat-15a__word:focus-visible::after {
opacity: .95;
animation: cat-15a-s2 .45s steps(4) infinite;
}
.cat-15a__word:focus-visible {
outline: 2px solid var(--cyan);
outline-offset: 8px;
}
.cat-15a__sub {
margin-top: 22px;
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
letter-spacing: .2em;
color: rgba(170,190,230,.4);
}
@keyframes cat-15a-s1 {
0% {
clip-path: inset(0 0 62% 0);
transform: translate(-3px,0);
}
33% {
clip-path: inset(38% 0 28% 0);
transform: translate(2px,-2px);
}
66% {
clip-path: inset(72% 0 4% 0);
transform: translate(-2px,1px);
}
100% {
clip-path: inset(10% 0 74% 0);
transform: translate(3px,0);
}
}
@keyframes cat-15a-s2 {
0% {
clip-path: inset(64% 0 6% 0);
transform: translate(3px,0);
}
33% {
clip-path: inset(6% 0 70% 0);
transform: translate(-2px,2px);
}
66% {
clip-path: inset(42% 0 34% 0);
transform: translate(2px,-1px);
}
100% {
clip-path: inset(78% 0 2% 0);
transform: translate(-3px,0);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-15a__word:hover::before,
.cat-15a__word:hover::after,
.cat-15a__word:focus-visible::before,
.cat-15a__word:focus-visible::after {
animation: none;
opacity: .5;
clip-path: none;
transform: none;
}
}
.cat-15b,
.cat-15b *,
.cat-15b *::before,
.cat-15b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-15b {
--lime: oklch(0.9 0.23 135);
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: #0a0f0a;
}
.cat-15b__stage {
text-align: center;
}
.cat-15b__word {
position: relative;
display: inline-block;
overflow: hidden;
font-family: 'JetBrains Mono',ui-monospace,Menlo,monospace;
font-size: clamp(38px,7.6vw,92px);
font-weight: 800;
letter-spacing: .04em;
color: var(--lime);
padding: .1em .2em;
cursor: crosshair;
}
.cat-15b__scan {
position: absolute;
left: 0;
right: 0;
top: -30%;
height: 22%;
background: linear-gradient(180deg,transparent,rgba(190,255,160,.28),transparent);
opacity: 0;
pointer-events: none;
}
.cat-15b__word:hover,
.cat-15b__word:focus-visible {
animation: cat-15b-shiver .4s steps(2) infinite;
}
.cat-15b__word:hover .cat-15b__scan,
.cat-15b__word:focus-visible .cat-15b__scan {
opacity: 1;
animation: cat-15b-sweep .7s linear infinite;
}
.cat-15b__word:focus-visible {
outline: 2px solid var(--lime);
outline-offset: 6px;
}
.cat-15b__sub {
margin-top: 20px;
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
letter-spacing: .16em;
color: rgba(170,220,170,.4);
}
@keyframes cat-15b-sweep {
to {
top: 110%;
}
}
@keyframes cat-15b-shiver {
0% {
transform: translateX(0);
text-shadow: 2px 0 rgba(255,60,120,.6),-2px 0 rgba(60,200,255,.6);
}
50% {
transform: translateX(2px);
text-shadow: -2px 0 rgba(255,60,120,.6),2px 0 rgba(60,200,255,.6);
}
100% {
transform: translateX(-2px);
text-shadow: 2px 0 rgba(255,60,120,.6),-2px 0 rgba(60,200,255,.6);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-15b__word:hover,
.cat-15b__word:focus-visible {
animation: none;
text-shadow: 2px 0 rgba(255,60,120,.4),-2px 0 rgba(60,200,255,.4);
}
.cat-15b__word:hover .cat-15b__scan,
.cat-15b__word:focus-visible .cat-15b__scan {
animation: none;
opacity: 0;
}
}/* No JavaScript — two attr(data-text) pseudo clones carry cyan/magenta shadows; steps() keyframes snap different clip-path:inset() bands per frame while the base text holds still. */ /* No JavaScript — a gradient scan bar sweeps top-to-bottom while the word micro-translates on steps(2) with alternating RGB text-shadows. */
/* No JavaScript — two attr(data-text) pseudo clones carry cyan/magenta shadows; steps() keyframes snap different clip-path:inset() bands per frame while the base text holds still. */
/* No JavaScript — a gradient scan bar sweeps top-to-bottom while the word micro-translates on steps(2) with alternating RGB text-shadows. */Here's a working CSS Text Animation 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 Text Hover Glitch Effect Keyframes
Source: https://codefronts.com/motion/css-text-animations/css-glitch-text-effect-animation/
Broadcast-corruption typography for gaming and cyber brands: a data-text double-layer glitch with clip-path slice storms and RGB fringes, and a scanline tear where a sweep bar drags the word into stepped chromatic shivers.
## HTML
```html
<div class="cat-15-group">
<link href="https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,500..900;1,500..900&display=swap" rel="stylesheet">
<section class="cat-15a" aria-label="Glitch slice text hover">
<div class="cat-15a__stage">
<h1 class="cat-15a__word" data-text="OVERDRIVE" tabindex="0">OVERDRIVE</h1>
<p class="cat-15a__sub" aria-hidden="true">hover / focus to corrupt the signal</p>
</div>
</section>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400..800&display=swap" rel="stylesheet">
<section class="cat-15b" aria-label="Scanline glitch text hover">
<div class="cat-15b__stage">
<h1 class="cat-15b__word" tabindex="0">LEVEL UP<span class="cat-15b__scan" aria-hidden="true"></span></h1>
<p class="cat-15b__sub" aria-hidden="true">a sweep bar drags stepped chromatic shivers</p>
</div>
</section>
</div>
```
## CSS
```css
.cat-15-group {
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
}
.cat-15-group > section {
flex: 1 1 480px;
min-width: min(100%,360px);
}
.cat-15a,
.cat-15a *,
.cat-15a *::before,
.cat-15a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-15a {
--cyan: #22e3ff;
--mag: #ff2bd6;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: #07060f;
background-image: repeating-linear-gradient(0deg,rgba(255,255,255,.025) 0 1px,transparent 1px 3px);
}
.cat-15a__stage {
text-align: center;
}
.cat-15a__word {
position: relative;
display: inline-block;
font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
font-size: clamp(40px,8.4vw,104px);
font-weight: 900;
letter-spacing: .01em;
color: #f2f6ff;
cursor: crosshair;
}
.cat-15a__word::before,
.cat-15a__word::after {
content: attr(data-text);
position: absolute;
inset: 0;
opacity: 0;
pointer-events: none;
}
.cat-15a__word::before {
text-shadow: -2.5px 0 var(--cyan);
clip-path: inset(0 0 55% 0);
}
.cat-15a__word::after {
text-shadow: 2.5px 0 var(--mag);
clip-path: inset(55% 0 0 0);
}
.cat-15a__word:hover::before,
.cat-15a__word:focus-visible::before {
opacity: .95;
animation: cat-15a-s1 .55s steps(5) infinite;
}
.cat-15a__word:hover::after,
.cat-15a__word:focus-visible::after {
opacity: .95;
animation: cat-15a-s2 .45s steps(4) infinite;
}
.cat-15a__word:focus-visible {
outline: 2px solid var(--cyan);
outline-offset: 8px;
}
.cat-15a__sub {
margin-top: 22px;
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
letter-spacing: .2em;
color: rgba(170,190,230,.4);
}
@keyframes cat-15a-s1 {
0% {
clip-path: inset(0 0 62% 0);
transform: translate(-3px,0);
}
33% {
clip-path: inset(38% 0 28% 0);
transform: translate(2px,-2px);
}
66% {
clip-path: inset(72% 0 4% 0);
transform: translate(-2px,1px);
}
100% {
clip-path: inset(10% 0 74% 0);
transform: translate(3px,0);
}
}
@keyframes cat-15a-s2 {
0% {
clip-path: inset(64% 0 6% 0);
transform: translate(3px,0);
}
33% {
clip-path: inset(6% 0 70% 0);
transform: translate(-2px,2px);
}
66% {
clip-path: inset(42% 0 34% 0);
transform: translate(2px,-1px);
}
100% {
clip-path: inset(78% 0 2% 0);
transform: translate(-3px,0);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-15a__word:hover::before,
.cat-15a__word:hover::after,
.cat-15a__word:focus-visible::before,
.cat-15a__word:focus-visible::after {
animation: none;
opacity: .5;
clip-path: none;
transform: none;
}
}
.cat-15b,
.cat-15b *,
.cat-15b *::before,
.cat-15b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-15b {
--lime: oklch(0.9 0.23 135);
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: #0a0f0a;
}
.cat-15b__stage {
text-align: center;
}
.cat-15b__word {
position: relative;
display: inline-block;
overflow: hidden;
font-family: 'JetBrains Mono',ui-monospace,Menlo,monospace;
font-size: clamp(38px,7.6vw,92px);
font-weight: 800;
letter-spacing: .04em;
color: var(--lime);
padding: .1em .2em;
cursor: crosshair;
}
.cat-15b__scan {
position: absolute;
left: 0;
right: 0;
top: -30%;
height: 22%;
background: linear-gradient(180deg,transparent,rgba(190,255,160,.28),transparent);
opacity: 0;
pointer-events: none;
}
.cat-15b__word:hover,
.cat-15b__word:focus-visible {
animation: cat-15b-shiver .4s steps(2) infinite;
}
.cat-15b__word:hover .cat-15b__scan,
.cat-15b__word:focus-visible .cat-15b__scan {
opacity: 1;
animation: cat-15b-sweep .7s linear infinite;
}
.cat-15b__word:focus-visible {
outline: 2px solid var(--lime);
outline-offset: 6px;
}
.cat-15b__sub {
margin-top: 20px;
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
letter-spacing: .16em;
color: rgba(170,220,170,.4);
}
@keyframes cat-15b-sweep {
to {
top: 110%;
}
}
@keyframes cat-15b-shiver {
0% {
transform: translateX(0);
text-shadow: 2px 0 rgba(255,60,120,.6),-2px 0 rgba(60,200,255,.6);
}
50% {
transform: translateX(2px);
text-shadow: -2px 0 rgba(255,60,120,.6),2px 0 rgba(60,200,255,.6);
}
100% {
transform: translateX(-2px);
text-shadow: 2px 0 rgba(255,60,120,.6),-2px 0 rgba(60,200,255,.6);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-15b__word:hover,
.cat-15b__word:focus-visible {
animation: none;
text-shadow: 2px 0 rgba(255,60,120,.4),-2px 0 rgba(60,200,255,.4);
}
.cat-15b__word:hover .cat-15b__scan,
.cat-15b__word:focus-visible .cat-15b__scan {
animation: none;
opacity: 0;
}
}
```
## JavaScript
```js
/* No JavaScript — two attr(data-text) pseudo clones carry cyan/magenta shadows; steps() keyframes snap different clip-path:inset() bands per frame while the base text holds still. */
/* No JavaScript — a gradient scan bar sweeps top-to-bottom while the word micro-translates on steps(2) with alternating RGB text-shadows. */
```Here's a working CSS Text Animation 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 Text Hover Glitch Effect Keyframes
Source: https://codefronts.com/motion/css-text-animations/css-glitch-text-effect-animation/
Broadcast-corruption typography for gaming and cyber brands: a data-text double-layer glitch with clip-path slice storms and RGB fringes, and a scanline tear where a sweep bar drags the word into stepped chromatic shivers.
## HTML
```html
<div class="cat-15-group">
<link href="https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,500..900;1,500..900&display=swap" rel="stylesheet">
<section class="cat-15a" aria-label="Glitch slice text hover">
<div class="cat-15a__stage">
<h1 class="cat-15a__word" data-text="OVERDRIVE" tabindex="0">OVERDRIVE</h1>
<p class="cat-15a__sub" aria-hidden="true">hover / focus to corrupt the signal</p>
</div>
</section>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400..800&display=swap" rel="stylesheet">
<section class="cat-15b" aria-label="Scanline glitch text hover">
<div class="cat-15b__stage">
<h1 class="cat-15b__word" tabindex="0">LEVEL UP<span class="cat-15b__scan" aria-hidden="true"></span></h1>
<p class="cat-15b__sub" aria-hidden="true">a sweep bar drags stepped chromatic shivers</p>
</div>
</section>
</div>
```
## CSS
```css
.cat-15-group {
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
}
.cat-15-group > section {
flex: 1 1 480px;
min-width: min(100%,360px);
}
.cat-15a,
.cat-15a *,
.cat-15a *::before,
.cat-15a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-15a {
--cyan: #22e3ff;
--mag: #ff2bd6;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: #07060f;
background-image: repeating-linear-gradient(0deg,rgba(255,255,255,.025) 0 1px,transparent 1px 3px);
}
.cat-15a__stage {
text-align: center;
}
.cat-15a__word {
position: relative;
display: inline-block;
font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
font-size: clamp(40px,8.4vw,104px);
font-weight: 900;
letter-spacing: .01em;
color: #f2f6ff;
cursor: crosshair;
}
.cat-15a__word::before,
.cat-15a__word::after {
content: attr(data-text);
position: absolute;
inset: 0;
opacity: 0;
pointer-events: none;
}
.cat-15a__word::before {
text-shadow: -2.5px 0 var(--cyan);
clip-path: inset(0 0 55% 0);
}
.cat-15a__word::after {
text-shadow: 2.5px 0 var(--mag);
clip-path: inset(55% 0 0 0);
}
.cat-15a__word:hover::before,
.cat-15a__word:focus-visible::before {
opacity: .95;
animation: cat-15a-s1 .55s steps(5) infinite;
}
.cat-15a__word:hover::after,
.cat-15a__word:focus-visible::after {
opacity: .95;
animation: cat-15a-s2 .45s steps(4) infinite;
}
.cat-15a__word:focus-visible {
outline: 2px solid var(--cyan);
outline-offset: 8px;
}
.cat-15a__sub {
margin-top: 22px;
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
letter-spacing: .2em;
color: rgba(170,190,230,.4);
}
@keyframes cat-15a-s1 {
0% {
clip-path: inset(0 0 62% 0);
transform: translate(-3px,0);
}
33% {
clip-path: inset(38% 0 28% 0);
transform: translate(2px,-2px);
}
66% {
clip-path: inset(72% 0 4% 0);
transform: translate(-2px,1px);
}
100% {
clip-path: inset(10% 0 74% 0);
transform: translate(3px,0);
}
}
@keyframes cat-15a-s2 {
0% {
clip-path: inset(64% 0 6% 0);
transform: translate(3px,0);
}
33% {
clip-path: inset(6% 0 70% 0);
transform: translate(-2px,2px);
}
66% {
clip-path: inset(42% 0 34% 0);
transform: translate(2px,-1px);
}
100% {
clip-path: inset(78% 0 2% 0);
transform: translate(-3px,0);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-15a__word:hover::before,
.cat-15a__word:hover::after,
.cat-15a__word:focus-visible::before,
.cat-15a__word:focus-visible::after {
animation: none;
opacity: .5;
clip-path: none;
transform: none;
}
}
.cat-15b,
.cat-15b *,
.cat-15b *::before,
.cat-15b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cat-15b {
--lime: oklch(0.9 0.23 135);
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: #0a0f0a;
}
.cat-15b__stage {
text-align: center;
}
.cat-15b__word {
position: relative;
display: inline-block;
overflow: hidden;
font-family: 'JetBrains Mono',ui-monospace,Menlo,monospace;
font-size: clamp(38px,7.6vw,92px);
font-weight: 800;
letter-spacing: .04em;
color: var(--lime);
padding: .1em .2em;
cursor: crosshair;
}
.cat-15b__scan {
position: absolute;
left: 0;
right: 0;
top: -30%;
height: 22%;
background: linear-gradient(180deg,transparent,rgba(190,255,160,.28),transparent);
opacity: 0;
pointer-events: none;
}
.cat-15b__word:hover,
.cat-15b__word:focus-visible {
animation: cat-15b-shiver .4s steps(2) infinite;
}
.cat-15b__word:hover .cat-15b__scan,
.cat-15b__word:focus-visible .cat-15b__scan {
opacity: 1;
animation: cat-15b-sweep .7s linear infinite;
}
.cat-15b__word:focus-visible {
outline: 2px solid var(--lime);
outline-offset: 6px;
}
.cat-15b__sub {
margin-top: 20px;
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
letter-spacing: .16em;
color: rgba(170,220,170,.4);
}
@keyframes cat-15b-sweep {
to {
top: 110%;
}
}
@keyframes cat-15b-shiver {
0% {
transform: translateX(0);
text-shadow: 2px 0 rgba(255,60,120,.6),-2px 0 rgba(60,200,255,.6);
}
50% {
transform: translateX(2px);
text-shadow: -2px 0 rgba(255,60,120,.6),2px 0 rgba(60,200,255,.6);
}
100% {
transform: translateX(-2px);
text-shadow: 2px 0 rgba(255,60,120,.6),-2px 0 rgba(60,200,255,.6);
}
}
@media (prefers-reduced-motion: reduce) {
.cat-15b__word:hover,
.cat-15b__word:focus-visible {
animation: none;
text-shadow: 2px 0 rgba(255,60,120,.4),-2px 0 rgba(60,200,255,.4);
}
.cat-15b__word:hover .cat-15b__scan,
.cat-15b__word:focus-visible .cat-15b__scan {
animation: none;
opacity: 0;
}
}
```
## JavaScript
```js
/* No JavaScript — two attr(data-text) pseudo clones carry cyan/magenta shadows; steps() keyframes snap different clip-path:inset() bands per frame while the base text holds still. */
/* No JavaScript — a gradient scan bar sweeps top-to-bottom while the word micro-translates on steps(2) with alternating RGB text-shadows. */
```How this works
The word is duplicated into ::before/::after via content:attr(data-text). On hover each clone gets an offset colored shadow (cyan one way, magenta the other) and a clip-path:inset() keyframe running on steps() so different horizontal bands of each clone snap visible per frame — the readable base layer never moves:
.glitch::before{content:attr(data-text);
text-shadow:-2px 0 #22e3ff;clip-path:inset(0 0 55% 0)}
.glitch:hover::before{animation:slice .5s steps(5) infinite}The scanline variant runs a bright horizontal bar (a gradient pseudo) top-to-bottom while the whole word micro-translates with steps(2) and flashes split text-shadows — cheaper, one clone fewer, and it reads perfectly at small sizes.
Make it yours
- Aberration distance: ±2px is subtle CRT, ±6px is broken-transmission.
- Add a third clone with skewX for tape-warp corruption.
- Constrain the loop: run 2–3 iterations then settle, instead of infinite.
- Recolor the fringes to your brand pair — glitch reads through any two hues.
Gotchas — read before shipping
- Keep the base layer un-animated and fully opaque — legibility survives the storm.
- Clones are decorative: aria-hidden isn't needed since pseudos are skipped, but data-text must mirror the real text exactly.
- Under prefers-reduced-motion kill the animations and show a static duotone shadow instead.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 15.4+ | 113+ | 111+ |
Floor set by oklch() as this demo is written. The core technique itself goes back further — Chrome 55+.
clip-path on text layers is supported everywhere evergreen. Fallback (no clip-path) is a plain colored-shadow hover — still on-brand.