DEV Community

Cover image for A Multi-line CSS only Typewriter effect
Temani Afif
Temani Afif

Posted on Edited on

A Multi-line CSS only Typewriter effect

After the scalable one-line typewriter and the crazy "scrabble"-writer let's do another one: The multi-line typewriter.

A CSS-only solution of course:

The effect relies on using a Monospace font and knowing the number of characters. Yes, I am starting with the drawbacks but that was the price for a generic and easy-to-use code.

The HTML is very basic:

This is a <span class="type" style="--n:53">CSS only solution for a multi-line typewriter effect.</span>
Enter fullscreen mode Exit fullscreen mode

A span with our text and the number of characters as a variable.

For the CSS:

.type {
  font-family: monospace;
  color:#0000;
  background:
    linear-gradient(-90deg,#00DFFC 5px,#0000 0) 10px 0,
    linear-gradient(#00DFFC 0 0) 0 0;
  background-size:calc(var(--n)*1ch) 200%;
  -webkit-background-clip:padding-box,text;
  background-clip:padding-box,text;
  background-repeat:no-repeat;
  animation: 
    b .7s infinite steps(1),   
    t calc(var(--n)*.3s) steps(var(--n)) forwards;
}
@keyframes t{
  from {background-size:0 200%}
}
@keyframes b{
  50% {background-position:0 -100%,0 0}
}
Enter fullscreen mode Exit fullscreen mode

A few lines of CSS code with no hard-coded values. We only need to update the variable --n.


How does it work?

The trick relies on background properties so as a reference I always recommend this article:

We have two background layers. The first layer will color the text and the second one will create the blinking caret.

The idea of the first layer is to apply a discrete animation of background-size to create a filling effect from the first character to the last one using a gradient coloration.

Here is a step-by-step illustration to understand the trick:

The second layer is our caret. Here we will perform two animations. The first one is a background-size animation similar to the text coloration since the caret needs to follow the text. The second one is a background-position animation to create the blinking effect.

Another step-by-step to understand:

The width of the caret is controlled by the 5px inside the gradient and we add a small offset (10px) to avoid having an overlap with the text animation.

That's it! Simply imagine both layers animating at the same time and we have our CSS-only typewriter effect.

✔️ No Javascript
✔️ A basic HTML code
✔️ No complex CSS code. Less than 10 declarations and no hard-coded values
✔️ Accessible. The text is written within the HTML code (no pseudo-element, no duplicated text)
❌ Require a monospace font
⚠️ You can use any text without changing the code but you have to update one variable

nice work


buy me a coffee

OR

Become a patron

Top comments (18)

Collapse
 
grahamthedev profile image
GrahamTheDev • • Edited

Love this one, I can't spot it but on iPhone (again...damned apple) it only shows the first two lines and then stops? Is it the background clip not behaving itself?

I only think that as the cursor position works correctly, I could be wrong!

Collapse
 
afif profile image
Temani Afif •

yes it's the background-clip:text working only for the first line of the span. Safari and IOS have a lot of issues with background-clip:text

Collapse
 
shyam3050 profile image
Shyam3050 •

so how can we do for safari and IOS.

Thread Thread
 
pheels profile image
Oliver McPheely •

Did you ever find a fix for this? experiencing the same issue

Collapse
 
alvaromontoro profile image
Alvaro Montoro •

Nice. I really like this one and the whole explanation. A+.

Collapse
 
realjohnliter profile image
John Liter •

So I messed around with your code as it would just print everything on a single line and not create a new line depending on the size of the window, so I added work-break: break-all to the bottom of the .type id and now it automatically prints to the next line regardless of window size. I hope this helps to improve upon your non-JS CSS typewriter creation

Collapse
 
santiagoesmeral profile image
Santiago Esmeral •

Hi @afif , thank you very much for this guide. It was really useful!

I'm trying to implement a version of this in a personal project, and i needed a responsive, multi-line typewriter effect, and this fits very nicely.

However, i am having a bit of a problem. I am not sure if this is a bug or me not having understood your guide well enough, but when i try to do it the steps dont seem to match the characters. Characters get chopped up weirdly.

I made a sandbox with an example implementation of my code. I tried even hardcoding the text length, the time and the text to display and the bug is still there. Its more visible on longer texts.

If you could take a look at it and see if you can spot the bug, i would really appreciate it. n.n

here's the sandbox: codesandbox.io/s/buggy-typewriter-...

Collapse
 
afif profile image
Temani Afif •

You are changing the animation, this won't work. Check my code to see the background-size definition I am using. It depends on the text length background-size:calc(var(--n)*1ch) 200%; You need to keep this. Same for the duration, it look like this: calc(var(--n)*.3s)

Collapse
 
santiagoesmeral profile image
Santiago Esmeral • • Edited

Thanks for replying Afif!

I re-implemented the background and the calcs, but that was not the problem.

It turns out that the problem were my modification to the animations.

I wrote:
@keyframes typeText {
from {
background-size: 0 200%;
}
to {
background-size: 100% 200%;
}
}

and commenting out the to{} fixed it. I seem to have misunderstood what the animation does exactly.

additionally, another bug is that i was using japanese characters or emojis, which seem to not work very well with monospace fonts...

Anyways, thanks again for the typewriter effect! i love it

Collapse
 
kayaks2fish profile image
kayaks2fish •

This one's really helpful and I will surely try this, the explanation was also great.

Collapse
 
maenon profile image
Luca • • Edited

Hey! This is great. I have been trying to implement it on text under a tag, but I am having some difficulties. That's the best I got: codepen.io/Luca-Marco-Pappalardo/p.... Basically the link text is not animated in sequence, the other best outcome I had was for the text to remain black and not be animated at all. Any idea on how ti fix this?

Collapse
 
bbln profile image
bbln •

Respect!

Collapse
 
ribosomatic profile image
Jesus Liñan •

Nice! Good job!

Collapse
 
guscarpim profile image
Gustavo Scarpim •

Good, how do you link the posts?

Collapse
 
afif profile image
Temani Afif •

by creating a serie. You can find this setting next to the publish button

Collapse
 
alvaromontoro profile image
Alvaro Montoro •

Oooh! I need to make mine a series too... next one coming this evening.

Collapse
 
guscarpim profile image
Gustavo Scarpim •

Nice, tks!

Collapse
 
eronalves1996 profile image
EronAlves1996 •

This can be great if you use it with javascript to calculate the length of text and update the variable. The code can be simple.