# Understrykningen som korsade varje bokstav

2026-09-28

Vår egen webbplats stryker under varje länk och låter webbläsaren skära ut en
lucka där en bokstavs svans korsar linjen — `g`, `p`, kommatecknet. I Safari
gjorde den inte det. Linjen gick rakt igenom dem. Så hade det varit på de
engelska och danska sidorna så länge webbplatsen hade varit
flerspråkig *(buggen som ingen rapporterar, eftersom den bara ser billig ut)*.

Orsaken var tre typsnittsdeklarationer för ett alfabet som de sidorna aldrig
laddar ned.

## Vad webbläsaren ska göra

`text-decoration-skip-ink` är egenskapen som lyfter en understrykning runt en
nedstapel. Den är på som standard, och i åratal har svaret på ”min understrykning
ser fel ut” varit att ta till `text-underline-offset` och skjuta linjen längre
ned. Det är fel reflex: att flytta linjen ändrar designen, och luckan är det som
faktiskt saknades.

Vi hittade två verkliga orsaker före den intressanta, och båda är värda att
känna till.

- **En understrykning på `1px` får en lucka i storleken `1px`.** Brytningen som
  motorn skär ut är proportionell mot tjockleken på linjen som skär. Vår
  stilmall låste tjockleken vid en pixel, vilket lämnade ungefär 0,6 px luft på
  var sida om en stapel — tekniskt sett en lucka, visuellt en linje rakt genom
  bokstaven. Att sätta `text-decoration-thickness: auto` skalade båda
  tillsammans och tog luckan från 3,5 px till 12,4 px utan att flytta
  understrykningen en enda pixel.
- **`from-font` är inte det säkra standardval det låter som.** Det läser den
  tjocklek som typsnittet självt deklarerar, och Ubuntu deklarerar 0,056 em för
  Light, 0,020 em för Medium och 0,120 em för Bold — en familj vars linje i
  Medium är mindre än hälften så kraftig som den i Light. I stora storlekar blir
  det en linje på sex pixlar bredvid en linje på två pixlar på samma sida.

Det löste saken i Chrome. Safari drog fortfarande linjen genom allt.

## Den del som tog längst tid

Vi mätte ordentligt: styr en riktig Safari, färga om understrykningen, ta en
skärmbild i åtta gångers förstoring och räkna pixlarna där linjen slutar och
börjar.

|                                  | ritad tjocklek | lucka runt en nedstapel |
| -------------------------------- | -------------- | ----------------------- |
| Chrome | 2,00 px        | 5,8 / 12,5 / 6,3 px     |
| Safari | 1,38 px        | 1,8 / 1,0 / 1,0 px      |

Safari skar alltså en lucka. Den var bara sex gånger smalare än den i Chrome,
och i lässtorlek är en lucka på en pixel ingen lucka. Värre var att det vanliga
greppet gjorde saken värre: vid en tjocklek på 3 px gick Safari från tre luckor
till en, vid 4 px till ingen, eftersom den inte skalar luckan med linjen. Den
låser den vid ungefär 0,07 em i alla storlekar, där Chrome ger 0,6 em.

Vi prövade ett tjugotal deklarationer mot det — `skip-ink: all`, båda äldre
stavningarna av egenskapen, varje tjocklek från en halv pixel till fyra,
`text-underline-position`, `font-smoothing`, `text-rendering`, `paint-order`.
Ingenting gjorde luckan bredare. Den ärliga slutsatsen vid den punkten var att
WebKit helt enkelt satte ett tak för luckan och att det inte fanns mer att göra
från en stilmall.

Den slutsatsen var fel, och det som fällde den var
[en buggrapport mot ett typsnittsprojekt](https://github.com/fontsource/fontsource/issues/1096):
Safari ignorerar skip-ink när ett typsnitt laddas med en icke-latinsk delmängd.

## Den faktiska orsaken

Webbplatsen serverar Ubuntu i sex delar — tre vikter med latinska tecken, tre
med kyrilliska — så att en ukrainsk sida sätts i samma typsnitt som en engelsk i
stället för att falla tillbaka på vad systemet nu erbjuder. Varje del
deklarerar det teckenintervall den täcker, och webbläsaren laddar bara ned de
delar som en sida faktiskt behöver.

Alla sex var deklarerade under ett och samma familjenamn, vilket är det
självklara sättet att skriva det. Och det är utlösaren, registrerad som
[WebKit-bugg 255159](https://bugs.webkit.org/show_bug.cgi?id=255159): **när ett
snitt i en familj deklarerar ett icke-latinskt teckenintervall försämrar Safari
skip-ink för varje tecken i den familjen** — även latinsk text på en sida som
aldrig hämtar den andra filen.

En engelsk sida återgav sina understrykningar dåligt för att det fanns en
ukrainsk typsnittsdeklaration någonstans i stilmallen. Att ta bort de tre
raderna under körning, och inte ändra något annat, tog luckorna från
1,8/1,0/1,0 px till 4,5/11,0/5,0 px.

## Lösningen

Ge den andra skriften ett eget familjenamn, och ange det i typsnittsstacken
efter det första:

```css
@font-face {
    font-family: UbuntuCyrillic;   /* var: Ubuntu */
    src: url(ubuntu_300_cyrillic.woff2) format('woff2');
    unicode-range: U+0400-045F, U+0490-0491;
}

:root {
    --body-font: Ubuntu, UbuntuCyrillic, system-ui, sans-serif;
}
```

En latinsk bokstav hittas i den första familjen och når aldrig den andra. En
kyrillisk faller förbi den första, som saknar en sådan glyf, och landar i den
andra i stället för i ett systemtypsnitt. Teckenintervallen avgör fortfarande
vad som laddas ned, så ingenting i laddningen ändras: engelska och danska sidor
hämtar tre latinska filer och inga kyrilliska, ukrainska sidor det omvända.

Tre omdöpta deklarationer och en ny post i stacken. Luckorna i Safari blev
4,5/11,0/5,0 px, Chrome lämnades orört, understrykningen flyttade sig inte, och
ukrainska sätts fortfarande i Ubuntu med identiska bredder.

## Vad vi skulle säga till nästa person

- **En skip-ink-mätning gäller bara för den motor som gav den.** Vi hade en
  tabell med siffror, en korrekt diagnos och en verklig lösning, och allt var
  Chromium. Skärmbilden som öppnade fallet igen kom från en människa som tittade
  på sidan.
- **Ta till tjockleken före förskjutningen.** Att bredda luckan behåller
  designen; att flytta ned linjen ersätter den.
- **Att dela upp ett typsnitt efter skrift är rätt, men uppdelningen hör hemma
  i familjenamnet också.** Ett gemensamt namn för flera skrifter läser bättre och
  kostar dig skip-ink i Safari. Att slå ihop dem igen ser ut som städning och är
  en regression.
- **Laddningen var aldrig problemet.** Varje instinkt säger att en sida som
  återges dåligt på grund av ett kyrilliskt typsnitt måste ladda ned något den
  inte borde. Det gjorde den inte. Deklarationen räckte i sig.

## Källor

- [WebKit-bugg 255159 — `text-decoration-skip-ink` och typsnittsdelmängder](https://bugs.webkit.org/show_bug.cgi?id=255159)
- [Fontsource-ärende 1096, som pekade ut utlösaren](https://github.com/fontsource/fontsource/issues/1096)
- [MDN: `text-decoration-skip-ink`](https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-skip-ink)
- [MDN: `unicode-range`](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range)

<https://software.engineer.company/sv/notes/safari-underline-font-subset/>
