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.
5
I modified one of your css class and added another keyframe and if my understanding is correct, you are looking for something like this?
.typewriter .p2{
font-size: 3rem;
animation: showAfter 3s, typing 3s steps(22) forwards 2.9s, blink 1s step-end infinite;
}
@keyframes showAfter {
0% {
opacity: 0;
}
99% {
opacity: 0;
}
100% {
opacity: 1;
}
}
A brief explanation is basically to hide .p2 for 3 seconds (same duration as .p1 animation) then play the typing animation before the full 3 seconds completes (2.9s delay).
2
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:
- should use only CSS.
- should ensure simplicity and scalability.
- should ensure the second and following elements stay hidden until the initial animation is finished playing.
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 { width: 0; }
to { 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;
}
p:nth-child(2) {
animation: show 0s 2s, var(--typing-effect) 2s, var(--blink-effect), hide 4s step-end;
/* Adjust based on text length */
animation-fill-mode: forwards;
}
p:nth-child(3) {
animation: show 0s 4.2s forwards, var(--typing-effect) 4.2s, var(--blink-effect) infinite;
}
<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.
Even though I have achieved what I wanted, there are still some issues with the spacing. If you run the snippet you can see that the cursor extends to the full-width of the element even though I have set width: fit-content
to all <p>
elements.
If anyone can solve this problem, it would be a great help.
1