Краща типографіка для документації, яку інженери реально читають

Було корисно?

Ваша документація може бути технічно коректною й водночас функціонально марною. Я бачив, як інженери на чергуванні пролистували сторінку тричі, бо вона виглядала як лист з викупом: рядки по 140 символів, заголовки без сенсу, і блоки коду, що розривалися всередині прапорців.

Це не «зробити красиво». Це оперативна гігієна. Типографіка — це частина документації, яка вирішує, чи читач дістанеться потрібної команди за 20 секунд або вигадає власний обхід у продакшні.

Чому типографіка — проблема SRE

Документація є частиною контрольної площини. Не метафорично — буквально. Ваші інструкції на інциденти, операційні посібники, плани міграції та «це сервіс поводиться дивно» знання племені живуть там. Якщо типографіка ворожа, система стає ворожою. Інженери все одно виконуватимуть зміни, мінятимуть ключі, відбудовуватимуть масиви. Вони просто робитимуть це з пам’яті. Так з’являються тихі відмінності в процедурах, розбіжні припущення й той тип відмов, що не відтворюється.

Типографіка впливає на три оперативні метрики, які вам мають бути небайдужі:

  • Час до відповіді під стресом. Документація, яку можна швидко переглянути, перемагає. Док, що вимагає читання — програє.
  • Рівень помилок при копіюванні/вставці. Розбиті блоки коду, неоднозначні переноси та схожі гліфи — надійне джерело неправильних команд.
  • Безпека змін. Якщо заголовки не є стабільними якорями, а довжина рядка спричиняє хаос рідкісного перерозподілу, рецензенти пропускають дифі й документація віддаляється від реальності.

Типографіка не виправить зламану топологію зберігання. Але вона зупинить те, щоб руковідник «брехав» через форматування.

Одна цитата, яка досі має значення в операційній роботі: «Сподівання — не стратегія.»Вінс Ломбарді. Це не цитата зі світу софту, тому ще цінніша. Ваш макет документації не має покладатися на сподівання, що читач «помітить».

Цікаві факти (бо це має історію)

  • Ранні норми довжини рядка походять з обмежень друку. Газети й книги зійшлися на помірних вимірах, бо довгі рядки збільшують помилки при поверненні ока до початку наступного рядка.
  • Конвенції друкарської машинки сформували очікування для monospace. Фіксована ширина навчила покоління читати вирівняні колонки — досі важливо для логів, таблиць і виводу CLI.
  • Гіпенізація колись була ручною працею. Композитори вставляли розумні дефіси вручну; сучасні алгоритми роблять це автоматично і іноді погано, особливо для технічних термінів.
  • ASCII — причина боротьби з подібними символами. Проблема «1/l/I» давня; ставки зросли, коли ці символи почали з’являтися в секретах, токенах і іменах хостів.
  • Markdown успадкував звички епохи електронної пошти. Багато конвенцій Markdown оптимізувалися під читабельність у plain-text, а не під поліруване відображення — звідси дивні взаємодії з перенесенням і блоками коду.
  • Підтримка CSS-графи гіпенізації неоднорідна. Властивість hyphens залежить від словників мови й поведінки браузера; вона не детермінована у всіх клієнтах.
  • Якорі стали оперативним інтерфейсом. Коли документація почали навігувати через фрагменти URL, текст заголовка став поводитися як API — його зміна ламає руковідники й тікети.
  • Вибір шрифту коду впливає на читабельність гліфів. Деякі шрифти роблять {}, [] і () занадто схожими при малих розмірах — гарно для естетики, погано для продакшну.

Жарт №1: Типографіка як моніторинг: якщо ви помічаєте її лише коли вона «кричить», ви вже у біді.

Довжина рядка: тихий поглинач часу

Якщо основний текст вашої документації простягається на всю ширину 34-дюймового монітора, ви побудували тест на витривалість сканування. Довгі рядки — це не «більше інформації». Це більше руху очей. Рух очей коштує часу. У стресі час перетворюється на помилки.

Що робити

  • Цілитися в 60–80 символів на рядок для основного тексту. Якщо потрібне одне число: 72 — добрий дефолт.
  • Використовувати max-width, виміряний у символах (ch), а не в пікселях. Пікселі брешуть між шрифтами й пристроями; символи ближчі до реальності читання.
  • Дозволяйте коду бути ширшим за прозу, але не дозволяйте йому переноситися за замовчуванням. Горизонтальна прокрутка в блоках коду менш злочинна, ніж розбиті команди, що змінюють значення.

Несправності, які ви реально побачите

  • Помилки повернення з рядка: читач втрачає місце, коли переходить від кінця довгого рядка до початку наступного, особливо в щільних абзацах.
  • Колапс швидкого перегляду: заголовки втрачають ефективність, бо сторінка стає стіною; стратегія читача — «Ctrl+F і молитися».
  • Шум у дифах: якщо ваш редактор обгортає при одній ширині, а сайт — при іншій, невеликі правки переписують цілі абзаци й рецензенти перестають довіряти дифам.

CSS, що поводиться як дорослий

Ось той CSS, який ви кладете на сайт документації й більше не чіпаєте, якщо не любите постмортеми.

cr0x@server:~$ cat docs-typography.css
:root{
  --measure: 72ch;
  --body-font: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --mono-font: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  --base-size: 16px;
  --line-height: 1.55;
}
main, article{
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 1rem;
  font-family: var(--body-font);
  font-size: var(--base-size);
  line-height: var(--line-height);
}
pre, code, kbd, samp{
  font-family: var(--mono-font);
}
pre{
  overflow-x: auto;
  white-space: pre;
  tab-size: 2;
}
code{
  font-size: 0.95em;
}

Це файл, а не обіцянка. Рішення: вимірюйте прозу в символах, обмежуйте її централізовано й дозволяйте блокам коду прокручуватися горизонтально замість переносу.

Не ускладнюйте плавну типографіку без запобіжників

Плавна типографіка може бути чудовою. Вона також може непомітно перетворити 72ch у 110ch на широких екранах, поєднавшись з плаваючим розміром шрифту. Якщо ви йдете в плавність, обмежте measure.

Заголовки, які виправдовують своє існування

Заголовки — не прикраса. Це система навігації, план для швидкого перегляду і API-якорі для посилань з тікетів, алертів і чату. Коли ви випадково перейменовуєте заголовки, ви ламаете м’язову пам’ять людей. Коли ви погано оформлюєте заголовки, ви робите сторінку нечитаємою для швидкого перегляду.

Правила, що вбережуть вас від проблем

  • Одна сторінка — один H1. Нехай він буде обіцянкою сторінки. Якщо заголовок невизначений, решта не врятує.
  • Розділи H2 мають бути зрозумілими без контексту. «Конфігурація» — не розділ. «Налаштування TLS для вихідних вебхуків» — так.
  • Тримайте ієрархію заголовків неглибокою. H2 і H3 виконують більшість роботи. H4 — підозра. H5 — крик про допомогу.
  • Не стилізуйте заголовки надто агресивно. Великий контраст і помірна вага перемагають; гігантський градієнтний текст програє.
  • Даєте заголовкам стабільні ID. Якщо платформа автогенерує ID з тексту, зміна одного слова ламає посилання. Віддавайте перевагу явним ID або механізму псевдонімів.

Типографічні рішення, що змінюють поведінку

Інженери переглядають сторінки за формою. Якщо кожен заголовок має такий самий вагу, як основний текст, сторінка стає плоскою. Якщо кожен заголовок величезний, сторінка стає шумною. Потрібна чітка типографічна сходинка: H2 помітно відрізняється, H3 — підкрок, а основний текст залишається спокійним.

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

Якорі як оперативні інтерфейси

Якщо ваш інцидентний руковідник каже «Перейдіть до “Швидкої процедури відкату”», ця фраза має існувати і бути доступною за посиланням. Ставтеся до якорів заголовків як до кінцевих точок API: стабільні, версіоновані за потреби і не переписані під час «оновлення контенту».

Шрифти коду та блоки коду: припиніть ламати команди

Документація найчастіше провалюється в коді. Люди копіюють команди, вставляють їх у shell від root і натискають Enter з тією ж упевненістю, з якою схвалюють запит на зміну. Ваше завдання — не допустити, щоб текст мутував між екраном і терміналом.

Обирайте monospace-шрифт за читабельністю, а не виглядом

Моноширинні шрифти — це інфраструктура. Оберіть такий, що має:

  • Чітке розрізнення гліфів: O проти 0, l проти 1, {} проти (), і ;, що не зникає.
  • Хороше hinting при малих розмірах, щоб код не розмивався на дисплеях низької якості.
  • Стабільна ширина, щоб таблиці й вирівняний вивід CLI залишалися вирівняними.

Вбудований код проти блоків коду

  • Вбудований код для ідентифікаторів і коротких уривків: шляхи до файлів, прапорці, ключі JSON. Тримайте його коротким; не вставляйте повні команди в рядок.
  • Блоки коду для всього, що очікується копіювати/вставляти, для багаторядкового вмісту та для всього, де перенос змінює значення.

Ніколи не переносіть команди за замовчуванням

Перенесений код — фабрика для створення зламаних команд без видимого помилкового повідомлення до тих пір, поки не стане занадто пізно. Це особливо підступно для:

  • довгих заголовків curl
  • kubectl JSONPath-виразів
  • виводу CLI з диска, де колонки передають семантику
  • усіх випадків з backslash, лапками чи heredoc

Зробіть копіювання/вставку надійним

Використовуйте white-space: pre і горизонтальну прокрутку. Якщо хочете допомогти мобільним користувачам — надайте коротку версію команди, а не м’яке обгортання. Також переконайтеся, що сайт не замінює звичайні пробіли на NBSP або не виконує типографічні «поновлення» всередині блоків коду. Саме так з’являється невидимий Unicode, що ламає shell-и.

Жарт №2: Єдине гірше за розбиту команду — розбита команда, що все ще виглядає як нерозбита.

Гіпенізація: де гарне верстання зустрічає проблемний копіпейст

Гіпенізація існує, щоб вирівняний текст виглядав менш «дірчастим». Більшість технічних документів не повинні використовувати повне вирівнювання по ширині. Якщо ви це робите, ви запрошуєте проблеми гіпенізації, ріки пробілів і сторінку, що виглядає як неправильно налаштований текстовий редактор.

Коли гіпенізація допомагає

Для вузьких колонок (мобільні, бокові панелі) гіпенізація може зменшити незручні інтервали й не дати вирівняному правому краю виглядати як спіраль. Але технічна документація — не роман. Вона містить ідентифікатори, які не повинні переноситися: імена функцій, хостнейми, прапорці й складені терміни, що мають залишатися пошуковими.

Правила великого пальця

  • Вимикайте гіпенізацію для коду й UI-рядків. Усе, що читач може копіювати, набирати або шукати, не має переноситися дефісом.
  • Увімкніть гіпенізацію тільки для прозового тексту і лише після тестування в браузерах та переконавшись, що вказано мову контенту.
  • Уникайте вирівнювання по ширині. Нерівний правий край — це нормально; ваші читачі — інженери, а не наборники.

CSS-підхід, що не саботує токени

cr0x@server:~$ cat hyphenation.css
article{
  hyphens: auto;
}
code, pre, kbd, samp, a, .no-hyphen{
  hyphens: none;
}
h1, h2, h3{
  hyphens: manual;
}

Рішення: дозволити браузеру гіпенізувати абзаци (якщо ви справді цього хочете), але явно вимкнути її для коду, посилань і всього, що нагадує токен. Також: встановіть мову документа правильно. Словники гіпенізації від них залежать.

М’які дефіси — пастка в інженерній документації

М’який дефіс може непомітно потрапити в скопійований текст і зіпсувати пошук — особливо в полях пошуку, YAML-значеннях і shell-рядках. Більшість сучасних браузерів не включають м’які дефіси при копіюванні, але «більшість» — не контракт. Якщо потрібне розривання рядка, використовуйте CSS. Тримайте вихідний текст чистим.

Швидкий плейбук діагностики

Це плейбук «десь не читається». Використовуйте його, коли хтось скаржиться, що docs важко читати, тяжко переглядати або «команда, яку я скопіював, не спрацювала», і вам потрібно швидко знайти вузьке місце.

По-перше: перевірте measure і перенесення (найбільші виграші)

  1. Чи прозу обмежено приблизно 60–80 символами? Якщо ні — виправте max-width (надавайте перевагу ch).
  2. Чи блоки коду переносяться? Якщо так — зупиніться. Використовуйте горизонтальну прокрутку і white-space: pre.
  3. Чи заголовки візуально відрізняються? Якщо заголовки не «вистрибують», сканування провалюється. Відрегулюйте вагу/розмір/відступи.

По-друге: перевірте цілісність копіювання/вставки

  1. Чи застосовуються «розумні лапки» або типографічні заміни до коду? Вони зламають shell-и й JSON.
  2. Чи є невидимі символи? NBSP, нуль-ширинні пробіли, м’які дефіси.
  3. Чи роблять шрифти гліфи неоднозначними? Якщо O і 0 виглядають однаково — секрети й ID стають рулеткою.

По-третє: перевірте навігацію й якорі

  1. Чи TOC відображає реальну структуру? Якщо він автогенерований, але ієрархія хаотична — він не допоможе.
  2. Чи стабільні якорі заголовків? Якщо люди посилаються на розділи з тікетів — зміна ID ламає оперативний потік.
  3. Чи є на сторінці пошук, що працює? Якщо пошук є, але типографіка робить заголовки недескриптивними — результати пошуку марні.

Дванадцять+ реальних завдань з командами, виводом і рішеннями

Це практичні перевірки, які ви можете виконати в репозиторії документації або на відрендереному сайті. Кожне завдання містить: команду, реалістичний вивід, що цей вивід означає, і рішення, яке потрібно прийняти. Так ви перетворюєте «доки видаються поганими» на конкретний тікет.

Завдання 1: Знайти підозріло довгі рядки в Markdown (проза)

cr0x@server:~$ python3 - <<'PY'
import os, re
root="docs"
limit=120
hits=0
for dp, _, files in os.walk(root):
  for f in files:
    if not f.endswith(".md"): 
      continue
    p=os.path.join(dp,f)
    with open(p,"r",encoding="utf-8") as fh:
      for i,line in enumerate(fh,1):
        if len(line.rstrip("\n"))>limit and not line.lstrip().startswith(("```","    ")):
          hits+=1
          print(f"{p}:{i}:{len(line.rstrip())}")
print("hits",hits)
PY
docs/runbooks/restore.md:44:168
docs/guide/architecture.md:112:203
hits 2

Значення: два прозові рядки перевищують 120 символів (не в блоках коду). Це часто вказує або на не обгорнуті абзаци, або на вставлений контент, що буде відрендерений як широкі рядки.

Рішення: переформатуйте ці абзаци в джерелі (або переконайтеся, що рендерер обгортає). Якщо ваш рендерер трактує переноси в Markdown як жорсткі, потрібно переформатувати.

Завдання 2: Виявити блоки коду, що переносяться через CSS

cr0x@server:~$ rg -n "white-space:\s*pre-wrap|white-space:\s*normal" site/assets/*.css
site/assets/main.css:418:white-space: pre-wrap;

Значення: блоки коду можуть використовувати pre-wrap, що переносить довгі команди.

Рішення: змінити на white-space: pre для елементів pre й дозволити горизонтальну прокрутку.

Завдання 3: Перевірити обчислений CSS для блоку коду (відрендерений сайт)

cr0x@server:~$ node - <<'NODE'
const fs=require('fs');
const html=fs.readFileSync('public/index.html','utf8');
console.log(html.includes('white-space: pre-wrap') ? 'pre-wrap found' : 'no pre-wrap in HTML');
NODE
no pre-wrap in HTML

Значення: проблемний pre-wrap ймовірно походить з зовнішньої таблиці стилів, а не з інлайнового HTML.

Рішення: виправляйте CSS у джерелі (дизайн-система/тема), а не на окремих сторінках.

Завдання 4: Знайти розумні лапки в кодових блоках

cr0x@server:~$ python3 - <<'PY'
import re, pathlib
root=pathlib.Path("docs")
bad = ["\u2018","\u2019","\u201c","\u201d"]
for p in root.rglob("*.md"):
  t=p.read_text(encoding="utf-8",errors="ignore")
  in_code=False
  for i,line in enumerate(t.splitlines(),1):
    if line.strip().startswith("```"):
      in_code = not in_code
    if in_code and any(ch in line for ch in bad):
      print(f"{p}:{i}: smart quote in code fence")
PY
docs/runbooks/backup.md:87: smart quote in code fence

Значення: «кудлаті» лапки з’явилися всередині блоку коду, що може зламати shell-команди й JSON.

Рішення: замінити на ASCII-лапки і припинити автоматичне «окультурювання» коду в редакторі/форматері.

Завдання 5: Виявити NBSP у блоках коду (вбивці копіпейсту)

cr0x@server:~$ python3 - <<'PY'
import pathlib
nbsp="\u00a0"
root=pathlib.Path("docs")
for p in root.rglob("*.md"):
  t=p.read_text(encoding="utf-8",errors="ignore")
  if nbsp in t:
    print(p, "contains NBSP")
PY
docs/guide/kubernetes.md contains NBSP

Значення: NBSP присутній десь у Markdown. У коді він може зламати прапорці й вирівнювання невидимим способом.

Рішення: замініть NBSP на звичайні пробіли; додайте лінт, щоб запобігти повторенню.

Завдання 6: Аудит ієрархії заголовків (занадто глибока, дивна)

cr0x@server:~$ python3 - <<'PY'
import pathlib, re
root=pathlib.Path("docs")
for p in root.rglob("*.md"):
  levels=[]
  for line in p.read_text(encoding="utf-8",errors="ignore").splitlines():
    m=re.match(r'^(#{1,6})\s+', line)
    if m:
      levels.append(len(m.group(1)))
  if any(l>3 for l in levels):
    print(p, "has heading level > 3:", sorted(set(levels)))
PY
docs/guide/storage.md has heading level > 3: [1, 2, 3, 4, 5]

Значення: у файлі використовуються H4/H5; ймовірно це спричинено бажанням заглибитись у деталі через погану структуру.

Рішення: реструктуруйте в меншу кількість осмислених H2/H3 розділів. Глибина рідко означає ясність.

Завдання 7: Виявити нестабільні автогенеровані ID-якорі (ризик для руководів)

cr0x@server:~$ rg -n "##\s+.*\s+\(deprecated\)|##\s+.*\s+\(old\)" docs/runbooks
docs/runbooks/restore.md:12:## Restore Procedure (old)

Значення: заголовки перейменовуються з доповненнями типу «(old)», що ймовірно змінює slugified ID і ламає вхідні посилання.

Рішення: тримайте заголовок стабільним і позначайте статус інакше (бейдж, нотатка) або додавайте явні ID-якорі, якщо система це дозволяє.

Завдання 8: Підтвердити, що overflow для блоків коду ввімкнено (запобігає переносу)

cr0x@server:~$ rg -n "pre\s*\{|pre\." site/assets/main.css | head
212:pre{
218:  overflow-x: auto;
219:  white-space: pre;

Значення: CSS вже використовує горизонтальну прокрутку і зберігає пробіли.

Рішення: добре — не чіпайте. Якщо користувачі все ще повідомляють про перенос, шукайте більш специфічні правила CSS, що перекривають ці.

Завдання 9: Виміряти середню довжину рядка у згенерованому HTML (виявити «повноширинні» макети)

cr0x@server:~$ python3 - <<'PY'
from bs4 import BeautifulSoup
import pathlib, statistics, re
p=pathlib.Path("public/index.html")
soup=BeautifulSoup(p.read_text(encoding="utf-8",errors="ignore"),"html.parser")
text=" ".join(soup.get_text(" ").split())
chunks=re.findall(r'.{1,200}', text)
lens=[len(c) for c in chunks if len(c)>50]
print("sample chunk lengths:", lens[:8])
print("median:", int(statistics.median(lens)))
PY
sample chunk lengths: [200, 200, 200, 200, 200, 200, 200, 200]
median: 200

Значення: витягнутий текст розбився на шматки по 200 символів, тож це не ідеальне вимірювання — але сигналізує про довгий неперерваний текст без природних розривів.

Рішення: використовуйте це як сигнал, а не доказ. Наступний крок — візуальна перевірка і перевірка CSS-measure (max-width) контейнера.

Завдання 10: Знайти налаштування гіпенізації в CSS (і де вони застосовуються)

cr0x@server:~$ rg -n "\bhyphens\s*:" site/assets/*.css
site/assets/main.css:88:  hyphens: auto;
site/assets/main.css:97:  hyphens: auto;

Значення: гіпенізація ввімкнена десь, можливо глобально.

Рішення: переконайтеся, що вона обмежена лише прозовими контейнерами; вимкніть для коду, посилань і токеноподібних фрагментів.

Завдання 11: Виявити м’які дефіси в джерельному контенті

cr0x@server:~$ python3 - <<'PY'
import pathlib
shy="\u00ad"
root=pathlib.Path("docs")
count=0
for p in root.rglob("*.md"):
  t=p.read_text(encoding="utf-8",errors="ignore")
  if shy in t:
    n=t.count(shy)
    count+=n
    print(p, "soft hyphens:", n)
print("total",count)
PY
total 0

Значення: м’яких дефісів у Markdown немає. Добре — ваш контент ще не отруєний.

Рішення: тримайте так: уникайте копіювання з джерел, що вставляють м’які дефіси (деякі PDF, деякі редактори CMS).

Завдання 12: Перевірити, чи встановлено мову документа (гiпенізація й екранні рідери)

cr0x@server:~$ python3 - <<'PY'
import pathlib, re
html=pathlib.Path("public/index.html").read_text(encoding="utf-8",errors="ignore")
m=re.search(r'<html[^>]*\blang="([^"]+)"', html)
print("lang=", m.group(1) if m else "missing")
PY
lang= en

Значення: мова встановлена. Це впливає на словники гіпенізації й інструменти доступності.

Рішення: переконайтесь, що кожна сторінка встановлює lang, а не лише шаблон головної сторінки.

Завдання 13: Знайти блоки коду без тегу мови (погіршує читабельність і безпеку копіювання)

cr0x@server:~$ python3 - <<'PY'
import pathlib, re
root=pathlib.Path("docs")
for p in root.rglob("*.md"):
  lines=p.read_text(encoding="utf-8",errors="ignore").splitlines()
  for i,l in enumerate(lines,1):
    if l.strip()=="```":
      print(f"{p}:{i}: code fence without language")
      break
PY
docs/guide/ssl.md:55: code fence without language

Значення: немарковані fenced-коди знижують якість підсвітки синтаксису й іноді впливають на віджети копіювання чи правила стилю.

Рішення: маркуйте fence-вирази (bash, json, yaml). Послідовність допомагає читачам і інструментам.

Завдання 14: Перевірити наявність табуляцій у блоках коду (вирівнювання ламається в різних середовищах)

cr0x@server:~$ python3 - <<'PY'
import pathlib
root=pathlib.Path("docs")
in_code=False
for p in root.rglob("*.md"):
  in_code=False
  for i,line in enumerate(p.read_text(encoding="utf-8",errors="ignore").splitlines(),1):
    if line.strip().startswith("```"):
      in_code=not in_code
    if in_code and "\t" in line:
      print(f"{p}:{i}: tab in code fence")
      break
PY
docs/runbooks/network.md:102: tab in code fence

Значення: таби всередині блоків коду можуть рендеритися по-різному; вирівнювання залежне від табулятора або YAML особливо крихке.

Рішення: конвертуйте таби в пробіли; якщо потрібно зберегти — встановіть tab-size у CSS (але не рекомендується).

Корпоративні міні-історії (бо так воно ламається)

1) Інцидент через хибне припущення: «Сайт документації безпечно переносить код»

У компанії був акуратний внутрішній портал документів. Гарна тема, хороший пошук, весь «developer experience» пакет. Руководства були в Markdown, відрендерені статичним сайто-генератором з корпоративним CSS поверхом.

Під час рутинної ротації сертифікатів молодший інженер на чергуванні слідував руковіднику і скопіював довгу команду openssl з кількома прапорцями й шляхами до файлів. Блок коду виглядав нормально візуально, бо тема робила м’який перенос довгих рядків і вставляла тонкий відступ при переносі. У терміналі вставлена команда включала перевід рядка посеред прапорця. Команда не виконалась, і інженер — під легким стресом — зробив класичний крок: редагував її, поки вона не запрацювала.

Вона запрацювала. Водночас згенерувався ключ з іншими параметрами і поклали його в інший каталог, ніж очікував сервіс. Наступний деплой підхопив неправильний файл, і частина інстансів почала неправильно вести TLS-рукостиск. Інцидент не вивів увесь сервіс з ладу. Він просто зробив частину трафіку помилковою періодично, що гірше, бо виглядає як мережевий привид.

Постмортем не звинувачував інженера. Хибне припущення було структурне: «Якщо команда в блоці коду — її безпечно копіювати.» Це не так. Виправлення було нудним: вимкнути перенос у блоках коду, додати кнопку копіювання, яка копіює raw-текст, і лінтувати руковідники на надто довгі однорядкові команди. Також додали секцію «Очікуваний вивід» у руковіднику, щоб інженер міг раніше помітити відхилення.

2) Оптимізація, що далась боком: «Увімкнемо повне вирівнювання й гіпенізацію для “книжкового” вигляду»

Ініціатива редизайну документів вирішила, що внутрішня платформа виглядає «занадто в стилі вікі». Хтось захотів, щоб вона виглядала як відполірована база знань. Вони увімкнули вирівнювання по ширині, щоб створити чисті лівий і правий краї, потім включили автоматичну гіпенізацію, щоб зменшити великі проміжки між словами.

На десктопі домашня сторінка виглядала… нормально. На мобільних і вузьких розділених екранах (поширений режим під час інцидентів) проза гіпенізувалася агресивно. Це було б просто дратівливим, якби правила гіпенізації не спрацьовували іноді на технічні складені терміни в заголовках і вбудованих токенах у прозі. Читачі почали шукати терміни, які бачили на сторінці, але не могли їх знайти, бо пам’ятали фрагменти з дефісами.

Більша проблема вдарила по руковідникам: респондери інцидентів переглядають заголовки, щоб навігувати. Гіпенізовані заголовки ламали цей паттерн сканування. Люди перестали використовувати TOC, бо розриви рядків робили назви розділів ніби різними словами. І оскільки команда використовувала автогенеровані якорі заголовків, невеликі правки тексту заголовка змінювали ID, тож посилання зі старих тікетів ламались. «Документація брешуть» стало поширеною скаргою.

Відкат був простим, але політично болючим: нерівний правий край, гіпенізація вимкнена за замовчуванням, гіпенізація дозволена лише для довгих абзаців на вузьких екранах і ніколи в заголовках чи в будь-чому, що позначене як код. Команда редизайну дізналася практичну істину: типографіка, що оптимізує естетику, може зменшувати оперативну точність. Мета не «вигляд як книга». Мета — «коректно за стресу».

3) Нудна, але правильна практика, що врятувала день: стабільні анкори й консервативна типографіка

В іншому місці команда документації мала звичку, яка виглядала занадто обережною: вони розглядали заголовки й анкори як версіоновані інтерфейси. Якщо заголовок потрібно було перейменувати задля ясності, вони зберігали старий анкор як псевдонім або залишали старий заголовок як прихований цільовий анкор. Інженери жартували, що документація отримує «губернанство API». Вони не були зовсім неправі.

Потім під час великої міграції платформи стався інцидент. Половина компанії була у war room. Багато команд вставляли розділи руковідників у чати: «перейдіть до розділу ‘Emergency failover’», «виконайте чекліст ‘Disable writes’», «перевірте кроки ‘Storage pool health’». Ці посилання були місяцями старі, взяті з старих тікетів і м’язової пам’яті.

Вони всі працювали. Ніяких 404, ніякого «розділ не знайдено», ніяких марних п’яти хвилин на пошук перейменованого заголовка. Типографіка сайту теж була консервативною: читабельна ширина, сильний контраст заголовків, блоки коду без переносу й передбачуваний макет, де блоки «Небезпечна команда» виглядали небезпечними.

Нічого з цього дизайну не отримало нагород. Але він зробив інше цінне: зменшив координаційні витрати під час простою. Люди могли довіряти формі документа. Коли форма документа стабільна, команди витрачають обмежений бюджет стресу на систему, а не на сторінку.

Поширені помилки: симптом → корінна причина → виправлення

Це те, що з’являється у формах зворотного зв’язку як «доки погані». Симптоми реальні. Виправлення зазвичай не складні. Потрібно просто, щоб хтось поставився до документації як до продакшну.

1) Симптом: «Я скопіював команду і вона не спрацювала»

Корінна причина: блоки коду переносяться, або типографія замінила лапки/тире, або існують невидимі символи (NBSP, нуль-ширинний пробіл).

Виправлення: примусити white-space: pre і overflow-x: auto; вимкнути типографічні заміни в коді; додати лінтер для NBSP і розумних лапок у кодових блоках.

2) Симптом: «Цю сторінку виснажливо читати»

Корінна причина: рядки надто довгі; недостатня висота рядка; низький контраст; щільні абзаци без структури.

Виправлення: обмежити measure до ~72ch; встановити line-height ~1.5; трохи збільшити відступи між абзацами; розбити довгі секції значущими H2/H3 заголовками.

3) Симптом: «TOC марний»

Корінна причина: заголовки загальні («Overview», «Details») або ієрархія надто глибока/хаотична.

Виправлення: перейменуйте заголовки на орієнтовані на завдання формулювання; тримайте основний контент у H2/H3; розділіть сторінки, що потребують H4/H5.

4) Симптом: «Результати пошуку не допомагають»

Корінна причина: заголовки не містять слів, що шукають користувачі; ключові терміни поховані в прозі; гіпенізація/м’які розриви впливають на запам’ятовані терміни.

Виправлення: пишіть заголовки, що відповідають намірам користувача; включайте ключові терміни на початку; уникайте гіпенізації токенів; забезпечте коректну індексацію коду й заголовків.

5) Симптом: «Посилання в старих тікетах ведуть не туди»

Корінна причина: автогенеровані ID-якорі змінилися при редагуванні заголовків; контент реорганізовано без редіректів/псевдонімів.

Виправлення: використовуйте явні, стабільні ID; додавайте alias-якорі; ставтеся до перейменувань заголовків як до змін API з підтримкою міграції.

6) Симптом: «Таблиці й CLI-вивід не вирівнюються»

Корінна причина: шрифт коду не справді monospace, або всередині pre використовується пропорційний шрифт; таби рендеряться по-різному.

Виправлення: задайте надійний monospace-стек для pre/code; конвертуйте таби в пробіли; явно вкажіть tab-size.

7) Симптом: «Заголовки відчуваються як випадкові жирні речення»

Корінна причина: недостатній типографічний контраст; відступи заголовків занадто тісні; вага заголовка надто легка; стиль великими літерами зменшує впізнаваність форми.

Виправлення: збільшити різницю розміру/ваги; додати вертикальний ритм; уникати великих літер для довгих заголовків; забезпечити сканованість заголовків.

8) Симптом: «Мобільний макет — хаос»

Корінна причина: блоки коду намагаються вміститися на екрані через перенос; довгі слова виходять за межі; гіпенізація в заголовках.

Виправлення: дозволити коду прокручуватись горизонтально; додати overflow-wrap: anywhere тільки для прозових блоків; вимкнути гіпенізацію для заголовків і коду.

Чеклісти / покроковий план

Чекліст: типографічні дефолти для платформи документації

  • Контейнер прозового тексту max-width: 65–75ch.
  • Розмір шрифту тіла: 16–18px залежно від шрифту; line-height: 1.5–1.7.
  • Нерівний правий край; уникайте повного вирівнювання по ширині.
  • Сходинка заголовків: H2 явно сильніший за текст; H3 відрізняється, але не дратує.
  • Блоки коду: white-space: pre, overflow-x: auto, кнопка копіювання копіює raw-текст.
  • Шрифт коду: чіткий monospace-стек; у операційних доках уникайте фірмових лігатур.
  • Гіпенізація: вимкнена глобально, якщо ви не протестували; якщо увімкнено — обмежена прозою.
  • Стабільні анкори: явні ID або стратегія псевдонімів; ставтеся до перейменувань заголовків як до breaking change.
  • Лінт: ловіть NBSP, розумні лапки в коді, відсутні мови fence, таби в YAML/коді.

Покроковий план: виправити існуючий безладний сайт документів за тиждень

  1. День 1: вимірювання і переноси. Додайте max-width: 72ch до основного контейнера. Виправте блоки коду, щоб вони перестали переноситися.
  2. День 2: заголовки і TOC. Уніфікуйте ієрархію заголовків. Розділіть сторінки, що потребують H4/H5, на окремі сторінки або секції.
  3. День 3: цілісність коду. Вимкніть розумну типографію в коді. Додайте лінт для NBSP/розумних лапок. Додайте кнопку «копіювати raw», якщо платформа це підтримує.
  4. День 4: стабільність якорів. Перестаньте покладатися на автогенерацію ID, якщо можете. Додайте псевдоніми для часто лінкованих заголовків.
  5. День 5: рішення по гіпенізації. Або вимкніть гіпенізацію, або обмежте її прозою. Підтвердіть, що lang встановлено й узгоджено.
  6. День 6: доступність і контраст. Перевірте контраст кольору для тексту і заголовків. Зробіть фокуси видимими для клавіатурної навігації.
  7. День 7: операційний рев’ю. Виберіть три руковідники, що використовуються в реальних інцидентах. Програйте їх: копіюйте/вставляйте команди, перевіряйте вивід, дивіться, чи можете знайти потрібний розділ за 10 секунд.

Як запобігти регрессії

Регресії типографіки підступні, бо ніхто не напише тікет «line-height впав з 1.55 до 1.3». Вони напишуть «доки стали гірші». Запобігайте цим автоматизацією:

  • Огляд CSS: зміни в pre, code, розмірах заголовків і ширині контейнера вимагають погодження.
  • Контент-лінт у CI: відхиляти NBSP і розумні лапки в кодових блоках.
  • Візуальні тести регресу для кількох критичних сторінок (руковідники).

Питання й відповіді

1) Яка найкраща довжина рядка для технічної документації?

Для прозових частин орієнтуйтеся на 60–80 символів на рядок. Якщо потрібен один дефолт — використовуйте 72ch для основного контейнера. Це золота середина для сканування й зменшення втоми.

2) Чи повинні блоки коду переноситися на мобільних?

Ні. Перенос змінює значення й ламає копіювання. Дозвольте блокам коду горизонтально прокручуватись. Якщо команда занадто довга для мобільного, надайте коротшу альтернативу або файл-скрипт.

3) Гіпенізація — добре чи погано?

Переважно погано в інженерних доках. Вона може допомогти в вузьких прозових колонках, але має бути вимкнена для заголовків, коду, посилань і токенів. Якщо увімкнено — жорстко обмежте область і протестуйте.

4) Чому не вирівнювати по ширині? Це виглядає чистіше.

Вирівнювання по ширині часто породжує нерівномірні інтервали («річки») в вебі, особливо у вузьких колонках і з технічними термінами. Нерівний правий край читабельніший і менш крихкий.

5) Як заголовки впливають на надійність?

Заголовки — це навігаційні API. Вони забезпечують TOC, релевантність пошуку й вхідні посилання з тікетів. Погані заголовки сповільнюють реагування на інциденти. Нестабільні анкори ламають робочі процеси.

6) Який моноширинний шрифт нам використовувати?

Обирайте системний monospace-стек, якщо немає сильної причини інакше. Оптимізуйте для чіткості гліфів і рендерінгу на малих розмірах. Уникайте шрифтів, де 0/O або 1/l/I неоднозначні.

7) Чи використовувати лігатури в коді?

Для операційних документів я рекомендую ні. Лігатури роблять код гарним, але можуть збивати читачів і іноді впливати на вибір/копіювання. Лігатури підходять для редакторів, не для руковідників.

8) Як запобігти зламаним якиманям, коли заголовки змінюються?

Використовуйте явні ID де можливо. Якщо платформа автогенерує анкори, введіть механізм псевдонімів (приховані анкори) для часто лінкованих розділів. Ставтеся до перейменувань заголовків як до breaking change.

9) Наші доки в Markdown. Чи варто жорстко обгортати рядки на 80 символів?

Залежить від інструментів. Жорстке обгортання може покращити дифи й рев’ю, але також створити дивні переноси, якщо рендерер трактує їх як жорсткі. Якщо жорстко обгортаєте, переконайтеся, що Markdown-процесор використовує нормальні правила обгортання абзаців.

10) Яка найбільша за впливом зміна?

Припиніть переносити блоки коду й обмежте прозу за виміром. Ці дві зміни усувають дивну кількість операційних терть.

Висновок: наступні кроки, що справді працюють

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

Зробіть наступне

  1. Встановіть основний контейнер контенту на ~72ch max-width і адекватний line-height.
  2. Зробіть блоки коду непереносними з горизонтальною прокруткою. Додайте кнопку копіювання, якщо можете.
  3. Вимкніть гіпенізацію в заголовках, коді, посиланнях і токеноподібних елементах. Розгляньте повне вимкнення.
  4. Уніфікуйте ієрархію заголовків: осмислені H2, корисні H3, мінімальна глибина.
  5. Додайте CI-лінти для розумних лапок, NBSP і відсутніх мов у fence-кодах.
  6. Виберіть три руковідники і програйте їх як інциденти. Якщо це дратує в спокійній кімнаті, воно буде небезпечним о 3-й ночі.

Зробіть сторінку нудною. Зробіть її послідовною. Зробіть її безпечною для копіювання. Ось як документація заробляє довіру, а довіра — це найрідкісніший ресурс у продакшн-системах.

← Попередня
Debian 13: auditd без знищення SSD — практичні налаштування для розумного аудиту
Наступна →
NVIDIA vs AMD vs Intel: що потрібно конкуренції, щоб зберегти здоровий глузд

Залишити коментар