Text typing animation without JavaScript (only CSS)
This is a text typing effect that is achieved using only CSS and HTML.
Preview
This is a text typing effect that happens entirely through HTML and CSS.
Html
Click to edit (doesn't update preview)
<p>
<span class="typing-effect" style="animation-delay: 0s; animation-duration: 1.5s; width: 29ch; animation-timing-function: steps(29);">This is a text typing effect</span>
<span class="typing-effect" style="animation-delay: 1.65s; animation-duration: 1.85s; width: 30ch; animation-timing-function: steps(30);">that happens entirely through</span>
<span class="typing-effect" style="animation-delay: 3.65s; animation-duration: 0.9s; width: 13ch; animation-timing-function: steps(13);">HTML and CSS.</span>
</p>
<!-- Button below is only used for animation reset -->
<button onClick="reset()" class="typing-effect" style="animation-delay: 5s; animation-duration: 1.3s; width: 19ch; animation-timing-function: steps(18);">Click me to reset!</button>
CSS
Click to edit (doesn't update preview)
.typing-effect {
display: block;
animation: letters, blink .5s step-end alternate;
animation-fill-mode: forwards;
white-space: nowrap;
overflow: hidden;
border-right: 3px solid;
opacity: 0;
font-family: monospace;
}
@keyframes letters {
0% {
width: 0;
opacity: 1;
}
99% {
border-color: #888;
}
100% {
opacity: 1;
border-color: transparent;
}
}
JS
Click to edit (doesn't update preview)
// JavaScript is not needed at all!
// This is just a function for the "reset" button.
function reset() {
const typing = document.getElementsByClassName('typing-effect');
for (var i = 0; i < typing.length; ++i) {
typing[i].style.display = 'none';
}
setTimeout(() => {
for (var i = 0; i < typing.length; ++i) {
typing[i].style.display = 'block';
}
}, 55);
}
Description
How it works
The .typing-effect
class has an animation where it goes from zero width to full width on multiple text lines. Part of the animation is a border-right
CSS attribute, which creates the typing pointer effect.
To make sure each line has the correct width, the width
attribute is inlined to each span element using a ch (ch = character width unit). To know what ch amount you need, you just count how many letters the line has, and use that amount. With some fonts, you might need to use a larger or smaller amount.
Next to the inlined width attribute is the animation-timing-function
attribute that tells the CSS in how many steps the animation should happen. Without it, the width would animate smoothly instead of being "typed out". As we want only one letter to come out on each step, we use the amount of letters on the line as the step amount. A line with 20 letters will have a step amount of 20.
Each line has an animation-duration
attribute, where you just choose how fast that line should get typed. The longer the line, the longer the duration should be. Next to it is the animation-delay
, which makes sure that the lines don't all start at the same time, and instead you only make each line start animating after the one above it has finished.
Accessibility
This effect is fully accessible to screen readers. If this effect is a major part of your design, you might want to check out prefers-reduced-motion
media option in CSS. That way, you can disable the effect for those users who don't wish to see moving elements on the screen.
The lines are wrapped inside a paragraph tag, because in this context, each line is not a separate paragraph, and instead is part of the same paragraph.