Styling underlines with CSS
If you’re not underlining your links, you should be. There’re a couple of ways to underline links;
text-decoration: underline is the most obvious as that’s how links are styled by default, and
border-bottom offers us a bit more flexibility. Using borders, it’s possible to specify the thickness, style and colour, but did you know it’s now possible to do that with
Why bother though, if it’s working for us already with borders? Well,
text-decoration: underline is better typographically as the underlines sit nicely on the baseline of words, passing through descenders (the bits of letters that go below the baseline in letters like
border-bottom underlines sit under the descenders, which means there’s too much distance between the words and their underline when.
Not only that, but browsers now detect descenders and the
text-decoration underline neatly skips them by default. This can be undone with
text-decoration-skip on Safari), but I can’t see what that would gain, which is why it’s ‘on’ by default.
So how do we get that visual flair with
text-decoration: underline that we’ve always had via
We’re talking about underlines here, but it’s worth prefacing this with a quick tangent:
text-decoration-line, just like
text-decoration, has 3 positions:
- Under the text (
- Through the text (
- Over the text (
text-decoration-line also allows multiple values, so we can have lines under, through and above the same block of text. A bit weird, but it’s there:
text-decoration-line: underline overline;
What the underline looks like
Back to underlines. We now have control of how they look, via
text-decoration-style; there are 5 options:
They each look just as you’d expect, with a double line, wavy line, etc. Just add the
The underline colour
This one’s great.
text-decoration-color lets us change the colour of the underline. It accepts any normal CSS colour value, whether a keyword, hexadecimal, RGB, RGBA, HSL, etc.:
Just be sure that the underline passes the colour contrast ratio you’re aiming for!
Thickening up those underlines
Finally, we can control how thick the underline is with
text-decoration-thickness, for example:
Of course, we can do lots at the same time:
Or we can use
text-decoration-line instead of
That’s turning into a lot of CSS! Luckily, like margin, padding, border radius and loads of other CSS properties,
text-decoration is now a shorthand where we can declare multiple values:
text-decoration: underline wavy red;
Notice I haven’t added the
text-decoration-thickness property in that example. There’s a good reason for that: browser support.
A progressive enhancement
Underline styling is well supported across all modern browsers. Older versions (and Internet Explorer 11 and below, of course) should get a bog standard but still very user-friendly underline, as long as there’s nothing like this in your CSS reset:
But keep in mind, browser support for varies depending on:
- the property you use
- the values in the property
Prefixes needed for shorthand
If you’re using shorthand, you’ll need vendor prefixes for Safari to do your bidding:
text-decoration: underline wavy red;
-webkit-text-decoration: underline wavy red;
Easy enough to do if you’re automating things with Autoprefixer, and not too much extra work if you’re writing it by hand. Again, browsers that don’t support
text-decoration shorthand should just fall back to that default underline.
text-decoration-thickness isn’t as well supported as the others
The browser support for
text-decoration-color is pretty good. Each browser implemented all three at the same time, but controlling an underline’s thickness was introduced much later. In fact, only Safari and Firefox currently support it, so we’re still waiting on Chrome (and therefore Opera and Edge).
What’s more, Firefox is currently the only browser to support thickness in the shorthand, so if you want to use thickness in your shorthand you’ll need to do the classic double-declaration so that other browsers get a value they understand:
text-decoration: underline solid red;
text-decoration: underline solid red 5px;
text-decoration-thickness and percentages don’t play nicely
Also, be careful using percentage values for thickness, as it’s only Firefox that supports them.
The good news is that percentage values are calculated as a percentage of 1em, so
text-decoration-thickness: 0.1em is the same as
text-decoration-thickness: 10%, so you might as well stick to
ems as they do effectively the same thing.
There are always pixels (
px), but it’s nicer typographically to keep the thickness of the line relative to the text it’s underlining, so if the user increases the size of the text on their screen the underline increases proportionally.
Be careful when pairing
text-decoration-thickness. Anything other than the default
solid line (and maybe
double line) can look messy when the thickness is set too high. Those
dotted almost always usually cut off in untidy places when they skip descenders, and at the end of a word.
As with most CSS, remember: with great power comes great responsibility, and from a usability point of view, I’d be wary of using anything other than a solid underline to style a link.
So you’re probably fine if you’re after:
- a different coloured underline
- a progressively enhanced thick underline
- maybe even a double underline
But be careful with everything else:
text-decoration-line: line-throughis basically how
<del>elements look, with a strikethrough
text-decoration-line: overlinelooks weird and could make the text above the link look like the link instead
dashedunderlines could look like spelling or grammatical errors in a word processing document, rather than links
Where I think
dashed could work nicely, though, is for hover states.
What I would do
Shorthand comes with vendor prefixes and dodgy double-declarations, so I’d start with the classic
text-decoration: underline; and enhance it. I’d be inclined to avoid anything other than a straightforward underline, which users know well, so
text-decoration-line is out; which leaves me with a splash of colour and a nice
em-based thickness for non-Chromium browsers: