shaky.sh

CSS text-decoration and headings

I'm no designer, but I've been having fun tweaking the styling for this site recently. One fun bit has been the <h2> elements I use as headings with a post. Like this:

Hey there

The fun bit, of course, is the underlining. You might think it's a simple border-bottom. Au contraire! A border-bottom can't skip over glyph descenders (the "tail" on the y in the heading above).

Instead, I'm using text-decoration, which you typically see on links/anchors, and which does skip over glyph descenders1.

.prose h2 {
  text-decoration: underline;
  text-decoration-color: var(--primary-accent-color);
}

Whyyyyyyyy?

Because it's a fun look! As mentioned, I'm no designer.

But I don't want headings to be mistaken for links. So I wanted this line to continue the full width of the heading. The only way (I could find) to do this is by adding non-breaking spaces after the text in the heading. The simplest way to do that is with :after content:

.prose h2:after {
  content: " \a0\a0\a0";
}

This is three non-breaking spaces, but actually, I'm adding a lot of them enought to fill out the rest of the line even when my text is short. Too many for most cases, actually. So now we have to hide the overflow:

.prose h2 {
  white-space: nowrap;
  overflow: hidden;
}

This means, of course, that I can never write a heading that may break onto multiple lines. Pretty sure I can live with that for now.

In case this changes in the future, here's an image of what this looks like today.

Two level-two headings. The first says 'Hey there', the second says `Why' with eight 'y's. They demonstrate the styling of the level-two headings in this post, in dark mode, at the time of this writing

If there's a better way to do this, I'd love to hear! If this looks bad in your browser, please send me a screenshot!


  1. As I recently learned, you can control that with text-decoration-skip-ink. ↩︎