63

Is there a way to control the position of the underline in text-decoration: underline?

<a href="#">Example link</a>

The example above has an underline by default...is there a way to nudge that underline down by a few pixels so that there is more space between the text and the underline?

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
redconservatory
  • 21,438
  • 40
  • 120
  • 189

9 Answers9

89

2020

Use text-underline-offset!

2012

The only way to do that is to use a border instead of an underline. Underlines are notoriously inflexible.

a {
    border-bottom: 1px solid currentColor; /* Or whatever color you want */
    text-decoration: none;
}

Here's a demo. If that's not enough space, you can easily add more — if it's too much, that's a little less convenient.

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • 5
    Its worth noting that `border` does not wrap like `underline` does. – Blowsie Sep 23 '14 at 13:22
  • 8
    @Blowsie: It does on `inline` elements; try resizing the frame in the fiddle. – Ry- Sep 23 '14 at 17:30
  • Note that it does underline :before and :after as well. – Mathijs Segers Nov 30 '15 at 20:00
  • It's the easiest solution in most cases, but doesn't work when you want a big `line-height` to have a big click target (in a menu for example) but don't want to push the "underline" (border) as far below. Then, the `text-underline-position` or `:after` solutions work best. – Yann Dìnendal Jul 31 '18 at 14:47
  • 1
    @YannDìnendal: I’m not sure how `text-underline-position` could work at all, given that it’s about which side of the text the underline appears on… but yes, if you have a single line of text you can use `::after`. A solution that allows both line breaks and a big click target at the expense of maybe needing more markup is to put the underlined text in a vertically-centred wrapper. – Ry- Apr 05 '19 at 12:43
  • Right. About `text-underline-position` , it doesn't allow specifying a number of pixels, but it's not just about the side. `under` puts it below the letters descenders, which is not the same as the default `auto` that puts it on the baseline: https://www.w3.org/TR/css-text-decor-3/#text-underline-position-property – Yann Dìnendal Apr 05 '19 at 22:04
24

You can use pseudo before and after like this. It works well and is completely customizable.

CSS

p {
  line-height: 1.6; 
}
.underline {
   text-decoration: none; 
   position: relative; 
 }   

.underline:after {
    position: absolute;
    height: 1px;
    margin: 0 auto;
    content: '';
    left: 0;
    right: 0;
    width: 90%;
    color: #000;
    background-color: red;
    left: 0;
    bottom: -3px; /* adjust this to move up and down. you may have to adjust the line height of the paragraph if you move it down a lot. */
}

HTML

<p>This is some example text. From this page, you can <a href="#">read more example text</a>, or you can <a href="#" class="underline">visit the bookshop</a> to read example text later.</p>


Here's a more advanced demo with a screenshot attached I made that animates the underline on hovering, changes colors, etc...

http://codepen.io/bootstrapped/details/yJqbPa/

underline css

Bryan Willis
  • 3,552
  • 1
  • 25
  • 34
  • This ain't work if you need, for example, the whole

    element underlined and white-space:wrap enabled

    – Vitali Protosovitski May 04 '17 at 16:34
  • This also won't work if your anchor link spans more than a single line, even by itself without other content around it. Thanks for the alternative idea though. – Ben Sewards Aug 16 '17 at 22:43
  • I am using this for header underline animation with fewer modifications by using responsive css units. – mimi Apr 12 '19 at 13:55
  • Also won't work if your text needs to have a lot of padding and you can't put additional html element to wrap your text with. Just something to think of. – trainoasis Dec 03 '19 at 10:04
16

There is the proposed text-underline-position property in CSS 3, but it seems that it has not been implemented in any browser yet.

So you would need to use the workaround of suppressing the underline and adding a bottom border, as suggested in other answers.

Note the the underline does not add to the total height of an element but bottom border does. In some situations, you might wish to use outline-bottom – which does not add to the total height – instead (though it is not as widely supported as border-bottom).

Jukka K. Korpela
  • 195,524
  • 37
  • 270
  • 390
  • 2
    That would only allow putting the line on another side, but not changing the distance between the text and the line. – ygoe Dec 21 '15 at 22:22
12

2021

There is the text-underline-offset property in CSS Text Decoration Module Level 4 which allows you to move the decoration by a specified distance away from its original position.

Supported in Safari 12.1+, Firefox 70+ and Chrome 87+ (released 2020-11-17).

text-underline-offset property accepts these values:

  • auto - default, makes the browser choose the appropriate offset.
  • from-font - if the used font specifies a preferred offset, use that, otherwise it falls back to auto.
  • <length> - specify distance in the "usual" CSS length units. Use em to allow scaling proportionally with the font-size.

Example below:

p {
  text-decoration: underline;
  text-decoration-color: red;
  margin-bottom: 1.5em;
}

p.test {
  position: relative;
}

p.test::after {
  position: absolute;
  content: '';
  display: block;
  height: 1px;
  width: 100%;
  background: blue;
  bottom: 0;
}
<p style="text-underline-offset: 0.75em;" class="test">
  If you see our red underline <strong>below</strong> the blue line, this property works in your browser.
</p>

<p style="text-underline-offset: auto">
  And now let’s try it with `text-underline-offset` set to `auto`.
</p>

<p style="text-underline-offset: from-font">
  With `text-underline-offset` set to `from-font`, it probably looks the same as above.
</p>
ericek111
  • 575
  • 7
  • 15
8

2023

You can use text-underline-position: under;

a {
  text-decoration: underline;
  text-underline-position: under;
}
<h1>
  <a href="#">My link</a>
</h1>
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Dory Daniel
  • 798
  • 14
  • 21
4

There is one property text-underline-position: under. But only supported in Chrome and IE 10+.

More info: https://css-tricks.com/almanac/properties/t/text-underline-position/ https://developer.mozilla.org/en-US/docs/Web/CSS/text-underline-position

Jinu Kurian
  • 9,128
  • 3
  • 27
  • 35
3

Using border-bottom-width and border-bottom-style will make the border the same color of the text by default:

text-decoration: none;
border-bottom-width: 1px;
border-bottom-style: solid;
padding-bottom: 1px;
Dorian
  • 22,759
  • 8
  • 120
  • 116
3

Use a border-bottom instead of the underline

a{    
    border-bottom: 1px solid #000;
    padding-bottom: 2px;
}

Change padding-bottom to adjust the space

Julien
  • 3,509
  • 20
  • 35
0

I would use border instead. Easier to control that.

mikevoermans
  • 3,967
  • 22
  • 27