javascripthtmlcssanimation

How can I play an animation after the previous one is finished?


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.


Solution

  • 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>

    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.

    Edited:

    1. 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.

    2. Setting separate max-width for each nth-child element we can complete the solution.