Taha

How to Create Text-fill Animation with CSS

In this article, I'll show you how to create a text-fill animation on hover using pure CSS. You can test what we are going to build from the preview section on the right (or below if you're on mobile).

The main idea of this animation is creating two versions of the same text: one that animates and one that doesn't. We display the animating version on the top of the static one. When the user hovers over the text, we initiate the animation of the top layer. The animation is basically changing the width from 0 to 100%.

Let's see how to implement this in code.

1. Create the text element

Let's start by creating the text element.

<h1 class="text">
  Text
</h1>

In the CSS, we need to specify its size and color, and most importantly, set postion to relative—you will see why later.

.text {
  position: relative;
  font-size: 20px;
  font-weight: bold;
  color: #111;
  margin: 0;
  padding: 0;
  line-height: 1;
}

2. Create a clone of the text

Instead of creating the element in HTML, we can use the ::before psuedo-element in CSS. With CSS psudeo-elements, we can access data from the HTML using attr().

So, first, let's add the same text to a data attribute, like this:

<h1 class="text" data-text="text">
  Text
</h1>

Now, let's create the ::before element.

.text::before {
  content: attr(data-text);
  position: absolute;
  z-index: 1;
  color: #0ea5e9;
  pointer-events: none;
}

Notice how we needed to set its position to absolute to display it on top of the original text (that's why we needed to set position to relative on .text).

3. Setting ::before width to 0

Now, the psuedo-element is filling the whole text area. But in the idle state, it should be hidden. Since we are going to animate its width, let's hide it by setting its width to 0. And for that to work, we also need to set its overflow to hidden.

.text::before {
  content: attr(data-text);
  position: absolute;
  z-index: 1;
  color: #0ea5e9;
  pointer-events: none;

  width: 0;
  overflow: hidden;
}

4. Set ::before back to full width on hover

Our last step is to make the ::before element fill the whole area when its parent is hovered. To make it animatable, we need to define a transition for the width property.

.text::before {
  content: attr(data-text);
  position: absolute;
  z-index: 1;
  color: #0ea5e9;
  pointer-events: none;
  width: 0;
  overflow: hidden;

  transition: 0.4s ease-out width;
}

.text:hover::before {
  width: 100%;
}
Taha Shashtari

I'm Taha Shashtari, a full-stack web developer. Building for the web is my passion. Teaching people how to do that is what I like the most. I like to explore new techniques and tools to help me and others write better code.

Subscribe to get latest updates about my work
©2024 Taha Shashtari. All rights reserved.