Reprinted: China first all graphics son github.com/chokcoco

First, how to use pure CSS to create the following effect?

Take a moment before you read on. Try to think about the above effect or try to do it, without using JS, can skillfully 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 use Javascript, my first reaction is, it’s a hassle. So I’ve been thinking, is it possible to do this with just CSS?

Define requirements

Let’s define a simple rule as follows:

  • Suppose the HTML structure is as follows:
< ul > < li > unbelievable CSS < / li > < li > navigation bar < / li > < li > cursor little underscore followed < / li > < li > PURE CSS < / li > < li > Nav Underline < / li > < / ul >Copy the code
  • Navigation columnliThe width of is not fixed
  • When from the left side of the navigationliMove to the rightliThe underline moves from left to right. Similarly, when you go from the right side of the navigationliMove to the leftliThe underline moves from right to left.

Implementation requirements

When I first saw this effect, I felt that it was impossible to do it with CSS alone.

If you want to implement only CSS, you have to go the other way and use some clever methods.

Ok, let’s do this step by step using CSS with some clever tricks. Analyze the difficulties:

Unfixed width

The first difficulty is that the width of Li is not fixed. Therefore, we may need to work from the width of Li itself.

Since the width of each li is uncertain, the length of its corresponding underline must be appropriate to its own. Naturally, we would think to use its border-bottom.

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

So, maybe now it looks like this (li are joined together, li gaps are created using padding) :

Default hidden, animated effect

Of course, none of these are underlined at first, so we might want to hide them.

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

Overturn and start again, with the aid of false elements

This doesn’t seem to work, because when you hover Li after hiding it, you need an underline animation, and li itself definitely can’t move. So, let’s think about pseudo-elements. Apply an underscore to each pseudo-element of Li.

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

Consider the first animation, hover, the underline should expand from the side motion. So, we use absolute positioning, set the width of li pseudo-element to 0, and hover, width: 0 -> width: 100%, CSS as follows:

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

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

The result is as follows:

Left out, right out, right out

OK, that feels like a step closer to success. That leaves the hardest question:

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

Let’s take a closer look at the effect now:

When switching from the first li to the second li, the first Li underscore is withdrawn in the wrong direction. So, we need to shift the initial position of the underline to left: 100%, so that every time the underline is withdrawn, the first li is correct:

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

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

Look at the results:

Well, comparing the two images carefully, the second effect is penny wise and pound foolish. The first li is moving in the right direction, but the second Li is moving in the wrong direction.

Magic ~ selector

Therefore, we urgently need a way to change the way the current hover li’s underline moves without changing the way its next li’s underline moves (tricky).

That’s right. We can use it here~Selectors, doing the hard work, is the most important part of this example.

For the current hover li, the position of the underline corresponding to the pseudo-element is left: 100%, and for li:hover ~ li::before, they are left: 0. The CSS code looks like this:

li::before {
    content: "";
    position: absolute;
    top: 0;
    left: 100%;
    width: 0;
    height: 100%;
    border-bottom: 2pxsolid# 000;The transition: 0.2 salllinear; } li:hover::before { width: 100%; left: 0; } li:hover~li::before { left: 0; }Copy the code

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

The effect is good, but a little stiff, we can change the easing function and add an animation delay to achieve the above effect. Of course, these are the icing on the cake.

The full DEMO can be stamped here: CodePen — DEMO

The last

The biggest flaw of this method is that at the beginning of entering the first LI, the lines can only be from right to left. Otherwise, the following effect can be well realized.

I haven’t updated it for a long time. Recently, I am obsessed with learning blockchain-related technologies, such as ethereum programming and writing smart contracts. Behind will still put more energy in the line, more than some front-end articles, the charm of CSS or can not resist.

More interesting CSS technology articles are summarized in my Github — iCSS, constantly updated, welcome to click on the star subscription favorites.

Well, the end of this article, I hope to help you 🙂

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