I have been trying the typewriter animation, and it went well!
.typewriter{
display: flex;
justify-content: center;
}
.typewriter .p1,.p2{
font-family: monospace;
font-size: 1.5rem;
/* margin-inline: auto; */
overflow: hidden;
/* keeps on a single line */
white-space: nowrap;
/* cursor */
border-right: 3px solid;
/* steps = number of characters */
animation: typing 3s steps(22) forwards, blink 1s step-end infinite;
}
.typewriter .p2{
font-size: 3rem;
animation-delay: after previos;
}
@keyframes typing{
from{
width: 0;
}
to{
width: 100%;
}
}
@keyframes blink{
50%{
border-color: transparent;
}
}
<div class = "typewriter">
<div>
<p class = "p1">Hello, Welcome to CodePen!</p>
<p class = "p2">Let's get started!</p>
</div>
</div>
But I am confused, about how to play the second line animation after the first one.
I am trying to create a typewriter animation for two specific paragraphs with different lengths and font sizes.
I want to customize the animation delay for each line so that the second paragraph starts typing only after the first finishes.
Solutions that use animation-delay
or other modern techniques are welcome, but the existing duplicates do not address the unique requirements of this typewriter effect.
After going through the w3schools documentation and taking @AHaworth, @Yogi, and @alvinalvord's solutions, I have ended up with an answer myself. I would like to thank you all for your involvement.
The typewriter effect is a bit challenging when it comes to multiple elements with the conditions set by me:
By combining CSS properties like visibility
, nth-child(n)
, animation-fill-mode
I was able to achieve what I desired:
:root {
--typing-effect: typing 2s steps(24, end);
--blink-effect: blink 1s step-end;
}
.typewriter {
font-family: monospace;
display: flex;
justify-content: center;
font-size: 1.5rem;
}
.typewriter p {
overflow: hidden;
/* Ensures text doesn't overflow */
white-space: nowrap;
/* Prevents text from wrapping */
border-right: 2px solid black;
/* Simulates a typing cursor */
visibility: hidden;
width: fit-content;
}
/* Typing animation */
@keyframes typing {
from { max-width: 0; }
to { max-width: 100%; }
}
@keyframes blink { 50% { border-color: transparent; }}
/* Hide the cursor at the end. */
@keyframes hide { to { border-color: transparent; }}
/* Shows only after the previous animation is complete */
@keyframes show {
from { visibility: hidden; }
to { visibility: visible; }
}
/* Applying the animation */
p:nth-child(1) {
visibility: visible;
animation: var(--typing-effect), var(--blink-effect), hide 2s step-end;
/* Adjust based on text length */
animation-fill-mode: forwards;
max-width: calc(33*1.5rem);
}
p:nth-child(2) {
animation: show 0s 2s, var(--typing-effect) 2s, var(--blink-effect), hide 3.6s step-end;
/* Adjust based on text length */
animation-fill-mode: forwards;
max-width: calc(18*1.5rem);
}
p:nth-child(3) {
animation: show 0s 4.2s forwards, var(--typing-effect) 4.2s, var(--blink-effect) infinite;
max-width: calc(19*1.5rem);
}
<div class="typewriter">
<div>
<p>Hello, Welcome to stack overflow!</p>
<p>Let's get started!</p>
<p>Good Morning Peers!</p>
</div>
</div>
The visibility:hidden
property ensures subsequent lines remain hidden until their animations start.
The nth-child(n)
selector synchronizes the animations for each line.
The animation-fill-mode: forwards
keeps the lines visible after typing.
Edited:
The previous spacing issue has been solved by @alvinalvord
using max-width
instead of width
inside the typing @keyframes
we can solve the cursor extending problem.
Setting separate max-width for each nth-child
element we can complete the solution.