Lucas Bebber’s Glitch is a super cool effect. It’s like you’re looking at some text displayed on a progressive scan monitor that has been dropped on the ground one too many times and so the alignment of the pixels is off in weirdly un-even amounts time and space.
It’s bonafide CSS trick if there ever was one! It took me a bit to figure out how it was working, so I thought I’d explain. Then I ended up making it work for other kinds of content as well as making it into a group of Sass @mixin
s to make working with it a bit easier.
See the Pen
CSS Glitched Text by Chris Coyier (@chriscoyier)
on CodePen.
Three Copies of the Text
While the HTML is just:
<div class="glitch" data-text="GLITCH">GLITCH</div>
Three copies of it are created, via pseudo-elements, and they are positioned right on top of each other.
.glitch {
position: relative;
}
.glitch::before,
.glitch::after {
content: attr(data-text);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
Producing three unique copies that can be controlled individually:

Alter the Copies
Each copy is identical except that:
- It’s offset to the left or right
- It has a highlight, in the form of a text-shadow
Between the offset and the highlight, it gives it that broken feeling.
.glitch::before {
/* ... anything needed to make it identical */
/* variation */
left: 2px;
text-shadow: -1px 0 red;
/* important: opaque background masks the original */
background: black;
}
.glitch::after {
/* ... anything needed to make it identical */
/* variation */
left: -2px;
text-shadow: -1px 0 blue;
/* important: opaque background masks the original */
background: black;
}
So now the three copies are like this:

Clipping the Copies
You’d only ever see the top copy if left as-is. Probably the ::after
version, unless you alter with z-index
. But never fear, we’re going to be only revealing parts of the top, altered copies with the clip
property. This property is apparently deprecated in favor of clip-path
, but at the time of this writing, only clip
was working for me. I’m sure that will change in time, so we’ll have to keep an eye on it, and presumably, Autoprefixer will handle it.
Update! August 2019: Plenty of time has past, and clip
is still generally supported, but deprecated in favor of the (better) clip-path
. The clip
syntax can do what the inset()
function value is for clip-path
, so I’m updating this article to use that. Doesn’t look like Autoprefixer deals with the conversation.
The syntax for clip
is kinda weird. For the four values, you might expect something like top/left/width/height, or point-at-top-left/point-at-bottom-right. But instead, it’s like margin and padding: top/right/bottom/left
.glitch::before {
clip: rect(44px, 450px, 56px, 0);
/*
Essentially a box from 0, 44px
to 450px, 56px
*/
/* clip-path: inset(); needs how far you want to push in from the edges instead */
}
Here’s some example clips on those layers, now with fully opaque backgrounds applied (but still rotated and with extra colors so you can see what’s going on):

Animate the Clips
Turns out clip can be animated, so, that clipped box will animate to a new position over time if told to, Here’s an example of keyframes:
@keyframes noise-anim {
0% {
clip-path: inset(40% 0 61% 0);
}
20% {
clip-path: inset(92% 0 1% 0);
}
40% {
clip-path: inset(43% 0 1% 0);
}
60% {
clip-path: inset(25% 0 58% 0);
}
80% {
clip-path: inset(54% 0 7% 0);
}
100% {
clip-path: inset(58% 0 43% 0);
}
}
Notice the left and right values remain the same, it’s just the top and bottom that change. And those values are kinda random.
You can generate that pretty easily with Sass, like:
@keyframes noise-anim {
$steps: 20;
@for $i from 0 through $steps {
#{percentage($i*(1/$steps))} {
$top: random(100);
$bottom: random(101 - $top);
clip-path: inset(#{$top}% 0 #{$bottom}% 0);
}
}
}
Because you’d want two sets of randomized clipping positions, you’d make two sets of those @keyframes, and apply them to the copies:
.glitch::before {
...
animation: glitch-anim-1 2s infinite linear alternate-reverse;
}
.glitch::after {
...
animation: glitch-anim-2 2s infinite linear alternate-reverse;
}
There is where we set the speed (number of keyframes also affects speed) as well as making it run infinitely back and forth.
It’s pretty fun to watch:

Although it should go without saying a little goes a long way.
Sass @mixins
I thought it would be neat if the technique was more reusable. Basically, call a @mixin
with parameters to control the effect and get just what you need.
.example-one {
font-size: 100px;
@include textGlitch("example-one", 17, white, black, red, blue, 450, 115);
}
Here’s my take on it:
/*
(TEXT) PARAMS
=================
1. Namespace
2. Intensity
3. Text color
4. Background color (flat)
5. Highlight #1 color
6. Highlight #2 color
7. Width (px)
8. Height (px)
*/
@mixin textGlitch($name, $intensity, $textColor, $background, $highlightColor1, $highlightColor2, $width, $height) {
color: $textColor;
position: relative;
$steps: $intensity;
// Ensure the @keyframes are generated at the root level
@at-root {
// We need two different ones
@for $i from 1 through 2 {
@keyframes #{$name}-anim-#{$i} {
@for $i from 0 through $steps {
$top: random(100);
$bottom: random(101 - $top);
#{percentage($i*(1/$steps))} {
clip-path: inset(#{$top}% 0 #{$bottom}% 0);
}
}
}
}
}
&::before,
&::after {
content: attr(data-text);
position: absolute;
top: 0;
left: 0;
width: 100%;
background: $background;
}
&::after {
left: 2px;
text-shadow: -1px 0 $highlightColor1;
animation: #{$name}-anim-1 2s infinite linear alternate-reverse;
}
&::before {
left: -2px;
text-shadow: 2px 0 $highlightColor2;
animation: #{$name}-anim-2 3s infinite linear alternate-reverse;
}
}
There are a million different ways to approach it, this is just one. Totally depends on how much you want the mixin to do for you, how much customizability you want or need, what you want left in the HTML, etc.
I also made two more mixins, one for applying this effect to images, and on for inline SVG. They are different because they don’t use pseudo-elements to make the copies, coloring happens in different ways, positioning happens differently, etc. Here’s all three of them together.
And a demo:
See the Pen
CSS Glitched Text by Chris Coyier (@chriscoyier)
on CodePen.
Clever!
Really nice use of clipping. Thank you.
Cool effect but one wonders whether this crosses the line in regards to WCAG 2.0’s “Guideline 2.3 Seizures: Do not design content in a way that is known to cause seizures.”
It is definitely crossing that line but nobody really adheres to those rules anyway.
It’s a demo highlighting cool techniques, not something that’s recommended to put on a live site. WCAG doesn’t really apply here.
Though thinking about it, media queries for certain accessibility issues would actually allow things like this safely.
Please note that I didn’t say it wasn’t a cool demo or not inspiring or that this effect can’t be used evers. I just noted it may break one of the WCAG 2.0’s guidelines for accessibility. Thus my original comment. Let’s not read more into my comment then what’s there.
@Chao – media queries for accessibility – that sounds like an interesting idea. How would you envision that working?
My head hurts now.
@Ben not anything thought out just something that came to mind then thinking about the line between some accessibility guidelines and design. Basically a user would let their browser know certain accessibility issues and could resolve these within a media query. The exact granularity and features would of course be subject to a wide amount of discussion.
So if for instance I came across a beautifully designed page with a blue heading with a drop shadow against a light blue background this would obviously fail WCAG on contrast ratios. I could select in the browser accessibility options a preference for high contrast (some eg Firefox already have an option for this). Thankfully this site has catered for me and the CSS contains the following:
For browsers with a built in high-contrast mode the explicit declaration would either turn this off or tell it to be less aggressive with its built in themes.
Ben, your answer is here: http://www.w3.org/TR/UNDERSTANDING-WCAG20/seizure-does-not-violate.html As this effect doesn’t blink nor flash, I would think the glitch technique is safe from an accessibility point of view. That said, I imagine it might be difficult for people with cognitive issues to parse text content.
Oh hey very nice write-up, and great mixin as well!
Not very useful in this form but still awesome :D
Select the text for a good time.
Great effects. Really nice animations ;)
Clever, but it hurts my eyes to look at it for more than a second.
You know what would be a cool addition? Some sweet text glowing and fuzzy-ing with text-shadow for a ring-ish effect. Maybe even some random zoom jumps?
Now I’m gonna go waste some time making that happen…
http://codepen.io/jcutrell/pen/zgJfn – fun times.
Fun times indeed and yes i will steal your ideas while looking forward to your book :)
wow, cool effect
Chris could you make an article about styling external referenced SVG with CSS, and supporting browsers, Ii’m having a terrible time wth these to aspect of SVG Sprite Maps.
wait… question, how would you go on about prefixing animation with compass?? for some reason, autoprefixer is not working for me and need to prefix this :(
Could you explain more?
To have all prefixes, always, use this rule:
last 44 versions
Very nice specialty. We’ll use in Kamera Sistemleri web site
Mind-blowing! Brilliant code! This is a visual effect that appears a lot in videos.
I believe you can create a movie using just HTML and CSS! :P
would be way glitchier with some added static noise…
…sorry but someone had to ;)
http://codepen.io/chuckneely/full/ronfx/
Nice Article !
Chris, you could also have used a
background-image: inherit
orbackground: inherit
to make a copy of the element if you want to make the glitch effect over an image or having less HTML.Edit: @Chuck Neely, you can use this little trick to simplify your code.
Nice tip Malik thanks! I’ve updated my pen to simply use
background: inherit
for the pseudo element background images, works a charm.Woah man, that’s really a clever way of using clipping!
I converted the sass to css and tried it out on wordpress, but it didn’t work. Any ideas?
I’ve tried to get this to work…using HTML and CSS code, but all I get is GLITCH, with NO animation, just static word in all caps…what am I missing?? I am NOT familiar with SASS yet either…
Thank you!
YEAH…NO IDEA WHY THIS DON’T WORK?? I MUST BE A WATERHEAD? SO nice others can read/comprehend, and offer some assistance…GREAT PLACE, GREAT WORK ALL…CARRY ON!!
Same thing could not get animation working… Pseudo elements are all right in place, mixing is parched, but no animation …
This is cool. What would be the easiest way to turn this into a hover effect?
Chris I like it! Thanks Again! I had to add to my site goo.gl/Nwby5Y
Jonathan, thanks used some of your extras.
Still need to do some fine tuning with my CSS. Right now only making webkit changes that for some reason only works with Chrome. Safari will not budge. So the firefox version is Jonathan’s version that’s slightly changed for my site.
Mike
Fantastic!!! a wonderful functionality with which to continue to learn and grow in developing css. Thank you !!
going to use in my web site
Amazing and inspiring Chris. Now I know what I’ll be doing when some underground electro music band approach me to design their website.
Wow.
Only using one element, that’s a trick for me, I think it will be great when applying to the site title.
Genius!
Never thought about animating the clip property!
http://dexvision.com/test/Glitch/