skip to Main Content

I want to create animation similar to lving.io where different text reveals. I tried to recreate this but the animation is not smooth.

I tried assigning different animation delays to the texts, but they are not working in sync.
The texts are revealed at the same time when they should be revealing one at a time.


    .animation-container {
      display: flex;
      align-items: center;
      height: 1.5em; /* Adjust this based on your content size */
      font-size: 1.2em; /* Adjust this based on your design */
      overflow: hidden;
    }

    .base-text {
      white-space: nowrap;
    }
    
    .spans-container{
    margin-left: 5px;
    display: flex;
    flex-direction: column
    }

    .word {
      margin: 0;
      opacity: 0;
      animation: fadeInOut 9s linear infinite;
    }

    .word:nth-child(2) { animation-delay: 3s; }
    .word:nth-child(3) { animation-delay: 6s; }

    @keyframes fadeInOut {
      0% {
        opacity: 0;
        transform: translateY(100%);
      }
      15% {
        opacity: 1;
        transform: translateY(0);
      }
      30% {
        opacity: 1;
        transform: translateY(0);
      }
      45% {
        opacity: 1;
        transform: translateY(0);
      }
      60% {
        opacity: 0;
        transform: translateY(-200%);
      }
      75% {
        opacity: 0;
        transform: translateY(-200%);
      }
      90% {
        opacity: 0;
        transform: translateY(-200%);
      }
      100% {
        opacity: 0;
        transform: translateY(100%);
      }
    }
  


  <div class="animation-container">
    <span class="base-text">The future of home</span>
    <div  class="spans-container">
      <span class="word"> living</span>
      <span class="word"> owning</span>
      <span class="word"> renting</span>
    </div>
  </div>


2

Answers


  1. Have the words be on top of each other before we apply the animation. This will simplify the animation since the words are in the same place, but with the animation offset:

    .animation-container {
      display: flex;
      align-items: center;
      height: 1.5em;
      /* Adjust this based on your content size */
      font-size: 1.2em;
      /* Adjust this based on your design */
      overflow: hidden;
    }
    
    .base-text {
      white-space: nowrap;
    }
    
    .spans-container {
      margin-left: 5px;
      display: grid;
    }
    
    .word {
      margin: 0;
      grid-area: 1 / 1 / -1 / -1;
    }
    <div class="animation-container">
      <span class="base-text">The future of home</span>
      <div class="spans-container">
        <span class="word"> living</span>
        <span class="word"> owning</span>
        <span class="word"> renting</span>
      </div>
    </div>

    For the animation, we have 3 elements, so our keyframe "active" duration should be 33.33%, since 100% ÷ 3 = 33.33…%. This is so our animations can be offset seamlessly:

    ■ Visible
    ◻ Invisible
    
     0%/100%     33.33%      66.66%     0%/100%
    1: |■ ■ ■ ■ ■ ■|◻ ◻ ◻ ◻ ◻ ◻|◻ ◻ ◻ ◻ ◻ ◻|■ ■ ■
    2: |◻ ◻ ◻ ◻ ◻ ◻|■ ■ ■ ■ ■ ■|◻ ◻ ◻ ◻ ◻ ◻|◻ ◻ ◻
    3: |◻ ◻ ◻ ◻ ◻ ◻|◻ ◻ ◻ ◻ ◻ ◻|■ ■ ■ ■ ■ ■|◻ ◻ ◻
    
    .animation-container {
      display: flex;
      align-items: center;
      height: 1.5em;
      /* Adjust this based on your content size */
      font-size: 1.2em;
      /* Adjust this based on your design */
      overflow: hidden;
    }
    
    .base-text {
      white-space: nowrap;
    }
    
    .spans-container {
      margin-left: 5px;
      display: grid;
    }
    
    .word {
      margin: 0;
      grid-area: 1 / 1 / -1 / -1;
      animation: fadeInOut 9s infinite both;
    }
    
    .word:nth-child(2) {
      animation-delay: -6s;
    }
    
    .word:nth-child(3) {
      animation-delay: -3s;
    }
    
    @keyframes fadeInOut {
      0%, 33.33%, 100% {
        opacity: 1;
        transform: translateY(0);
      }
      33.34% {
        opacity: 0;
        transform: translateY(-100%);
      }
      99.9% {
        opacity: 0;
        transform: translateY(100%);
      }
    }
    <div class="animation-container">
      <span class="base-text">The future of home</span>
      <div class="spans-container">
        <span class="word"> living</span>
        <span class="word"> owning</span>
        <span class="word"> renting</span>
      </div>
    </div>

    We then add some animation either side of 0% and 33%. It should be the same percentage amount so that the outgoing and ingoing animation happen together and at the same speed. For example, 10%:

    ■ Visible
    ◻ Invisible
    ◧ Transitioning out
    ◨ Transitioning in
                
     0%/100%     33.33%      66.66%     0%/100%
    1: |■ ■ ■ ■ ■|◧|◻ ◻ ◻ ◻ ◻ ◻|◻ ◻ ◻ ◻ ◻|◨|■ ■ ■
    2: |◻ ◻ ◻ ◻ ◻|◨|■ ■ ■ ■ ■ ◧|◻ ◻ ◻ ◻ ◻|◻|◻ ◻ ◻
    3: |◻ ◻ ◻ ◻ ◻|◻|◻ ◻ ◻ ◻ ◻ ◨|■ ■ ■ ■ ■|◧|◻ ◻ ◻
               23.33%                   90%
    

    The trick is to ensure the 10% transitioning overlaps by subtracting/adding 10% to the appropriate keyframe.

    .animation-container {
      display: flex;
      align-items: center;
      height: 1.5em;
      /* Adjust this based on your content size */
      font-size: 1.2em;
      /* Adjust this based on your design */
      overflow: hidden;
    }
    
    .base-text {
      white-space: nowrap;
    }
    
    .spans-container {
      margin-left: 5px;
      display: grid;
    }
    
    .word {
      margin: 0;
      grid-area: 1 / 1 / -1 / -1;
      animation: fadeInOut 9s infinite both;
    }
    
    .word:nth-child(2) {
      animation-delay: -6s;
    }
    
    .word:nth-child(3) {
      animation-delay: -3s;
    }
    
    @keyframes fadeInOut {
      0%, 23.33%, 100% {
        opacity: 1;
        transform: translateY(0);
      }
      33.33% {
        opacity: 0;
        transform: translateY(-100%);
      }
      90% {
        opacity: 0;
        transform: translateY(100%);
      }
    }
    <div class="animation-container">
      <span class="base-text">The future of home</span>
      <div class="spans-container">
        <span class="word"> living</span>
        <span class="word"> owning</span>
        <span class="word"> renting</span>
      </div>
    </div>
    Login or Signup to reply.
  2. As an option, you can create separate animations for each word.
    To avoid having to do it myself, I used a generator that was created in another stackoverflow answer.
    You might find it useful:

    .animation-container {
      font-size: 1.2em;
    }
    
    .spans-container {
      display: inline-flex;
      position: relative;
      overflow: hidden;
    }
    
    .word {
      position: absolute;
      inset: 0;
    }
    
    /* the largest word width */
    .word:nth-child(2) {
      position: relative; 
    }
    
    /* code from the generator */
    .word:nth-child(1) {
      animation: slide1 12s infinite;
    }
    @keyframes slide1 {
      0% { transform: translateY(100%); }
      3.333333333333334%, 30% { transform: translateY(0); }
      33.333333333333336%, 100% { transform: translateY(-100%); }
    }
            
    .word:nth-child(2) {
      animation: slide2 12s infinite;
    }
    @keyframes slide2 {
      0%, 33.333333333333336% { transform: translateY(100%); }
      36.66666666666667%, 63.333333333333336% { transform: translateY(0); }
      66.66666666666667%, 100% { transform: translateY(-100%); }
    }
            
    .word:nth-child(3) {
      animation: slide3 12s infinite;
    }
    @keyframes slide3 {
      0%, 66.66666666666667% { transform: translateY(100%); }
      70%, 96.66666666666667% { transform: translateY(0); }
      100% { transform: translateY(-100%); }
    }
    <div class="animation-container">
      <span class="base-text">The future of home</span>
      <div class="spans-container">
        <span class="word">living</span>
        <span class="word">owning</span>
        <span class="word">renting</span>
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search