DEV Community

Cover image for Create text change hover effect with JavaScript
Ramo Mujagic
Ramo Mujagic

Posted on • Originally published at ramomujagic.com

 

Create text change hover effect with JavaScript

I stumbled upon one website that had this hover effect where the original text would change to some random characters and start revealing itself over time.

It looked like a fun exercise, so I decided to recreate it. Below you can see how it looks and check out the source code as well. This is a beginner-friendly article and includes a step-by-step guide. If you completely understand the source code, feel free to skip reading so you do not waste your time.

In case you decided to continue reading, you might be interested in what we are going to cover here. We will start with a basic HTML structure and mention some CSS styles. However, the main focus will be on JavaScript. You can learn how to listen for and handle events, a little bit of string manipulation, and how to leverage the power of closure. If you are ready, let's get started.

HTML structure

As for any hover effect, you need to have something that you want to hover over. In this case, let's create a couple of links using <a> tag and put them into a body tag, just for demonstration purposes.

<body>
  <a class="text-hover-effect" href="#">pricing</a>
  <a class="text-hover-effect" href="#">projects</a>
  <a class="text-hover-effect" href="#">about us</a>
  <a class="text-hover-effect" href="#">subscribe!</a>
</body>
Enter fullscreen mode Exit fullscreen mode

Notice that every <a> tag has a class attribute with a value of text-hover-effect. We will need it later so we can target those HTML elements with JavaScript.

CSS styles

Since the HTML structure is ready, let's add some styles. In this case, I only want to do some simple things, like changing the background color and making sure that links are centered on the page. We can also add styles to links so they look a bit nicer.

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background-color: #18122b;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  flex: 1;
  height: 100vh;
}

a {
  font-family: sans-serif;
  color: #635985;
  text-transform: uppercase;
  letter-spacing: 0.1rem;
  font-size: 2.6rem;
  font-weight: bold;
  box-shadow: 0 0 2rem 1rem rgba(0, 0, 0, 0.2);
  background: transparent;
  padding: 0.6rem;
  border-radius: 0.4rem;
  min-width: 370px;
  border: 1px solid #635985;
  text-decoration: none;
  display: block;
  margin-bottom: 2rem;
}
Enter fullscreen mode Exit fullscreen mode

I will not go into details about what every CSS declaration does, you can always play around with them in the sample project. However, I want to bring your attention to one thing.

Even though we added some CSS, it is actually not required. Notice that there is not even a :hover pseudo-class. This is because the hover effect will be handled entirely by JavaScript.

Understanding the effect

To implement the desired effect and behavior, we first need to understand it. Take a look at the following image.

Illustration of required actions to reproduce the hover effect

In the default state, the original text is visible. When the cursor hovers over the text, it will immediately be populated with random characters. Only the first character from the original text should remain the same.

After some artificial delay, the character in the second position from the original text will replace the randomly generated character in the same position. This delay and replace process will continue until the last character is reached and the original text is completely revealed.

I hope this was clear enough for you to understand what we are trying to create here. If not, do not worry; we will split it into manageable chunks and cover every chunk separately.

JavaScript code

This is the part where we will spend the most time. First of all, we need to somehow generate random characters for our effect. We can do that by creating a simple array of characters.

// 🔡 Characters to cycle trough
let allowedCharacters = ['X', '$', 'Y', '#', '?', '*', '0', '1', '+'];
Enter fullscreen mode Exit fullscreen mode

The variable allowedCharacters holds a list of the allowed characters. Feel free to add or remove them from your version.

We also need a function that can randomly select one of the characters from the previously created list.

// 🎁 Function to return random character
function getRandomCharacter() {
  const randomIndex = Math.floor(Math.random() * allowedCharacters.length);
  return allowedCharacters[randomIndex];
}
Enter fullscreen mode Exit fullscreen mode

Function getRandomCharacter uses Math object to randomly generate a number, index, between 0 and the length of the allowedCharacters array. The generated index is then used to get the character from the allowedCharacters.

To handle hover events, we need to get all <a> tags and attach event listeners to all of them.

// 🛠 Event handler
function handleHoverEvent(e) {
  // TODO: Add implementation
}

// Attach an event listener to elements
document.querySelectorAll('.text-hover-effect').forEach((element) => {
  element.addEventListener('mouseover', handleHoverEvent);
});
Enter fullscreen mode Exit fullscreen mode

Here, document.querySelectorAll is used to get all elements that have a value of text-hover-effect in the class attribute. Since we only added this class to <a> tags, it will return the iterable collection of Anchor, <a>, elements.

Using addEventListener, we can add mouseover event listener to every element and pass the function handleHoverEvent to handle the events. Now, whenever a user hovers over any of <a> tags, handleHoverEvent function will be executed.

So far, so good. The groundwork is complete; it's time to work on the hover effect implementation now. As we already said, we will split the task into multiple chunks. For the beginning, let's focus on the following part:

First step of the hover effect

On hover, we have to replace the original text, except for the first character, with a randomly generated one.

When an event is triggered, the handleHoverEvent function gets called and an Event-based object will be passed as an argument to the function.

function handleHoverEvent(e) {
  const text = e.target.innerHTML;
  const randomizedText = text.split('').map(getRandomCharacter).join('');

  e.target.innerHTML = `${text.substring(0,1)}${randomizedText.substring(1)}`;
}
Enter fullscreen mode Exit fullscreen mode

The function will receive the e, the event object, when the event is triggered. First, we have to save the current text value from the <a> tag that was hovered. To do so, we can use e.target.innerHTML and save the value into the text variable.

Keep in mind that innerHTML gets or sets the HTML markup contained within the element. If your hovered element has other HTML tags as children, they will be serialized and returned as well.

Next, we need to generate randomized text with the same length as the original. This is where we can use the getRandomCharacter function that was created before.

The value saved in the text variable is a string that includes multiple characters. But getRandomCharacter generates only one character per call. To solve this problem, we can convert the original text into an array of characters using the split('') method.

Now that we have an array, we can chain the map method and pass the getRandomCharacter function to it. Now, for every original character, a random one will be generated. Finally, to convert the resulting array back to a string, the join('') method is used.

Generate random characters from the original text

The "subscribe" string is used as an example to illustrate how the text is being processed. You can see that at the end, we have randomly generated text that is the same length as the original one.

Good, we now have two strings, one original and one randomly generated. The last step is to combine them and update the e.target.innerHTML property. To get the first character from the original text, we can use text.substring(0,1) and to get the rest of the characters from the randomized text, we can use randomizedText.substring(1).

Combine substrings into the final string