# Підкреслення, яке не обходило літери

2026-09-28

Наш власний сайт підкреслює кожне посилання й дозволяє браузеру вирізати
проміжок там, де хвостик літери перетинає лінію, — `g`, `p`, кома. У Safari
цього не відбувалося. Лінія йшла просто крізь них. І так було на англійських та
данських сторінках відтоді, як сайт став
багатомовним *(вада, про яку ніхто не повідомляє, бо вона просто має дешевий вигляд)*.

Причиною були три оголошення шрифту для абетки, яку ті сторінки ніколи не
завантажують.

## Що браузер має робити

`text-decoration-skip-ink` — це властивість, яка піднімає підкреслення над
нижнім виносним елементом. Вона ввімкнена за замовчуванням, і роками відповіддю
на «моє підкреслення має неправильний вигляд» було взятися за
`text-underline-offset` і посунути лінію нижче. Це хибний рефлекс: зсув лінії
змінює дизайн, а бракувало насправді саме проміжку.

Перш ніж дійти до цікавого, ми знайшли дві справжні причини, і обидві варті
уваги.

- **Підкреслення завтовшки `1px` отримує проміжок розміром `1px`.** Розрив, який
  вирізає рушій, пропорційний товщині лінії, що його вирізає. Наш стиль
  зафіксував товщину на одному пікселі, і це лишало близько 0,6px повітря з
  кожного боку штриха — технічно проміжок, візуально лінія просто крізь літеру.
  `text-decoration-thickness: auto` змасштабував обидві величини разом і збільшив
  проміжок з 3,5px до 12,4px, не зсунувши підкреслення ані на піксель.
- **`from-font` — не той безпечний варіант, яким здається.** Він читає товщину,
  яку оголошує сам шрифт, а Ubuntu оголошує 0,056em для Light, 0,020em для
  Medium і 0,120em для Bold — родина, у якої лінія Medium важить менше за
  половину лінії Light. На великих розмірах це шестипіксельна лінія поряд із
  двопіксельною на одній сторінці.

Це виправило Chrome. Safari й далі вів лінію крізь усе.

## Частина, яка забрала найбільше часу

Ми виміряли це як належить: запустити справжній Safari, перефарбувати
підкреслення, зробити знімок екрана у восьмикратному масштабі й порахувати
пікселі, де лінія уривається й починається знову.

| | намальована товщина | проміжок навколо виносного елемента |
| --- | --- | --- |
| Chrome | 2,00px | 5,8 / 12,5 / 6,3px |
| Safari | 1,38px | 1,8 / 1,0 / 1,0px |

Отже, Safari таки вирізав проміжок. Просто вшестеро вужчий за Chrome, а в
розмірі для читання проміжок в один піксель — це не проміжок. Гірше: звичний
важіль лише погіршував справу. За товщини 3px Safari падав із трьох проміжків до
одного, за 4px — до жодного, бо він не масштабує проміжок разом із лінією. Він
фіксує його приблизно на 0,07em за будь-якого розміру, тоді як Chrome дає 0,6em.

Ми перебрали проти нього близько двадцяти оголошень — `skip-ink: all`, обидва
застарілі написання властивості, кожну товщину від половини пікселя до чотирьох,
`text-underline-position`, `font-smoothing`, `text-rendering`, `paint-order`.
Ніщо не розширило проміжок. Чесний висновок на той момент був такий: WebKit
просто обмежує проміжок, і зі стилів більше нічого не вдіяти.

Той висновок виявився хибним, а зламав його
[звіт про ваду проти шрифтового проєкту](https://github.com/fontsource/fontsource/issues/1096):
Safari ігнорує skip-ink, коли шрифт завантажено з нелатинською підмножиною.

## Справжня причина

Сайт віддає Ubuntu шістьма частинами — три накреслення латиницею, три
кирилицею, — щоб українська сторінка була набрана тим самим шрифтом, що й
англійська, а не відкочувалася до того, що запропонує система. Кожна частина
оголошує діапазон символів, який покриває, і браузер завантажує лише ті
частини, які сторінці справді потрібні.

Усі шість були оголошені під однією назвою родини — це найочевидніший спосіб це
записати. І саме він є спусковим гачком, зафіксованим як
[вада WebKit 255159](https://bugs.webkit.org/show_bug.cgi?id=255159): **коли
одне накреслення в родині оголошує нелатинський діапазон символів, Safari
погіршує skip-ink для кожного символу цієї родини** — зокрема для латинського
тексту на сторінці, яка ніколи не завантажує той інший файл.

Англійська сторінка малювала свої підкреслення погано, бо десь у стилях існувало
українське оголошення шрифту. Коли ми видалили ті три рядки під час виконання й
не змінили більше нічого, проміжки зросли з 1,8/1,0/1,0px до 4,5/11,0/5,0px.

## Виправлення

Дайте другій системі письма власну назву родини й назвіть її у стеку шрифтів
після першої:

```css
@font-face {
    font-family: UbuntuCyrillic;   /* було: 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;
}
```

Латинська літера знаходиться в першій родині й ніколи не доходить до другої.
Кирилична проминає першу, де такого гліфа немає, і потрапляє в другу, а не в
системний шрифт. Діапазони символів і далі вирішують, що завантажується, тож в
завантаженні не змінюється нічого: англійські та данські сторінки беруть три
латинські файли й жодного кириличного, українські — навпаки.

Три перейменовані оголошення й один запис у стеку. Проміжки в Safari зросли до
4,5/11,0/5,0px, Chrome лишився недоторканим, підкреслення не зрушило з місця, а
українська й далі набирається в Ubuntu з тими самими ширинами.

## Що ми сказали б наступному

- **Вимірювання skip-ink справедливе лише для того рушія, який його дав.** Ми
  мали таблицю чисел, правильний діагноз і справжнє виправлення — і все це було
  Chromium. Знімок екрана, який відкрив справу наново, надійшов від людини, яка
  подивилася на сторінку.
- **Беріться за товщину раніше, ніж за зсув.** Ширший проміжок зберігає дизайн;
  зсув лінії вниз його замінює.
- **Ділити шрифт за системами письма — правильно, але поділ має бути й у назві
  родини.** Одна назва на кілька систем письма читається краще й коштує вам
  skip-ink у Safari. Злити їх назад має вигляд прибирання, а є регресом.
- **Завантаження ніколи не було проблемою.** Будь-яка інтуїція підказує, що
  сторінка, яка малюється погано через кириличний шрифт, мусить завантажувати
  щось зайве. Вона не завантажувала. Досить було самого оголошення.

## Джерела

- [Вада WebKit 255159 — `text-decoration-skip-ink` і підмножини шрифтів](https://bugs.webkit.org/show_bug.cgi?id=255159)
- [Issue 1096 у Fontsource, який назвав спусковий гачок](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/uk/notes/safari-underline-font-subset/>
