Javascript is utilized to populate text within a div, although the animation is exclusively applied to the initial text

I am currently working on designing a landing page that showcases a dynamic display of rotating texts with a typewriter-like animation effect. While I have successfully implemented the animation for the first text, I am facing an issue where the subsequent texts are not animated but simply displayed on the screen. I am exploring solutions to address this problem, such as potentially applying the animation CSS with JavaScript for each text refresh. However, I am concerned about the efficiency and complexity of this approach. Any suggestions on how to resolve this issue in a more streamlined manner?

document.addEventListener('DOMContentLoaded', function(event) {
  // array with texts to type in typewriter
  var dataText = ["Hi, I'm Ned.", "Developer.", "Writer."];

  function typeWriter(i) {
    // add next text to h1
    document.querySelector("h1").innerHTML = dataText[i] + '<span aria-hidden="true"></span>';

    // wait for a while and call this function again for next text
    setTimeout(function() {
      typeWriter((i + 1) % 3)
    }, 10000);
  }

  // start the text animation
  typeWriter(0);
});
.typewriter h1 {
  font-weight: bold;
  color: #000;
  font-family: "Lucida Console";
  font-size: 2em;
  overflow: hidden;
  /*Hide content before animation*/
  border-right: .1em solid white;
  /*Cursor*/
  white-space: nowrap;
  /*Keep text on same line*/
  margin: 0 auto;
  /*Scrolling effect while typing*/
  letter-spacing: .1em;
  animation: typing 3s steps(30, end), blink-caret .75s steps(1, end) infinite alternate;
}


/* The typing effect */

@keyframes typing {
  from {
    width: 0
  }
  to {
    width: 100%
  }
}


/* The typewriter cursor effect */

@keyframes blink-caret {
  from,
  to {
    border-color: transparent
  }
  50% {
    border-color: white;
  }
}
<div class="jumbotron" id="jumbotron">
  <div class="typewriter">
    <h1></h1>
  </div>
</div>

Answer №1

The issue lies in the fact that once the CSS animation completes, it will not repeat for that specific element. To achieve a repeat effect, you can either remove the CSS class (containing the animation) from the element, pause for a moment, and then reapply it, or you can delete the element and recreate it.

In your case, I recommend creating a new h1 element, updating its content, and inserting it into the DOM. Make sure to remove the old element as well. Using jQuery, you can accomplish this with the following code:

var newH1 = $("<h1>");           // create the element
newH1.innerHTML = ...;
$(".typewriter").empty();    // remove all children
$(".typewriter").append(newH1);  // add the new h1 element

Plain JavaScript Method:

var newH1 = document.createElement("h1"); // create the element
newH1.innerHTML = ...;          // set its content
var typewriter = document.querySelector(".typewriter");
typewriter.innerHTML = '';  // remove all children
typewriter.appendChild(newH1);  // add the new h1 element

Additionally, please be aware that the changes made using the current query selector will affect ALL <h1> elements on the page.

Answer №2

If you want to simplify the process, utilizing JQuery can be beneficial. Additionally, I have included a function that halts the animation once all your data has been fully displayed.

<script type="text/javascript>
$(function() {
var dataText = [ "Hi, I'm Ned.", "Developer.", "Writer."];
function typeWriter(i) {
 var content = '<h1>' + dataText[i] +'<span aria-hidden="true></span></h1>'
 $(".typewriter").append(content);
 // wait for a while and call this function again for next character
 var myFunc = setTimeout(function() {
  typeWriter((i + 1)%3)
  }, 10000);
  if (i  == dataText.length - 1) {
   clearTimeout(myFunc);
  }
    }

  // start the text animation
  typeWriter(0);
})
</script>


<div class="jumbotron" id="jumbotron">
    <div class="typewriter">
    </div>
</div>

For further reference, you can view it here: https://jsfiddle.net/z4cryxx0/2/

Feel free to let me know if this addresses your query.

Answer №3

It seems like I have a solution for what you're looking for. Take a look:

const textData = [ "Hello, I'm Jenna.", "Designer.", "Artist."];
 
    function textAnimator(i) {
        // adding each character to h1 tag
        
        let h1Tag = document.createElement("h1");
        h1Tag.innerHTML = textData[i] +'<span aria-hidden="true"></span>'; // adding empty span for animation
        document.querySelector(".typewriter").append(h1Tag);
        
        // waiting for a while and calling the function again for the next character
        setTimeout(function() {
            document.querySelector(".typewriter").innerHTML = ''; // comment out to display the whole phrase
            textAnimator((i + 1)%3) // looping through the data array
        }, 8000); // controlling the speed of animation
    }

    // starting the text animation
    textAnimator(0);
.typewriter h1 {
    font-weight: bold;
    color: purple; 
    font-family: "Arial";
    font-size: 5em;
    overflow: hidden; /* hiding content before animation starts */
    border-right: .1em solid black; /* representing the cursor */
    white-space: nowrap; /* keep text on the same line */
    margin: 0 auto; /* creating typing effect */
    letter-spacing: .1em;
    animation:
        typing 3s steps(30, end),
        blink-caret .75s steps(1, end) infinite alternate;
}
/* The typing animation */
@keyframes typing {
   from { 
       width: 0
   }
   to { 
       width: 100% 
   }
}

/* The blinking cursor effect */
@keyframes blink-caret {
   from, to { 
       border-color: transparent 
   } 50% { 
       border-color: black; 
   }
}
<div class="container" id="container">
    <div class="typewriter">
        <h1></h1>
    </div>

The key is to reset the css animation by creating a new h1 element each time. Once a part or the whole phrase is displayed, all the existing h1 elements are removed, and the process is repeated.

Answer №4

To create a typewriter effect, you can make the animation infinite and adjust the duration to control the delay between text changes. Set the animation to end after 3 seconds (30% in this example) or any other desired duration:

.typewriter h1 {
    ...
    animation:
        typing 10s steps(30, end) infinite,
        blink-caret .75s steps(1, end) infinite alternate;
}

@keyframes typing {
   0% {
     width: 0;
   }
   30% {
     width: 100%;
   }
}

One downside is that when adjusting the delay between texts, you need to modify both the JavaScript delay and the CSS animation length.

JSFiddle

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

It never fails to function automatically, no matter which script is being executed

By default, the script will always be executed regardless of its environment. Check out my code snippet: import { Pool } from 'pg'; import config from './../config'; const connectionString = () => { switch (process.env.NODE_EN ...

Tips for automatically closing one sub menu while selecting another sub menu

I am working on a code snippet to manage the menu functionality. My goal is to ensure that when I click to open one submenu, any other currently open submenus should automatically close. ;(function($) { // Ensuring everything is loaded properly $ ...

Retrieve a key from the JSON response and then transmit it through a socket

In the context of a node server code using a monitoring module to track function properties, I am facing an issue where I need to retrieve a specific property from a JSON output and then transfer it to a socket. The function 'meter' looks like t ...

"Unleashing the power of custom servers to tap into the rendered HTML of Next

In my quest to serve a server-side generated page as a file using next.js, I decided to extract the rendered content within a custom server.js file: const express = require('express'); const next = require('next'); const port = parseIn ...

How to set default props in Vue Select component?

I have been utilizing the vue-multiselect plugin from this website: Given that I plan to use it frequently, I am interested in establishing some default props. For instance, my aim is to have the selectLabel prop set as an empty string and possibly con ...

The express gateway is unable to transfer multipart/formdata

I've implemented express gateway as my main service gateway. One of the services I have needs to update an image, and when I try to handle files independently using multer it works fine. However, once this service is routed through express gateway, th ...

Deno -> What steps should I take to ensure my codes run smoothly without any errors?

Trying to import locally Experimenting with Deno v1.6.0 in a testing environment Attempting local imports using Deno language Local directory structure: . └── src └── sample ├── hello_world.ts ├── httpRequest. ...

What is the best way to transfer JSON data to a different controller in AngularJS?

Hello, I'm still learning AngularJS and facing an issue with the following code snippet. app.config(function($routeProvider) { $routeProvider .when('/', { templateUrl: "partials/home.html", controller: "mainControlle ...

using database URL as an AJAX parameter

I am currently working on a Python CherryPy controller that needs to validate a database URL by attempting a connection. However, I am facing challenges with passing the parameter to the method. Below is my AJAX call: $.ajax({ async: false, ty ...

A simple method to obtain the ID of the element that has been clicked and save it in a variable to be utilized in a function responsible for

Seeking assistance in optimizing the code below by removing the specific #static id and allowing for dynamic IDs such as #dynamic within the one click function. This would eliminate the need to repeatedly copy and paste the same function with different ID ...

Ensure the backslashes are removed from the AWS Lambda string API response

I have an AWS Lambda function where I am sending a string as my final response let abc= `"phone_exist":"0","calls":"0","lastaction":"0"` callback(null,abc); Output: "\"phone_exist\":\"0\",\"calls\":\"0\",\"l ...

Manipulating visibility of an input tag using JQuery

Having a simple input tag: <input id="DAhour" type="number" style="width:50px; font-size: xx-small; visibility:hidden"> Initially, the input tag is set to be hidden. Upon changing a combobox to a specific index, it should become visible. Despite su ...

Clearing a textarea in jQuery

I'm experiencing an issue that I can't seem to resolve on my own. Any assistance would be greatly appreciated. My function designed to clear a textbox upon click doesn't seem to be working correctly: $(function() { $('textarea#co ...

Searching for entries using an array of _id along with other possible column values

const query_id = [1,2,3,4,5,6]; const query_type = "A"; let queries = await Query.find({ _id: query_id, query_type: query_type }); The current code functions as intended, but there may be a better and more elegant way to achieve t ...

Ways to avoid encoding Unicode characters in JavaScript programming

When I retrieve data from an API, I receive a STRING like this: [ { "reason": "Invalid address", "email": "j\u00c3\u00a9r\u00c3\u00b4mel\u00c3\u00a4ufer@com" }, { "reason": "Invalid address", "email": ...

What is the best way to place a p-growl element in the bottom right corner of the page?

I've been struggling to fix the positioning of my growl message at the bottom right corner by overriding the CSS classes of p-growl. Initially, I attempted to override the .ui-growl class like this: ::ng-deep .ui-growl { position: fixed; b ...

Receiving array data in a Javascript function and storing it within a variable

Hello everyone, please take a look at my code below. I am attempting to pass PHP array values to a JavaScript function. When I run the script, I receive alerts for parameter0=1, parameter1=2, and parameter2=3 separately. What I am trying to achieve is to ...

Navigating on Blogger can be a tricky task when it comes to searching and

I recently added a Table to my blogger post, along with an input form for readers to easily search data. After finding the code on W3Schools (link here), I implemented it successfully. However, I am looking to make some improvements. Here is my question: ...

Using MongoDB to find a specific element in an array and then make updates

I have performed aggregation to calculate the total and the objects that contribute to the total. Now, I need to update the source table with the aggregated object ID for the elements involved in the aggregation, establishing a two-way relationship. col ...

Understanding the Functioning of a Digital Analog Clock Using JavaScript

As a new learner, I found the operation of a Digital analog clock to be quite puzzling. I was presented with an image called clock.png, and I specifically struggled with how the hands of the clock function. Javascript - const deg = 6; // defining the valu ...