skip to Main Content

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.

2

Answers


  1. Chosen as BEST ANSWER

    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.


  2. 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).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search