LiquidFree

Generative Glitch

A white word doubled by two copies — cyan on its top band, magenta on its bottom band — that jitter by 2 to 3 px on 2 s and 3 s cycles: a chromatic glitch in pure CSS, 2 KB, no script and no randomness, read only once by screen readers and frozen at a slight offset when the user reduces motion.

CSSGlitchArt

Updated

GLITCH
Hover or click the scene to interact

This effect is free — the Liquid category contains 31 effects total, including 6 free. Effect.Labs has 840 vanilla effects. Explore the category →

Usage examples

Media literacy · Year 8Module 3 of 6
FAKE?

Spot a photo or a video that has been altered

Start · 4 steps, 15 min

① Fake or not? — a media literacy module for middle schoolers

WhenAt the start of module 3, the title screen shows a crackling "FAKE?", with the subtitle "Spot a photo or a video that has been altered" and two photos to compare.
WhyThe cyan/magenta doubling suggests an altered picture while keeping the word readable.
SettingsWord enlarged to 56 px on a midnight-blue background, container without background; two thumbnails A and B and a "Start" button below; the scene's small script copies the displayed text into data-text to follow the page's language.

Exhibition

REWIND

40 years of videotapes

4 – 29 November · free entry · Harbour media library, 1st floor

② Entrance panel of a videotape exhibition — a media library

WhenAt the exhibition entrance, the screen shows "REWIND — 40 years of videotapes"; the title shakes like a worn tape, between the "◀◀ REW" indicator and the VCR counter.
WhyThe sliding cyan and magenta bands recall the color shift of a damaged tape.
SettingsWord at 64 px, weight 900, spaced letters; almost black violet background striped with scan lines (a gradient repeated every 4 px); on-screen labels in a monospace font in the corners.

Bits of History · episode 12

Y2K

The millennium bug: how the world fixed its dates in time

12:04 / 38:00

③ The "Y2K" episode — the page of a computing history podcast

WhenOn episode 12's page, the title "Y2K" crackles above the summary and the audio player (38 min).
WhyIn pure CSS, the effect dresses an episode title with no script or image, and the crackle says "computer failure" without an illustration.
SettingsTitle in a 58 px monospace font, left-aligned, on a very dark terminal-green background; audio player as a rounded bar under the summary.

How it works

The word is a white, bold (800), 2.5rem <span class="ai-glitch-text">, centered in .ai-glitch-container (background #111). It carries the same text in a data-text attribute, which its two pseudo-elements copy (content: attr(data-text)) in absolute position, exactly on top. ::before is cyan (#0ff) and clipped by clip-path to its top 35%; ::after is magenta (#f0f) and clipped to its bottom 35%. The middle band stays white: the word is always readable.

Each copy has its own jitter animation. aiGlitch1 moves the cyan copy through five fixed positions (−3/+2 px, +3/−1 px, −2/−2 px, +2/+1 px, back to 0) in 2 s; aiGlitch2 moves the magenta copy through three positions (+2/−2 px, −3/+1 px, +1/+2 px) in 3 s. Both run alternate-reverse (forth then back), so over 4 s and 6 s: their movements only line up again every 12 s, which avoids a visible repeat. Nothing is random: the bands and positions are written in the CSS, and the catalog name "Generative" covers no computation and no artificial intelligence. Since only transform is animated, the browser moves the copies without redrawing the text.

The copies' content is written content: attr(data-text) / "": the part after the slash is the alternative text read by screen readers, empty here, so both copies are silent. Measured in Chromium 151, Firefox 153 and WebKit 26: the accessibility tree holds the word only once. The previous line, content: attr(data-text) alone, is the fallback for browsers that do not know this syntax: they show the copies, and may then read the word three times. The text and data-text must stay identical: a copy saying something other than the word would show in the colored bands.

Accessibility

  • Reduced motion: under prefers-reduced-motion: reduce, both copies stop at a slight fixed offset (cyan at −2/+1 px, magenta at +2/−1 px): the picture keeps its colored doubling, with no jitter at all. Measured in all three engines: 0% of pixels changing in 500 ms (against 1% in normal mode, the jitter only touching the letter edges).
  • Screen readers: the word is read once, the copies having an empty alternative text (/ ""). The word stays real text, selectable and translatable.
  • Readability and flashing: the central band stays white and offsets never exceed 3 px: the word reads at every moment. The jitter is continuous but has no flash or brightness alternation, far from the WCAG flash thresholds; on a heading that stays on screen for a long time, consider stopping it after a few seconds (animation-iteration-count).

Browser compatibility

Pure CSS (clip-path: polygon(), pseudo-elements with attr(), a transform animation), 2 KB, no dependency. Measured in Chromium 151, Firefox 153 and WebKit 26: same jitter, same offset stop under reduced motion, word read once. Alternative text on pseudo-elements (/ "") exists since Chrome 77, Firefox 128 and Safari 17.4; before that, the fallback line shows the same copies.

Chrome 77+✓ Full
Firefox 128+✓ Full (before: copies visible, read in addition to the word)
Safari 17.4+✓ Full (before: copies visible, read in addition to the word)
Edge 79+✓ Full
Mobile iOS 17.4+✓ Full
Android Chrome 77+✓ Full

Without clip-path (very old browsers), the copies cover the whole word: the doubling stays visible, stronger. Without CSS animations, the copies sit on the word with no offset: you see a three-color word (cyan, white, magenta), still.

The code

Copy the three blocks into your page. No dependencies.

HTML
<div class="fx-0416-root">
  <div class="ai-glitch-container">
    <span class="ai-glitch-text" data-text="GLITCH">GLITCH</span>
  </div>
</div>
CSS
.fx-0416-root,
.fx-0416-root *,
.fx-0416-root *::before,
.fx-0416-root *::after {
  box-sizing: border-box
}

.fx-0416-root {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 250px;
  overflow: hidden;
  position: relative;
  background: rgb(26, 26, 36);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.ai-glitch-container {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #111;
}

.ai-glitch-text {
  font-size: 2.5rem;
  font-weight: 800;
  color: #fff;
  position: relative;
}

.ai-glitch-text::before,
.ai-glitch-text::after {
  content: attr(data-text);
  content: attr(data-text) / "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.ai-glitch-text::before {
  animation: aiGlitch1 2s infinite linear alternate-reverse;
  clip-path: polygon(0 0, 100% 0, 100% 35%, 0 35%);
  color: #0ff;
}

.ai-glitch-text::after {
  animation: aiGlitch2 3s infinite linear alternate-reverse;
  clip-path: polygon(0 65%, 100% 65%, 100% 100%, 0 100%);
  color: #f0f;
}

@keyframes aiGlitch1 {
  0% {
    transform: translate(0);
  }

  20% {
    transform: translate(-3px, 2px);
  }

  40% {
    transform: translate(3px, -1px);
  }

  60% {
    transform: translate(-2px, -2px);
  }

  80% {
    transform: translate(2px, 1px);
  }

  100% {
    transform: translate(0);
  }
}

@keyframes aiGlitch2 {
  0% {
    transform: translate(0);
  }

  25% {
    transform: translate(2px, -2px);
  }

  50% {
    transform: translate(-3px, 1px);
  }

  75% {
    transform: translate(1px, 2px);
  }

  100% {
    transform: translate(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .ai-glitch-text::before {
    animation: none;
    transform: translate(-2px, 1px);
  }

  .ai-glitch-text::after {
    animation: none;
    transform: translate(2px, -1px);
  }
}
JavaScript (fx-0416)

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Text (HTML — content and data-text) GLITCH in both Write the same text in both places. If the text changes on the page (translation, dynamic content), copy it over in one line: el.dataset.text = el.textContent.
Copy colors (CSS — color of ::before and ::after) cyan #0ff, magenta #f0f Red and cyan (#ff2a2a, #00e5ff) give an anaglyph 3D look; two tones close to the text color, a subtle glitch.
Band height (CSS — clip-path: polygon(…)) 35% at the top, 35% at the bottom 20% / 20% leaves more white in the center and a finer effect; 50% / 50% colors the whole word, with no white band.
Amplitude (CSS — positions in @keyframes aiGlitch1 and aiGlitch2) 1 to 3 px Double the values (up to 6 px) for a very large heading; beyond that, the copies come off the word and reading gets tiring.
Pace (CSS — animation: aiGlitch1 2s …, aiGlitch2 3s …) 2 s and 3 s, back and forth Keep two different durations: if equal, the copies move together and the jitter looks mechanical. 0.3 s and 0.5 s give a nervous crackle.

FAQ

Is the slicing random?

No: both bands are fixed (35% at the top, 35% at the bottom) and the jitter positions are written in the @keyframes. The offset between two cycles of different lengths is what gives a feeling of irregularity. For truly random slicing you need a bit of JavaScript: every 100 to 300 ms, write randomly drawn bounds into two CSS variables and use them in the pseudo-elements' clip-path.

Why repeat the word in data-text?

Pseudo-elements cannot read an element's text, only its attributes: attr(data-text) is the only way, in pure CSS, to give them the same word. That is also why the copies do not follow a changing text: if your site translates or replaces the word, copy it into data-text at the same time.

How does it differ from AI Typo Morph (fx-0419)?

AI Typo Morph changes words: it scrambles the letters into randomly drawn characters, then settles the next word letter by letter, with a bit of JavaScript. Generative Glitch keeps the same word and makes it shake in colors, in pure CSS. Choose Generative Glitch for a fixed heading with a "disturbed signal" look; AI Typo Morph to reveal or cycle through words.