6

When setting the text-decoration:underline on an element, the line is shown on the baseline.

enter image description here

It is over the descender of letters. It makes reading difficult if the line contains many letters with descenders.

enter image description here

I want to move the underline below the descenders using text-underline-offset: 4px;.

enter image description here

It works.

On Chrome, it is exactly how I want. However, it is not below the descenders on Safari.

enter image description here

If I use, text-underline-offset: 5px;, It works on Safari. But on Chrome, It is close to the ascenders of the second line rather than being close to the descenders of the same line. I can solve it using a higher value line-height, but that I don't want.

Is there any way to caclualte the height of the descenders so that I offset the underline exaclty that much below the baseline?

Info:

The font I am using is called Basis Grotesque Pro regular

Links

mahan
  • 12,366
  • 5
  • 48
  • 83
  • Looks like the text is slightly larger on Safari. Does it help if you use an offset relative to the font size, for example `0.1em`? – Thomas May 04 '22 at 08:35
  • @Thomas no. I have used relative units (em & rem) too. – mahan May 04 '22 at 08:42
  • One of the aspects I can think of is your font is not consistent across browsers. I'd suggest that you should reset your font styles with [this](https://meyerweb.com/eric/tools/css/reset/) – Nick Vu May 04 '22 at 08:49

1 Answers1

2

Using the ideas from https://stackoverflow.com/questions/10180148/how-to-calculate-descender-height-in-javascript#:~:text=This%20is%20possible%3A%20use%20this%20library%3A%20baseline%20ratio%2C,The%200%20px%20font%20lies%20on%20the%20baseline.

you can calculate the height of a descender by putting two spans next to each other.

The first has a font size of 0px. If you find its top position that will be the position of the baseline for the pair of spans.

The second span has whatever font size you are interested in.

Then you can get the height of the ascender by taking the top of the second span from the top of the first span. The height of the descender will be the height of the second span minus this amount.

const span1Params = document.querySelector('.span1').getBoundingClientRect();
const span2Params = document.querySelector('.span2').getBoundingClientRect();
document.querySelector('.text').style.textUnderlineOffset = (span2Params.height - (span1Params.top - span2Params.top)) + 'px';
.test {
  position: absolute;
  top: -1000px;
}

.span1 {
  font-size: 0px;
}

.span2 {
  font-size: 36px;
}

.text {
  text-decoration: underline;
  font-size: 36px;
}
<div class="test">
  <span class="span1">j</span>
  <span class="span2">j</span>
</div>
<div class="text">Atmospheric impacts of hydrogen as an energy carrier</div>
A Haworth
  • 30,908
  • 4
  • 11
  • 14
  • What if you have elements with different font-size? – mahan May 04 '22 at 11:00
  • Depends on what effect you want - basically you'd do the calculation for all of them, or, more concise would be to do the calculation using a big font to get as accurate as possible ratio of descender size to font size and then use that (you could put it into a CSS variable and then get CSS to do the calcs). – A Haworth May 04 '22 at 11:02