0

I have a perplexing CSS issue, where multiple rows with background colour that should meet have a very slight gap in high DPI screens.

@font-face {
    font-family: 'Iosevka';
    font-style: normal;
    font-weight: 400;
    src: url(https://curiousdannii.github.io/parchment-testing/fonts/build/iosevka-custom-extended.woff2) format('woff2');
}

.BufferWindow {
    font-family: Georgia;
    font-size: 15px;
    line-height: 1.4;
    overflow-y: auto;
    scrollbar-gutter: stable;
}

.BufferLine {
    white-space: pre-wrap;
}

span.Style_preformatted {
    font-size: 1em;
    font-weight: normal;
    font-style: normal;
    font-family: Iosevka;
}

.reverse {
    background: black;
    color: white;
    display: inline-block;
}
<div class="BufferWindow">
    <div class="BufferLine Style_preformatted"><span class="Style_preformatted">         </span><span class="Style_preformatted reverse">   </span><span class="Style_preformatted"> </span><span class="Style_preformatted reverse">   </span></div>
    <div class="BufferLine Style_preformatted"><span class="Style_preformatted">         </span><span class="Style_preformatted reverse">       </span></div>
    <div class="BufferLine Style_preformatted"><span class="Style_preformatted">         </span><span class="Style_preformatted reverse">      </span><span class="Style_preformatted">  </span></div>
    <div class="BufferLine Style_preformatted"><span class="Style_preformatted">         </span><span class="Style_preformatted reverse">       </span></div>
    <div class="BufferLine Style_preformatted"><span class="Style_preformatted">         </span><span class="Style_preformatted reverse">       </span></div>
</div>

Screenshot showing how it's designed to look, on a non-HDPI screen:

Screenshot showing how it's designed to look, on a non-HDPI screen

Screenshot directly from my phone:

Screen shot from my phone

Screenshot from remote dev tools showing the height of one row, which is 21 pixels:

Screenshot from remote dev tools showing the height of one row

Screenshot from remote dev tools showing the height of all five rows, which is 107 pixels:

Screenshot from remote dev tools showing the height of all five rows

So on a non-HDPI screen the height of all five rows is 105 pixels, which is 5 times 21 pixels. Somehow on the HDPI screen it's adding two extra pixels.

So then I saw in dev tools that the height of the BufferLine isn't actually 21 pixels, it's 21.364:

screenshot from dev tools showing the BufferLine

I was wondering if it was that the line-height: 1.4 multiplier was producing something almost but not exactly 21 pixels high, which only becomes relevant on HDPI screens, but 15 * 1.4 = 21 exactly (I must have designed this sensibly in the past ;)). So I'm not sure what's cause that little bit extra in height.

How do I determine which part of my CSS is causing this, and how can I make it more reliable?

curiousdannii
  • 1,658
  • 1
  • 25
  • 40
  • 1
    When I either zoom in or out I'm getting it on non-HDPI too. I don't know how to fix it, but I thought I'd mention it. – H3AR7B3A7 Jun 04 '22 at 03:13
  • 1
    Your problem will be differences in how the leading is distributed between Georgia and Iosevka fonts. What's the goal in using each of the fonts? – Alohci Jun 04 '22 at 03:51
  • @Alohci Ah, I only know a little about leading in CSS. I had thought that line-height was applied to font-size so that the fonts didn't really matter. This is for a [web interactive fiction interpreter](https://iplayif.com/?story=https://ifarchive.org/if-archive/games/zcode/Savoir-Faire.zblorb) where I need reliable fonts for both monospaced and proportional. – curiousdannii Jun 04 '22 at 03:54
  • You don't really need to worry about the leading. All you need to know is that Georgia and Iosevka don't quite line up with one another vertically, so while both are 21px high because they don't line up one's a bit lower than the other and the total height from the top of one to the bottom of the other is 21.364px. So if you used Iosevka throughout you wouldn't get the problem. – Alohci Jun 04 '22 at 04:10
  • It seems to be related to Georgia's having ascenders above the caps. – A Haworth Jun 04 '22 at 04:22

2 Answers2

1

The arrangement you have is essentially this:

Two rectangles, each depicting a character block, the same height but vertically offset from one another, making the height from the top of one two the bottom of the other greater than the height of the rectangles.

(1/2L = Half Leading)

The characters align by their baselines, but because the ascents and/or descents differ, their tops and bottoms don't align with one another, and the total height is greater than either of the characters.

From this you should be able to see that the problem can be avoided by either using the same font throughout, or by reducing the line height of one of them, so that their half-leadings are so small (or negative) that the total top edge and bottom edge are both determined by the same character.

Alohci
  • 78,296
  • 16
  • 112
  • 156
  • Thank you! This has helped me understand the issue a lot. Now to see whether something like `vertical-align` might help. Or else by reducing the `line-height` as you suggest. – curiousdannii Jun 04 '22 at 12:31
  • Reducing the `line-height` won't work because it is what determines how much height to apply the background colour to. I didn't show it in this example, but I also need background colour to apply to the proportional font too. But I might be able to get the font metrics and then calculate padding values to apply manually, as suggested by [this answer](https://stackoverflow.com/a/56781081/2854284). Or maybe the `ascent-override`/`descent-override` properties of `@font-face`. – curiousdannii Jun 04 '22 at 22:54
0

UPDATE: It appears that the below is incorrect - although it worked for me it has not worked for the OP. The following is left here temporarily as a basis for discussion.

The phenomenon seems to occur because there is a difference in the way the two typefaces treat ascenders.

Georgia has a special characteristic that the ascenders come significantly above the caps.

From https://taylorhieber.co/georgia-type-set

enter image description here

If you replace Georgia with a typeface that does not have this difference then the gaps disappear.

This snippet uses another serif font, Times New Roman, but which does not have this 'extra' height on the ascenders:

@font-face {
    font-family: 'Iosevka';
    font-style: normal;
    font-weight: 400;
    src: url(https://curiousdannii.github.io/parchment-testing/fonts/build/iosevka-custom-extended.woff2) format('woff2');
}

.BufferWindow {
    font-family: 'Times New Roman';
    font-size: 15px;
    line-height: 1.4;
    overflow-y: auto;
    scrollbar-gutter: stable;
}

.BufferLine {
    white-space: pre-wrap;
}

span.Style_preformatted {
    font-size: 1em;
    font-weight: normal;
    font-style: normal;
    font-family: Iosevka;
}

.reverse {
    background: black;
    color: white;
    display: inline-block;
}
<div class="BufferWindow">
    <div class="BufferLine Style_preformatted"><span class="Style_preformatted">         </span><span class="Style_preformatted reverse">   </span><span class="Style_preformatted"> </span><span class="Style_preformatted reverse">   </span></div>
    <div class="BufferLine Style_preformatted"><span class="Style_preformatted">         </span><span class="Style_preformatted reverse">       </span></div>
    <div class="BufferLine Style_preformatted"><span class="Style_preformatted">         </span><span class="Style_preformatted reverse">      </span><span class="Style_preformatted">  </span></div>
    <div class="BufferLine Style_preformatted"><span class="Style_preformatted">         </span><span class="Style_preformatted reverse">       </span></div>
    <div class="BufferLine Style_preformatted"><span class="Style_preformatted">         </span><span class="Style_preformatted reverse">       </span></div>
</div>

Footnote: I am not absolutely convinced that it is because the ascenders are higher (relatively) on Georgia than Times New Roman, it may just be that the typefaces differ in how they interpret lineheight overall. Hope someone out there can confirm or deny. In any case it appears that using a different serif font may cure the white lines problem. More experiments with different serif fonts could be interesting.

A Haworth
  • 30,908
  • 4
  • 11
  • 14
  • Your example with TNR has the stripes even in my non-HDPI screen. But does this mean there's no way to properly contain any arbitrary font within a pixel box in CSS? – curiousdannii Jun 04 '22 at 06:15
  • Interesting, I got no stripes so assumed the lineheights were compatible. What browser/OS are you on? (I tried with Edge/Windows10). – A Haworth Jun 04 '22 at 06:18
  • Correction! I've just got stripes with just one zoom level (175%) - so back to the drawing board. I'm assuming your're requirement is to have one serif and one sans-serif font? – A Haworth Jun 04 '22 at 06:20
  • Chrome on Windows 10, 100% zoom. I guess I could change away from Georgia, but I'd really like to understand better what's going on. – curiousdannii Jun 04 '22 at 07:00
  • Yes, I'm asking a typographer what's going on. – A Haworth Jun 04 '22 at 07:30
  • FF on Windows10 - only saw problem at some zoom levels (which indicates an edge effect error as CSS pixels mapped to multiple screen pixels). Not sure where that leaves us. – A Haworth Jun 04 '22 at 07:47
  • Really, any two different fonts are likely to have the problem. If you don't get the problem at all, either (a) the fonts have been specifically designed to align together, or (b) you've struck incredibly lucky. – Alohci Jun 04 '22 at 10:24