Bug: ease-typewriter-loop caret visibly jumps at the end of each animation cycle
Description
The ease-typewriter-loop animation shows a visible blink/jump at the moment the animation resets from 100% to 0%. The typing cursor (caret) abruptly disappears and reappears at the start, and the typed text flashes briefly before retyping. This creates a jarring visual break at the end of each loop iteration.
Steps to Reproduce
- Link EaseMotion CSS v1.0.0
- Add a typewriter element:
<h1 class="ease-typewriter-loop">Hello World</h1>
- Watch the full animation cycle and observe the moment the text finishes typing and resets
Expected Behavior
The typewriter loop should smoothly transition between cycles — either by backspacing the text before retyping, or by having a brief pause with the full text visible before a clean reset, without any visible flash or jump.
Actual Behavior
At the end of each iteration, the steps() timing function causes the typed text to immediately snap from fully visible to completely empty. The caret (blinking cursor) disappears for one frame and reappears at the starting position. The transition is instant rather than smooth, and the visual flash is clearly noticeable, especially on dark backgrounds.
Implementation Hints
The issue is in core/animations.css where the typewriter keyframes are defined:
/* Current implementation */
.ease-typewriter-loop {
overflow: hidden;
white-space: nowrap;
border-right: 2px solid currentColor;
width: 0;
animation: ease-typewriter 4s steps(40) infinite;
}
@keyframes ease-typewriter {
0% {
width: 0;
}
100% {
width: 100%;
}
}
The fix should split the animation into multiple keyframe stages — typing, pause, deletion, pause — for a smoother loop:
/* Fixed implementation with smooth loop cycle */
.ease-typewriter-loop {
overflow: hidden;
white-space: nowrap;
border-right: 2px solid currentColor;
width: 0;
animation: ease-typewriter 6s steps(60) infinite;
}
@keyframes ease-typewriter {
0% {
width: 0;
}
40% {
width: 100%; /* Typing phase */
}
50% {
width: 100%; /* Pause with full text visible */
border-color: currentColor;
}
60% {
border-color: transparent; /* Blink caret off before deletion */
}
90% {
width: 0; /* Deletion phase (reverse typing) */
border-color: transparent;
}
100% {
width: 0; /* Pause before restart */
border-color: currentColor;
}
}
Alternatively, for a true smooth loop, animate in both directions:
@keyframes ease-typewriter-smooth {
0% {
width: 0;
border-color: currentColor;
}
35% {
width: 100%;
border-color: currentColor;
}
45% {
width: 100%;
border-color: transparent; /* Blink */
}
46% {
border-color: currentColor;
}
50% {
width: 100%;
border-color: currentColor;
}
85% {
width: 0;
border-color: currentColor;
}
100% {
width: 0;
border-color: currentColor;
}
}
Using animation-direction: alternate with steps() can also create a smoother back-and-forth typewriter loop without the hard reset.
Affected Files
core/animations.css — .ease-typewriter-loop keyframes timing and reset behavior
Labels
type:bug, level:intermediate, GSSoC-26
Bug:
ease-typewriter-loopcaret visibly jumps at the end of each animation cycleDescription
The
ease-typewriter-loopanimation shows a visible blink/jump at the moment the animation resets from 100% to 0%. The typing cursor (caret) abruptly disappears and reappears at the start, and the typed text flashes briefly before retyping. This creates a jarring visual break at the end of each loop iteration.Steps to Reproduce
Expected Behavior
The typewriter loop should smoothly transition between cycles — either by backspacing the text before retyping, or by having a brief pause with the full text visible before a clean reset, without any visible flash or jump.
Actual Behavior
At the end of each iteration, the
steps()timing function causes the typed text to immediately snap from fully visible to completely empty. The caret (blinking cursor) disappears for one frame and reappears at the starting position. The transition is instant rather than smooth, and the visual flash is clearly noticeable, especially on dark backgrounds.Implementation Hints
The issue is in
core/animations.csswhere the typewriter keyframes are defined:The fix should split the animation into multiple keyframe stages — typing, pause, deletion, pause — for a smoother loop:
Alternatively, for a true smooth loop, animate in both directions:
Using
animation-direction: alternatewithsteps()can also create a smoother back-and-forth typewriter loop without the hard reset.Affected Files
core/animations.css—.ease-typewriter-loopkeyframes timing and reset behaviorLabels
type:bug,level:intermediate,GSSoC-26