First, how can I create the following effect using pure CSS?

You can take a moment before reading on. Try to think about the above effect or start to try, without the help of JS, can clever to achieve the above effect.

OK, go ahead. This effect is a similar small problem I encountered in the process of business development. In fact, even if I had to use Javascript, my first reaction was that it was a hassle. So I’ve been wondering, is it possible to do this with just CSS?

Define requirements

Let’s define a simple rule that requires the following:

  • Suppose the HTML structure looks like this:
<ul>
  <li>Incredible CSS</li>
  <li>The navigation bar</li>
  <li>The cursor little underscore follows</li>
  <li>PURE CSS</li>
  <li>Nav Underline</li>
</ul>
Copy the code
  • NavigationalliThe width of is not fixed
  • When from the navigation to the leftliMove to the rightli, the underscore moves from left to right. Similarly, when from the right side of the navigationliMove to the leftli, the underscore moves from right to left.

Implementation requirements

At first glance, it feels like this follow animation is not possible with CSS alone.

If you want to do it in CSS only, you’ll have to go the other way, and use some clever methods.

Ok, so let’s do this step by step using some CSS tricks. Analyze the difficult points:

Width variable

The first difficulty is that the width of Li is not fixed. So, we might need to play with the width of Li itself.

Since the width of each li is not necessarily the same, the length of the underscore it corresponds to must be the same as it is. Naturally, we would want to use its border-bottom.

li {
    border-bottom: 2px solid # 000;
}
Copy the code

So, maybe now it looks like this (the Li’s are connected together, and the gap between the Li’s is created using padding) :

Default hidden, animation effects

Of course, there are no underscores to begin with, so we might want to hide them.

li {
    border-bottom: 0px solid # 000;
}
Copy the code

Overthrow and start over, with pseudo-elements

This does not seem to work, because after hiding, hover Li, need to underline animation, and Li itself is certainly not moving. So, let’s consider using pseudo-elements. Apply an underscore to each of the pseudoelements of LI.

li::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border-bottom: 2px solid # 000;
}
Copy the code

Let’s consider the first animation, hover, where the underscore moves from one side. So, we use absolute positioning, set the width of li pseudo-element to 0, in hover when the width from width: 0 -> width: 100%, CSS as follows:

li::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 0;
    height: 100%;
    border-bottom: 2px solid # 000;
}

li:hover::before {
    width: 100%;
}
Copy the code

To obtain the following effect:

Left to left, right to right

OK, it feels like a step closer. Now there’s the hardest question of all:

How to make the line follow the movement of the cursor, so that when the left li moves to the right li, the underline moves from left to right. Similarly, as you move from the right li to the left li of the navigation, the underscore moves from right to left.

Let’s take a closer look at what it looks like now:

When switching from the first li to the second li, the direction of the first li underscore retraction is incorrect. Therefore, we need to shift the initial position of the underscore to left: 100%, so that the first li is correct every time the underscore is retracted:

li::before {
    content: "";
    position: absolute;
    top: 0;
    left: 100%;
    width: 0;
    height: 100%;
    border-bottom: 2px solid # 000;
}

li:hover::before {
    left: 0;
    width: 100%;
}
Copy the code

Look at the effect:

Well, if you look closely at the two pictures, the second effect is that you’re picking seeds and losing melons. The first li is moving in the right direction, but the second li is moving in the wrong direction.

The magic ~ selector

So, we urgently need a method, can not change the current hover li underline movement but can change its next Li underline movement (good wound mouth).

That’s right. We can use that here~Selectors, doing this very difficult task, is the most important part of this example.

For the current hover li, the underline of its corresponding pseudo-element is left: 100%, while for li:hover ~ li::before, their positioning is left: 0. The CSS code looks like this:

li::before {
    content: "";
    position: absolute;
    top: 0;
    left: 100%;
    width: 0;
    height: 100%;
    border-bottom: 2px solid # 000;
    transition: 0.2 s all linear;
}

li:hover::before {
    width: 100%;
    left: 0;
}

li:hover ~ li::before {
    left: 0;
}
Copy the code

At this point, we want to achieve the effect of pull! And flowers. Take a look at:

It works fine, but it’s a little stiff. We can change the easing function and add an animation delay to achieve the same effect as above. All the icing on the cake, of course.

The full DEMO can be poked here: CodePen DEMO – incredible CSS cursor underscore following effect

The last

The biggest flaw of this method is that when entering the first Li at the beginning, the line can only be from right to left. In addition, the following effect can be achieved well.

More exciting CSS technical articles are summarized in my Github – iCSS, continue to update, welcome to click the star subscription favorites.

Ok, this article is over, hope to help you 🙂

If there are any questions or suggestions, you can communicate more, original article, writing style is limited, talent is shallow, if there is something wrong in the article, hope to inform.