1

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.

6
  • 2
    Animation delay will be useful here,but you'll want to have slightly different keyframes (in the sense of number of character steps) for the different lines as well.
    – A Haworth
    Commented 2 days ago
  • 1
    If you want just css you can use animation-delay as A Haworth said. With javascript you can use eventlistener 'animationend'.
    – Mehdi
    Commented 2 days ago
  • 2
    I have voted to reopen this question as the question marked as duplicate is not only very old and out of date but also does not explicitly tackle the two aspects here - starting the second line animation after the first is complete with ensuring the two lengths of the texts are dealt with well AND doing 'sensible' related animation of the caret (border).
    – A Haworth
    Commented 2 days ago
  • Thank you for voting to reopen this question @AHaworth Commented 2 days ago
  • This question is similar to: Animate div elements sequentially with CSS?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem.
    – Yogi
    Commented yesterday

2 Answers 2

4

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
  • This works perfectly! Thank you, @alvinalvord, for the detailed solution. Starting the second line animation after the first is complete. However, writing animations for each one individually might be challenging in a scenario with more than 10 <p> elements. Do you think there's a way to make this reusable for larger sets of text? Commented 2 days ago
  • 3
    Use CSS variables in the keyframes definitions for the step size and delay and a CSS calc for the width (ch units) and duration to cut down on the repetition a bit.
    – A Haworth
    Commented 2 days ago
1

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>

  1. The visibility:hidden property ensures subsequent lines remain hidden until their animations start.

  2. The nth-child(n) selector synchronizes the animations for each line.

  3. 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
  • 1
    upvote. OP's code has multiple problems, but it's not necessary to fix everything. This answer the main question of how to sequentially animate elements. using delays and css properties.
    – Yogi
    Commented 12 hours ago

Not the answer you're looking for? Browse other questions tagged or ask your own question.