53

I am using css to make an underline come under a span:

CSS:

.un{
    text-decoration:none;
    transition: all .5s ease-in;
}
.un:hover{
    text-decoration:underline;
}  

HTML:

<span class="un"> Underlined Text - Or to be underlined </span>

The underline simply appears, it doesn't move in over .5 seconds, like the transition should apply. Why not? How can I make this work?

Dharma
  • 3,007
  • 3
  • 23
  • 38
yaakov
  • 4,568
  • 4
  • 27
  • 51
  • Hi yak613, have you tried this on multiple browsers? Some browsers such as old versions of IE do not allow for transitions. –  May 20 '15 at 14:24
  • Getting the code right is probably a better idea than blaming older versions. The transition of the text-decoration property is the problem at hand here, even for modern browsers. [Transition support](http://caniuse.com/#feat=css-transitions) is pretty established by now. – Lave Loos May 20 '15 at 15:30

11 Answers11

84

Updated for 2021:

The support for text-decoration-color has come a long way, and common browser support requirements have loosened making it a viable option for most new projects. If you are only seeking a color transition, and can do without IE support, see this answer below.


Original answer:

You cannot change the color of the text-decoration independent of the color. However, you can achieve a similar effect with pseudo elements:

.un {
  display: inline-block;
}

.un::after {
  content: '';
  width: 0px;
  height: 1px;
  display: block;
  background: black;
  transition: 300ms;
}

.un:hover::after {
  width: 100%;
}
<span class="un">Underlined Text - Or to be underlined</span>

That is the most customizable way to do it, you can get all sorts of transitions. (Try playing around with the margins/alignment. You can make some awesome effects without adding to your HTML)
But if you just want a simple underline, use a border:

.un {
  transition: 300ms;
  border-bottom: 1px solid transparent;
}

.un:hover {
  border-color: black;
}
<span class="un"> Underlined Text - Or to be underlined </span>
Jacob G
  • 13,762
  • 3
  • 47
  • 67
41

A proper solution that will work with multiple line text and doesn't require border-bottom mockup should look like this. It utilizes text-decoration-color property.

Have in mind that it's not supported by old browsers

.underlined-text{
 text-decoration: underline;
 text-decoration-color: transparent;
 transition: 1s;

 /*add those for opera and mozilla support*/
 -webkit-text-decoration-color: transparent;
 -moz-text-decoration-color: transparent;
}

.underlined-text:hover{
 text-decoration-color: red;
 
 /*add those for opera and mozilla support*/
 -webkit-text-decoration-color: red;
 -moz-text-decoration-color: red;
}
<span class="underlined-text">You're the greatest thing that has ever been or ever will be. You're special. You're so very special. It is a lot of fun. You don't want to kill all your dark areas they are very important. In your world you can create anything you desire.</span>
karoluS
  • 2,980
  • 2
  • 23
  • 44
  • 2
    This is a better approach than the accepted answer, and I don't see a problem with its browser support. – Shahriar Oct 18 '22 at 09:10
15

I had a similar issue with a tags and I figured it out.

The reason it's not animating is because you cannot transition from a text-decoration: none value.

In my case, what I did was set text-decoration-color to transparent and then, on :hover, set the text-decoration-color to the color value I wanted.

In your particular case, you would have to specifiy text-decoration: underline transparent since span tags have an initial text-decoration value of none. Then, on :hover, specify the text-decoration-color that you want.

FWIW, text-decoration and text-decoration-color are animatable properties, according to MDN.

References:

user2046
  • 151
  • 1
  • 3
7

The answer of @Jacob is pretty neat. But I accidentally found a solution no one have provided:

.un {
  transition: .4s;
}

.un:hover {
  box-shadow: 0 3px 0 #7f7f7f;
}
<span class="un"> Underlined Text - Or to be underlined </span>

Use box-shadow with no blur can achieve underline effects even more tricky and special.
This can make your page run slower if you use a lot of it.

Webdeveloper_Jelle
  • 2,868
  • 4
  • 29
  • 55
ldm0
  • 71
  • 2
  • 4
3

You can use border-bottom instead, like so:

.un{
    border-bottom: 1px solid transparent;    
    transition: all .5s ease-in;
}
.un:hover{
    border-bottom: 1px solid black;    
}
<span class="un"> Underlined Text - Or to be underlined </span>
jaunt
  • 4,978
  • 4
  • 33
  • 54
2

Here is a workaround to add fade animation to the underline property:

.un{
    text-decoration: underline;
    text-decoration-color: #0000;
    transition: .2s;
}
.un:hover{
    text-decoration-color: #000;
} 
JulienRioux
  • 2,853
  • 2
  • 24
  • 37
1

Because text-decoration is an all-or-nothing property, you’ll probably want to try using a border-bottom instead. This is how I’ve done it previously:

.un {
    border-bottom: 1px solid transparent;
    transition: border-color 0.5s ease-in;
}
.un:hover {
    border-color: black; /* use whatever color matches your text */
}
Text that is <span class="un">wrapped in the “un” class</span> has a border-bottom that appears as an underline that fades in.

Applying the transition to the border color change from transparent to your text color should give the appearance of a “fade in” from no underline to underline.

Joel Farris
  • 510
  • 1
  • 6
  • 23
1

If you want an underline with increasing width like below, you can use background-image instead.

.un {
  display: inline;
  background-image: linear-gradient(#e876f5, #e876f5);
  /*                   ↓ height of underline  */
  background-size: 0% 2px;
  /*                        ↓ y position of underline. you can change as 50% to see it. */
  background-position: 0% 100%;
  background-repeat: no-repeat;
  transition: background 0.3s linear;
}

.un:hover {
  background-size: 100% 2px;
}
<span class="un">hover me</span>
doğukan
  • 23,073
  • 13
  • 57
  • 69
1

I found this solution to work best, clean and simple. The transition works once you specify a color.

@ref: https://www.w3schools.com/cssref/css3_pr_text-decoration-line.asp

a {
    color: #222;
    -webkit-text-decoration: none transparent;
            text-decoration: none transparent;
    -webkit-transition: all 0.2s ease-in-out;
            transition: all 0.2s ease-in-out;
}

a:focus,
a:hover {
    color: #222;
    -webkit-text-decoration: underline #222;
            text-decoration: underline #222;
}
James Mitchell
  • 123
  • 1
  • 4
0

This is how I moved the border up closer.

<style type="text/css">
a {
    text-decoration: none;
    border-bottom: solid 1px transparent;
    font-weight: 600;
    color: rgb(126,93,142);
    -webkit-transition: all .5s;
    transition: all .5s;
    display: inline-block;
    line-height: 1em;
}
a:hover {
    text-decoration: none;
    border-bottom: solid 1px;
    color: #ce40ce;
    display: inline-block;
    line-height: 1em;
}</style>

<a href="#">La La La</a>
Sonobor
  • 301
  • 3
  • 3
0

This can be accomplished by animating the text-decoration-color property.

Tested in Chrome, Firefox, and Safari.

.un {
  text-decoration: underline;
  text-decoration-color: transparent;
  transition: text-decoration-color 1s;
}

.un:hover {
  text-decoration-color: currentcolor;
}
<span class="un">Underlined Text - Or to be underlined</span>

(This is possible now that IE has reached EOL.)

Paul Draper
  • 78,542
  • 46
  • 206
  • 285