16 CSS Fade In Animation Designs 15 / 16
Glitch Flash Multi-Step Fade
A terminal-style display where the headline stutters into existence through a multi-step opacity flicker keyframe with micro translateX jitter, simulating a signal locking on.
The code
<div class="fi-15">
<div class="fi-15__screen">
<span class="fi-15__line">BOOT SEQUENCE INITIATED...</span>
<span class="fi-15__line">LOADING KERNEL MODULES...</span>
<span class="fi-15__line">SIGNAL ACQUIRED. RENDERING...</span>
<div class="fi-15__glitch-text" data-text="GLITCH FADE">GLITCH FADE</div>
<div class="fi-15__sub">MULTI-STEP OPACITY FLICKER TECHNIQUE<span class="fi-15__cursor"></span></div>
</div>
</div> <div class="fi-15">
<div class="fi-15__screen">
<span class="fi-15__line">BOOT SEQUENCE INITIATED...</span>
<span class="fi-15__line">LOADING KERNEL MODULES...</span>
<span class="fi-15__line">SIGNAL ACQUIRED. RENDERING...</span>
<div class="fi-15__glitch-text" data-text="GLITCH FADE">GLITCH FADE</div>
<div class="fi-15__sub">MULTI-STEP OPACITY FLICKER TECHNIQUE<span class="fi-15__cursor"></span></div>
</div>
</div>.fi-15{
--bg:#050505;--red:#ff2244;--white:#f8f8f8;--dim:#888;
font-family:'Orbitron',monospace;
min-height:340px;border-radius:20px;
display:grid;place-items:center;
padding:40px;overflow:hidden;position:relative;
}
.fi-15 *,.fi-15 *::before,.fi-15 *::after{box-sizing:border-box;margin:0;padding:0}
.fi-15 ::selection{background:var(--red);color:#fff}
/* glitch-flash fade: multi-step opacity flicker + slight translateX jitter */
.fi-15__screen{text-align:center;position:relative}
.fi-15__line{
display:block;
font-family:'Share Tech Mono',monospace;
font-size:.7rem;letter-spacing:.15em;color:var(--dim);
margin-bottom:8px;
opacity:0;animation:fi-15-static .1s steps(1) forwards;
}
.fi-15__line:nth-child(1){animation-delay:.1s}
.fi-15__line:nth-child(2){animation-delay:.2s}
.fi-15__line:nth-child(3){animation-delay:.3s}
.fi-15__glitch-text{
font-size:clamp(2rem,6vw,4rem);font-weight:900;
color:var(--white);position:relative;display:inline-block;
animation:fi-15-glitch-in 1.2s steps(1) .4s forwards;opacity:0;
}
.fi-15__glitch-text::before,.fi-15__glitch-text::after{
content:attr(data-text);position:absolute;inset:0;
}
.fi-15__glitch-text::before{
color:var(--red);
animation:fi-15-ghost-r 1.2s steps(1) .4s forwards;opacity:0;
clip-path:polygon(0 20%,100% 20%,100% 45%,0 45%);
}
.fi-15__glitch-text::after{
color:#0ff;
animation:fi-15-ghost-l 1.2s steps(1) .4s forwards;opacity:0;
clip-path:polygon(0 55%,100% 55%,100% 80%,0 80%);
}
.fi-15__sub{
font-size:.65rem;letter-spacing:.2em;color:var(--dim);margin-top:16px;
opacity:0;animation:fi-15-static .1s steps(1) 1.4s forwards;
}
.fi-15__cursor{
display:inline-block;width:2px;height:1em;background:var(--red);
vertical-align:middle;margin-left:4px;
animation:fi-15-blink .8s steps(1) infinite 1.4s;opacity:0;
}
@keyframes fi-15-glitch-in{
0%{opacity:0;transform:translateX(-4px)}
5%{opacity:1;transform:translateX(3px)}
8%{opacity:0;transform:translateX(-2px)}
12%{opacity:1;transform:translateX(0)}
20%{opacity:.3;transform:translateX(2px)}
22%{opacity:1;transform:translateX(0)}
35%{opacity:.8;transform:translateX(-1px)}
40%{opacity:1;transform:translateX(0)}
100%{opacity:1;transform:translateX(0)}
}
@keyframes fi-15-ghost-r{
0%{opacity:0}5%{opacity:.8;transform:translateX(4px)}
8%{opacity:0}20%{opacity:.6;transform:translateX(-3px)}
22%{opacity:0}35%{opacity:.4;transform:translateX(2px)}
40%{opacity:0}100%{opacity:0}
}
@keyframes fi-15-ghost-l{
0%{opacity:0}12%{opacity:.7;transform:translateX(-3px)}
15%{opacity:0}28%{opacity:.5;transform:translateX(2px)}
30%{opacity:0}100%{opacity:0}
}
@keyframes fi-15-static{to{opacity:1}}
@keyframes fi-15-blink{0%,100%{opacity:1}50%{opacity:0}}
@media(prefers-reduced-motion:reduce){
.fi-15 *{animation:none!important;opacity:1!important;transform:none!important}
} .fi-15{
--bg:#050505;--red:#ff2244;--white:#f8f8f8;--dim:#888;
font-family:'Orbitron',monospace;
min-height:340px;border-radius:20px;
display:grid;place-items:center;
padding:40px;overflow:hidden;position:relative;
}
.fi-15 *,.fi-15 *::before,.fi-15 *::after{box-sizing:border-box;margin:0;padding:0}
.fi-15 ::selection{background:var(--red);color:#fff}
/* glitch-flash fade: multi-step opacity flicker + slight translateX jitter */
.fi-15__screen{text-align:center;position:relative}
.fi-15__line{
display:block;
font-family:'Share Tech Mono',monospace;
font-size:.7rem;letter-spacing:.15em;color:var(--dim);
margin-bottom:8px;
opacity:0;animation:fi-15-static .1s steps(1) forwards;
}
.fi-15__line:nth-child(1){animation-delay:.1s}
.fi-15__line:nth-child(2){animation-delay:.2s}
.fi-15__line:nth-child(3){animation-delay:.3s}
.fi-15__glitch-text{
font-size:clamp(2rem,6vw,4rem);font-weight:900;
color:var(--white);position:relative;display:inline-block;
animation:fi-15-glitch-in 1.2s steps(1) .4s forwards;opacity:0;
}
.fi-15__glitch-text::before,.fi-15__glitch-text::after{
content:attr(data-text);position:absolute;inset:0;
}
.fi-15__glitch-text::before{
color:var(--red);
animation:fi-15-ghost-r 1.2s steps(1) .4s forwards;opacity:0;
clip-path:polygon(0 20%,100% 20%,100% 45%,0 45%);
}
.fi-15__glitch-text::after{
color:#0ff;
animation:fi-15-ghost-l 1.2s steps(1) .4s forwards;opacity:0;
clip-path:polygon(0 55%,100% 55%,100% 80%,0 80%);
}
.fi-15__sub{
font-size:.65rem;letter-spacing:.2em;color:var(--dim);margin-top:16px;
opacity:0;animation:fi-15-static .1s steps(1) 1.4s forwards;
}
.fi-15__cursor{
display:inline-block;width:2px;height:1em;background:var(--red);
vertical-align:middle;margin-left:4px;
animation:fi-15-blink .8s steps(1) infinite 1.4s;opacity:0;
}
@keyframes fi-15-glitch-in{
0%{opacity:0;transform:translateX(-4px)}
5%{opacity:1;transform:translateX(3px)}
8%{opacity:0;transform:translateX(-2px)}
12%{opacity:1;transform:translateX(0)}
20%{opacity:.3;transform:translateX(2px)}
22%{opacity:1;transform:translateX(0)}
35%{opacity:.8;transform:translateX(-1px)}
40%{opacity:1;transform:translateX(0)}
100%{opacity:1;transform:translateX(0)}
}
@keyframes fi-15-ghost-r{
0%{opacity:0}5%{opacity:.8;transform:translateX(4px)}
8%{opacity:0}20%{opacity:.6;transform:translateX(-3px)}
22%{opacity:0}35%{opacity:.4;transform:translateX(2px)}
40%{opacity:0}100%{opacity:0}
}
@keyframes fi-15-ghost-l{
0%{opacity:0}12%{opacity:.7;transform:translateX(-3px)}
15%{opacity:0}28%{opacity:.5;transform:translateX(2px)}
30%{opacity:0}100%{opacity:0}
}
@keyframes fi-15-static{to{opacity:1}}
@keyframes fi-15-blink{0%,100%{opacity:1}50%{opacity:0}}
@media(prefers-reduced-motion:reduce){
.fi-15 *{animation:none!important;opacity:1!important;transform:none!important}
}How this works
The headline keyframe fi-15-glitch-in uses steps(1) timing to create hard jumps between opacity states — simulating signal dropout and re-acquisition. At key percentages (5%, 8%, 20%, 35%), the opacity dips to 0 and the translateX shifts by ±2–4px, recreating the jitter of a corrupted display signal. The total animation duration is 1.2s, with most of the glitch activity in the first 40%.
Two ::before/::after pseudo-elements carry content: attr(data-text) — duplicates of the headline coloured red and cyan. They animate asynchronously via fi-15-ghost-r and fi-15-ghost-l, flashing at different moments than the main element. clip-path: polygon() restricts each ghost to a horizontal band, making the colour fringing appear only on portions of the letter forms, exactly like RGB channel separation in analogue glitch.
Customize
- Increase glitch intensity by adding more opacity-zero stops to
fi-15-glitch-inat 45%, 65%, and 80%. - Change ghost colours from red/cyan to green/magenta for a different RGB-split aesthetic.
- Adjust the jitter magnitude: increase
translateX(3px)to6pxfor more violent signal distortion. - Add a
letter-spacingvariation at glitch keyframes — letters briefly spread then snap together.
Watch out for
- The
steps(1)timing function on the supporting line reveals creates hard instant transitions — if the browser pauses rendering (e.g. heavy paint), multiple steps may fire at once, collapsing the dramatic build-up. content: attr(data-text)on pseudo-elements requires thedata-textattribute to exactly match the visible text — if the content is dynamic, update the attribute with JavaScript whenever the text changes.- The ghost pseudo-elements use
clip-path: polygon()to restrict their visibility to horizontal bands — this clips their outline, which can cause accessibility tools to misreport bounding rects.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 60+ | 12+ | 60+ | 60+ |
steps(1) timing and clip-path polygon both require modern browser; pseudo-element attr() widely supported