Text underline animation in CSS - the simplest way?

Viewed 462

I'm having an animated underline effect when user points the links on my website. The underline is a bit wider than the text itself, as there's a bit of horizontal padding.

Here's the effect I wanted to achieve and I did:

Underline animation

I was thinking if it was possible to simplify my code. After some trial and error, I used negative margin-left on the underline element and calc() to calculate its width as 100% + 2 * padding. It looks to me like an overcomplicated solution. Can the same effect be achieved without calc() and, perhaps, without negative margin?

Of note, adding a wrapper element is not an option. It needs to be a plain <a> element.

:root {
    --link-color: #f80;
    --link-underline-padding: .5em;
}

a {
    color: var(--link-color);
    display: inline-block;
    padding: 0 var(--link-underline-padding);
    text-decoration: none;
}

a:after {
    background-color: var(--link-color);
    content: '';
    display: block;
    height: .1em;
    margin-left: calc(var(--link-underline-padding) * -1);
    margin-top: .2em;
    transition: width .5s;
    width: 0;
}

a:hover:after {
    width: calc(100% + var(--link-underline-padding) * 2);
}
I find <a href="#">dogs</a> pretty cool.

2 Answers

If you set a to position: relative; you can then use position: absolute; and left: 0px; to push it past the padding and then just use width: 100% to have it extend the entire length.

:root {
    --link-color: #f80;
    --link-underline-padding: .5em;
}

a {
    position: relative;
    color: var(--link-color);
    display: inline-block;
    padding: 0px var(--link-underline-padding);
    text-decoration: none;
}

a:after {
    position: absolute;
    left: 0px;
    background-color: var(--link-color);
    content: '';
    display: block;
    height: .1em;
    margin-top: .2em;
    transition: width .5s;
    width: 0;
}

a:hover:after {
    width: 100%;
}
I find <a href="#">dogs</a> pretty cool.

Related