Unable to achieve smooth fade-in text animation in React using Typescript

Seeking assistance in creating a smooth fade-in text animation using CSS in React and Typescript with inline styling. I have attempted to define styles within an object and reference them in the style attribute, but encountered issues. Can anyone offer guidance or suggestions?

Here is a functional example of the desired effect: https://codepen.io/kazed972/pen/bQOQGR

Snippet from my code:

import React from 'react';

const styles = {
    // Styling properties here
};

function FadeInText() {
    var text = document.getElementById('text') as HTMLElement;
    var newDom = '';
    var animationDelay = 6;

    for (let i = 0; i < text.innerText.length; i++) {
        // Logic for generating dynamic span elements
    }

    // Apply animation delay to each character span element

    return (
        <div style={styles.center}>
            <p id="text">
                Lorem ipsum dolor sit amet consectetur adipisicing elit...
            </p>
        </div>
    );
}

export { FadeInText };


Answer №1

Consider using styled-components to maintain consistency in your react component styling.

I have made some changes to the styles. The parent element (Section) now utilizes flexbox. Each letter in TextStyle has a predefined position with a transform, which can be simplified by keeping only the final frame from the keyframes. Additionally, TextStyle now accepts two custom props: delay and color.

TextAnimation.tsx

import styled, { keyframes } from 'styled-components';

const anim = keyframes`
  100% { opacity: 1; transform: translate3d(0, 0, 0) }
`;

const Section = styled.section`
  width: 70vw;
  display: flex;
  flex-wrap: wrap;
`;

const TextStyle = styled.span<{ color: string; delay: number }>`
  animation: ${anim} 1s ease-out forwards;
  animation-delay: ${(props) => props.delay}ms;
  color: ${(props) => props.color};
  font-size: 2em;
  line-height: 1.3;
  opacity: 0;
  transform-style: perspective(500px);
  transform: translate3d(-35px, -40px, -150px) rotate3d(1, -1, 0, 35deg);
`;

const DELAY = 6; // ms
export const TextAnimation = ({ text }: { text: string }) => {
  // Splitting text into individual characters and creating an array of HTML nodes.
  const letters = text.split('').map((letter, index) => {
    // Calculate delay for each character
    const delayCounter = DELAY * (index + 1);

    return (
      <TextStyle key={index} delay={delayCounter} color="white">
        {letter === ' ' ? <>&nbsp;</> : letter}
      </TextStyle>
    );
  });

  return <Section>{letters}</Section>;
};

App.tsx

import { TextAnimation } from "./TextAnimation";

export default function App() {
  const text =
    "Lorem ipsum dolor sit amet consectetur adipisicing elit. Cupiditate incidunt praesentium, rerum voluptatem in reiciendis officia harum repudiandae tempore suscipit ex ea, adipisci ab porro.";
  return (
    <div className="App">
      <TextAnimation text={text} />
    </div>
  );
}

https://codesandbox.io/s/smooth-fade-in-text-animation-doesnt-work-react-typescript-2vt6e2?file=/src/App.tsx

Answer №2

Here is a unique React approach to achieve the desired effect:

FadeInText.js:

const FadeInText = ({ text }) => {
  return (
    <div className="center">
      <p>{addAnimationEffect(text)}</p>
    </div>
  );
};

const addAnimationEffect = (text) => {
  const ANIMATION_DELAY = 6;

  // Convert string to array of characters with non-breaking spaces for empty spaces
  const allChars = [...text].map((char) => (char === " " ? <>&nbsp;</> : char));

  return allChars.map((char, i) => {
    return (
      <span
        key={i}
        className="char"
        style={{ animationDelay: `${ANIMATION_DELAY * i}ms` }}
      >
        {char}
      </span>
    );
  });
};

export default FadeInText;

This is how you can utilize the above component:

App.js:

import FadeInText from "./FadeInText";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <FadeInText text="Lorem ipsum dolor sit amet consectetur adipisicing elit. Cupiditate incidunt praesentium, rerum voluptatem in reiciendis officia harum repudiandae tempore suscipit ex ea, adipisci ab porro." />
      <FadeInText text="Hello world! Hello world! Hello world! Hello world! Hello world!" />
    </div>
  );
}

styles.css:

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background-color: #232323;
  color: #fff;
  font-family: Calibri, sans-serif;
}

.center {
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

p {
  width: 70%;
  font-size: 30px;
  display: block;
  text-align: center;
}

.char {
  font-size: 40px;
  height: 40px;
  animation: an 1s ease-out 1 both;
  display: inline-block;
}

@keyframes an {
  from {
    opacity: 0;
    transform: perspective(500px) translate3d(-35px, -40px, -150px)
      rotate3d(1, -1, 0, 35deg);
  }
  to {
    opacity: 1;
    transform: perspective(500px) translate3d(0, 0, 0);
  }
}

See it in action here: https://codesandbox.io/s/bold-jepsen-bivcku?file=/src/FadeInText.js

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

Angular2 has encountered a malfunction with the chart feature

My attempt to create a Bar Chart with this GitHub repository is not working in Chrome. You can view my code on Plunker. Can someone help me identify the issue? Below is the updated code: app.ts import {Component, Pipe, PipeTransform} from 'angular2 ...

Instead of displaying the name, HTML reveals the ID

I have defined a status enum with different values such as Draft, Publish, OnHold, and Completed. export enum status { Draft = 1, Publish = 2, OnHold = 3, Completed = 4 } In my TypeScript file, I set the courseStatus variable to have a de ...

Is there a way to insert a colored square into a <button> tag rather than text?

Looking for help with the following HTML: <button name="darkBlue" onclick="setThemeColor(this.name)">Blue</button> <button name="black" onclick="setThemeColor(this.name)">Black</button> I'm interested in replacing the text on ...

Tips for leveraging a button to trigger server-side actions

Being a novice in web development, I'm currently working on a straightforward website that enables users to download files from the server side. These files are not pre-created; instead, there will be a button on the HTML page. When a user clicks this ...

Enhancing Alerts in Bootstrap 5.1+: Tweaking Text, Background, and Border Colors for Alert-Warning Messages using custom _variables.scss

Incorporating a custom _variables.scss file into my codebase is crucial for my project, and the way I import it is as follows: @import url('https://fonts.googleapis.com/css?family=Nunito'); @import 'variables'; @import 'bootstrap/s ...

How can I eliminate the gap above the footer in iframes alignment?

I have a setup with four iframes: header, menuframe, bodyframe, and footer. The menuframe and bodyframe are positioned next to each other with space between the footer and the menuframe/bodyframe. How can I remove this space? Here is the CSS: iframe{ ...

A JSON string transformed into a JSON value

Can a JSON string be used as a value within another JSON structure? Please provide a valid JSON string as a value of a JSON element. Here is an example of what I am looking for: { "numberOfBlocks": 2, "1": { "items": [ { "Id": "11 ...

Using JavaScript functions on HTML data loaded by the jQuery.append() method: A guide

Utilizing JSON data, I have successfully generated HTML content representing Questions and Multiple Choice Questions. My next goal is to capture user responses in an array after the submit button is clicked. This involves storing which radio button the use ...

Utilizing Typescript with Mongoose Schemas

Currently, I am attempting to connect my Model with a mongoose schema using Typescript. Within my IUser interface: export interface IUser{ _id: string; _email: string; } I also have a User class: export class User implements IUser{ _id: string; ...

What are the steps to validate a form control in Angular 13?

My Angular 13 application has a reactive form set up as follows: https://i.sstatic.net/LE219.png I am trying to validate this form using the following approach: https://i.sstatic.net/gxpgN.png However, I encountered the following error messages: https:// ...

Replacing all of the text in a document with a VSCode extension

I have a good understanding of how to implement a builder with selections, but I'm stuck on determining the appropriate replacement for my "something" comment vscode.window.activeTextEditor.edit(builder => { builder.replace(/* something */, "He ...

Tips for hiding a div element until its visibility is toggled:- Set the display property of

Looking for some guidance on this jQuery code I'm working with to create a toggle menu. The goal is to have the menu hidden when the page loads, and then revealed when a button is clicked. However, currently the menu starts off being visible instead o ...

Can an HTML select box have a horizontal scroll bar added to it?

I am facing an issue with the following HTML code. <!DOCTYPE html> <html> <body> <select> <option value="volvo">Volvoooooooooooooooootooooooolargeeeeeeeeeeee</option> <option value="saab">Saab& ...

What is the best way to iterate through multiple arrays using a single for loop

I have various hidden popups that are triggered to show on click using some JavaScript magic. As a beginner in JavaScript, I find myself writing multiple lines of code that look very similar. Currently, my code for handling these popup boxes looks like th ...

Strategies for ensuring completion of internal promises

When using fs.readdir to retrieve a list of directories and then again within the callback to get a list of "subpages" in each directory, I find myself wanting the first callback to wait until the second one is completed. Unfortunately, I'm unsure of ...

Tips for aligning pagination in the center in bootstrap 4

What is the best way to centrally align pagination in Bootstrap 4? I have tried adding the code, but the pagination remains aligned to the left instead of the center. Even when applying the text-center class to the parent element, it does not work as exp ...

Discover the steps for integrating an object into a Ext.grid.Panel using Sencha Ext Js

Currently, I am utilizing Sencha Ext Js 4 and have integrated an Ext.grid.Panel into my project. I am interested in adding another element inside the header, such as a textbox. Is this achievable? {filterable: true, header: 'Unique' /*Here i w ...

What is the solution to the error message stating that <tr> cannot be a child of <div>?

displayTodos() { return this.state.todos.map(function(item, index){ return <div todo={item} key = {index}>; <tr> <td>{item.todo_description}</td> <td>{item.todo_responsible}</td> ...

Ways to organize JSON data from a fetch request into multiple divisions

I have written a JavaScript code to fetch JSON information. I plan on storing this JSON file locally (I downloaded an example file and added a birthdate object for my usage example from https://jsonplaceholder.typicode.com/users) My goal is to parse the r ...

Changing a JavaScript Confirm to jQuery Confirm within a button element of an ASPX GridView

I am currently working on updating my code to replace the JavaScript confirm action with a Jquery confirm action. Using Jquery, I have implemented a Callback function that will run when the user clicks the OK button. How can I capture the OK action from t ...