Creating a typewriter animation using Tailwind CSS and Next.js

I am currently working on implementing a typewriter effect that is almost exactly how I want it. However, I am facing an issue with the printing process. Right now, each word gets printed on a new line and falls into place when done printing. What I actually want is for each word to be printed and then continue on the next line before reaching a certain point within the container.

Here's my global.css:

@tailwind base;
@tailwind components;
@tailwind utilities;

.typewriter {
  border-right: 0px solid;
  width: 100%;
  white-space: normal;
  overflow: hidden;
  animation: typing 2s steps(40), cursor .4s step-end infinite alternate;
}

@keyframes cursor {
  50% {
    border-color: transparent;
  }
}

@keyframes typing {
  from {
    width: 0;
  }
}

body {
  @apply bg-gray-100;
}

page.js:

'use client';
import { useState, useEffect } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCircle } from '@fortawesome/free-solid-svg-icons';
import { useRouter } from 'next/navigation'; 

export default function LandingPage() {
  const [phraseIndex, setPhraseIndex] = useState(0);
  const [fadeIn, setFadeIn] = useState(true);
  const router = useRouter();

  useEffect(() => {
    const interval = setInterval(() => {
      setFadeIn(false);
      setTimeout(() => {
        setPhraseIndex((prevIndex) => (prevIndex + 1) % userSearchExamples.length);
        setFadeIn(true);
      }, 500); 
    }, 5000);

    return () => clearInterval(interval);
  }, [phraseIndex]);

  const handleLoginClick = () => {
    router.push('/login');
  };

  const handleRegisterClick = () => {
    router.push('/register');
  }; 

  const userSearchExamples = [
    "Find me an outfit for a night out",
    "What would go well with a grey hoodie?",
    "I need a dress for a wedding",
    "I need a casual outfit for a date",
    "What should I wear to a job interview?",
    "Help me find an outfit for a vacation"
  ];

  return (
    <main>
      <div className="w-full h-screen grid grid-cols-5">
        <div className="col-span-3 bg-customColor">
          <p className="text-purple-400 p-1 font-bold inline-flex gap-2 text-2xl items-center absolute left-5 top-5">
            FashionFinder
            <FontAwesomeIcon icon={faCircle} className="w-5" />
          </p>
          <div className="h-full flex items-center">
            <p className={`typewriter text-purple-400 text-4xl font-semibold text-left ml-4 mr-5 ${fadeIn ? 'fade-in' : 'fade-out'}`} key={phraseIndex}>
              {userSearchExamples[phraseIndex]}
            </p>
          </div>
        </div>
        <div className="col-span-2 bg-black flex flex-col items-center justify-center">
          <p className="text-3xl font-bold text-white">
            Get started
          </p>
          <div className='flex gap-4 w-full p-6'>
            <button
              className="p-4 bg-blue-700 font-bold w-full rounded-lg shadow-xl text-white"
              onClick={handleLoginClick}>
              Login
            </button>
            <button
              className='p-4 bg-blue-700 font-bold w-full rounded-lg shadow-xl text-white'
              onClick={handleRegisterClick}>
              Register
            </button>
          </div>
        </div>
      </div>
    </main>
  )
}

Answer №1

To achieve the typewriter effect, you can modify your CSS in the following way:

.typewriter {
  text-transform: none!important;
  overflow: hidden;
  border-right: .2em solid blue;
  white-space: nowrap;
  margin: 0; /* Adjust margin for alignment */
  letter-spacing: .15em;
  animation: typing-animation 4s steps(40, end), blink-caret-animation .75s step-end infinite;
}
@keyframes typing-animation {
  from { width: 0 }
  to { width: 100% }
}
@keyframes blink-caret-animation {
  from, to { border-color: transparent }
  50% { border-color: blue; }
}

Alternatively, you can implement the effect using Tailwind CSS only by following these steps:

  1. Update your Tailwind configuration as shown below:
module.exports = {
  theme: {
    extend: {
      animation: {
        typewriter: 'typewriter 2s steps(11) forwards',
        caret: 'typewriter 2s steps(11) forwards, blink 1s steps(11) infinite 2s',
      },
      keyframes: {
        typewriter: {
          to: {
            left: '100%',
          },
        },
        blink: {
          '0%': {
            opacity: '0',
          },
          '0.1%': {
            opacity: '1',
          },
          '50%': {
            opacity: '1',
          },
          '50.1%': {
            opacity: '0',
          },
          '100%': {
            opacity: '0',
          },
        },
      },
    },
  },
  plugins: [],
}

Now, apply the typewriter effect like this:

<h2 class="relative w-[max-content] font-sans before:absolute before:inset-0 before:animate-typewriter before:bg-white after:absolute after:inset-0 after:w-[0.125em] after:animate-caret after:bg-black">Greetings</h2>

Feel free to check out a Live Demo of the effect.

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

Rotate the mat-select arrow when the dropdown opens (moving in both upward and downward directions)

Currently, I have a mat-select dropdown icon arrow that toggles facing up or down based on user clicks. However, after selecting an option and closing the dropdown, the arrow remains in the upward position unless further clicked and held. I have attempted ...

Content escapes its parent container and seamlessly transitions to the following element

I am facing an issue with the layout of my element, which includes an image and text centered inside a parent container. Whenever I try adding more elements below the existing image and text, the green text with a red border overflows the current parent . ...

Creating an intricate table layout using AngularJS and the ngRepeat directive

I'm attempting to create a table similar to the one shown in the image below using HTML5. In this table, there is a multi-dimensional matrix with Class A and Class B highlighted in yellow. Each class has three modes (highlighted in blue), and each mo ...

Achieving equal height for the inner div in Flexbox to match the height of its parent

I am currently using flexbox to structure a web application. While it is functioning as expected for most parts, I am encountering an issue with the main content area. The "router-view" element has the desired full height, but the nested div inside of it d ...

Increase the options available in the dropdown menu by adding more selected items, without removing any already selected

I came across this code on the internet http://jsfiddle.net/bvotcode/owhq5jat/ When I select a new item, the old item is replaced by the new item. How can I add more items without replacing them when I click "dropdown list"? Thank you <select id=&qu ...

In order to utilize Next.js with pkg, you must enable one of the specified parser plugins: 'flow' or 'typescript'

Utilizing next.js with the pkg in my project, following the steps outlined in this tutorial, I encountered an error when running the pkg command: > Error! This experimental syntax requires enabling one of the following parser plugin(s): 'flow, t ...

Tips for altering the color of an image using CSS attributes

I am looking to create a male Head component in this design draft and modify the CSS according to the skin prop. I have attempted to use filter and mix-blend-mode properties, but have not found a solution yet. Any guidance on how to achieve this would be ...

How can I apply bold styling to my interpolation binding in Angular while working on my HTML code?

Below is the code snippet where I am attempting to highlight profile.userId: <p class="profile__last-login" *ngIf="profile.lastLoggedIn"> {{'intranet.profile.dashboard.lastLoggedIn' | messageBundle: profile.userId + ',' + (pr ...

Can you help me modify the navbar color in Bootstrap 4 based on the screen width?

For example, if I use the navbar-dark and bg-dark classes in a nav tag, I want to switch them to navbar-light and bg-light when the screen width is changed to approximately 600px (using Bootstrap 4). ...

"Recently, I included a function called 'test' in the code, but I encountered an error stating that it was not recognized as a function. Can someone provide assistance

Issue Detected A 'TypeError' has been thrown: ".goal_test".click is not defined as a function Feel free to collaborate on the code by clicking this link: Please note that my modified code is enclosed within asterisk symbols. ...

[next-auth][error][client_fetch_error] NextAuthJS CredentialsProvider "providers SyntaxError: Invalid JSON format at position 0"

When I first started using Next.js, I discovered NextAuthJS as a way to implement custom email and password authentication. I decided to go with the Credentials Provider and set it up as shown below: import NextAuth from "next-auth"; import Crede ...

Instructions for adjusting the size of my modal window when the keyboard appears?

While developing a next.js app, I encountered an issue with the chat modal. When the input field is in focus, I want to resize the modal height so that the keyboard popup does not hide the input field. I attempted to modify the DOM but could not get it to ...

How can I implement a SWR refresh from a button click in a child component using a callback function?

I am currently working on a shopping cart component in Next.js and facing an issue with refreshing the cart data after making updates. My cart component is a function as per the recommendations in the Next.js documentation (https://nextjs.org/docs/basic-fe ...

Facing Issue with NextJS 13 App: Images Fail to Load When Accessed via GitHub Pages Route

Attempting to host a basic NextJS 13 website on GitHub pages has revealed some strange behavior that appears to only affect Safari users (both iOS and MacOS). Upon initial loading, the images appear correctly. However, as I navigate between routes, I enco ...

Tips for preloading a script in nextjs

I'm having trouble incorporating a script into my website. The issue is that the script doesn't load properly the first time the page loads, but after a few refreshes, it works and the responsible iFrame shows up. I've attempted several di ...

Looking for CSS properties to personalize a dropdown list in an HTML select element

After spending several days scouring the internet and trying out numerous methods, I have yet to find a satisfying way to create my own dropdown list. Using CSS, I am able to customize the text color (A), the border style and color (B) of the dropdown fie ...

Angular 10 is displaying a message indicating that a font has not been

I'm facing an error in my Angular project when trying to add a font to the SCSS file. How can I resolve this issue? style.scss: @import "~@angular/material/theming"; @include mat-core(); $PWP-primary: mat-palette($mat-indigo); $PWP-accent: ...

Strange behavior observed while attempting to create a smooth CSS transition effect from the right side

Is there a way to create a hover effect in my navbar where a line appears from the bottom left and top right, without causing any size or alignment issues with the links? * { margin : 0; padding: 0; } nav{ background-color: black; width: 1200px; he ...

The animated image gracefully glides down the webpage accompanied by an h3

How can I align an image and h3 tag side by side without the image sliding down? <img src="..." alt="..." /><h3>Shopping Cart</h3> I need them to be next to each other but the image keeps moving down. Any suggestions on how to fix this? ...

What is the best way to align the main text to the far left in a Bootstrap 4 cover template?

I am struggling to align the text to the far left of the page instead of it being centered. "Cover your page. Cover is a one-page template for creating elegant and uncomplicated home pages. Customize it by downloading, modifying the text, and inserti ...