В MapLibre GL JS текст на карте не использует системные шрифты
браузера напрямую: вся типографика рендерится через заранее
подготовленные векторные глифы, которые загружаются с сервера и
компилируются в SDF-изображения для WebGL. Именно поэтому механизм
резервных (fallback) шрифтов здесь отличается от привычного CSS
font-family.
В основе работы лежит концепция fontstack — упорядоченного списка шрифтов, которые последовательно проверяются при отсутствии нужных символов в первом варианте.
В слоях символов (symbol layer) параметр
layout.text-font задаёт массив шрифтов:
"text-font": ["Noto Sans Regular", "Arial Unicode MS Regular"]
Каждый элемент — это не локальный системный шрифт, а имя набора глифов, доступного на сервере glyphs. При рендеринге MapLibre GL JS запрашивает глифы именно по этому имени.
Порядок имеет критическое значение: первый доступный fontstack используется для каждого конкретного символа, если он содержит нужный Unicode-глиф.
Если символ отсутствует в первом шрифте, движок автоматически переходит к следующему элементу массива.
MapLibre GL JS не оперирует TTF/OTF файлами в рантайме. Вместо этого используется сервер глифов, который возвращает PBF-контейнеры с растеризованными символами.
Типичный запрос выглядит так:
/fonts/{fontstack}/{range}.pbf
где:
fontstack — имя набора шрифтов (например,
Noto Sans Regular)range — диапазон Unicode-символов (например,
0-255)Ключевой момент: fallback реализуется не на уровне браузера, а на уровне выбора glyph range и fontstack.
Если символ отсутствует во всех указанных fontstack:
MapLibre не пытается «склеить» текст из локальных шрифтов устройства — всё зависит от доступности глифов на сервере.
Типичная стратегия включает несколько уровней:
"text-font": [
"Inter Regular",
"Noto Sans Regular",
"Arial Unicode MS Regular"
]
Такой порядок позволяет контролировать внешний вид, сохраняя поддержку максимального количества символов.
Кириллица часто становится источником проблем, если используется узкий латинский fontstack.
Например:
"text-font": ["Roboto Regular", "Open Sans Regular"]
Оба шрифта могут не содержать полного набора кириллических символов, если сервер glyphs был собран без поддержки расширенных диапазонов.
Решение — использование шрифтов с Unicode coverage:
Для китайского, японского и корейского текста fallback становится критически важным из-за огромного количества глифов.
Обычно применяется стратегия разделения:
"text-font": [
"Noto Sans SC Regular",
"Noto Sans JP Regular",
"Noto Sans KR Regular",
"Noto Sans Regular"
]
Каждый fontstack содержит специализированный набор глифов, и MapLibre выбирает первый подходящий.
Особенность CJK в том, что один символ может отсутствовать даже в «универсальном» шрифте, поэтому fallback цепочка должна быть длиннее и более специализированной.
Символы вроде:
часто отсутствуют в базовых шрифтах. Если fontstack не покрывает Latin Extended диапазоны, MapLibre будет последовательно переходить к следующему набору.
Это особенно заметно в смешанных слоях, где названия городов содержат разные языковые системы.
Fallback зависит не только от text-font, но и от того,
как сервер генерирует glyph PBF.
Если сервер содержит только:
то даже корректный fontstack не поможет.
Типичный production endpoint должен включать:
/fonts/Noto Sans Regular/{0-255}.pbf
/fonts/Noto Sans Regular/{256-511}.pbf
/fonts/Noto Sans Regular/{CJK ranges}.pbf
Отсутствие диапазонов ломает fallback на уровне данных, а не логики клиента.
MapLibre использует Signed Distance Field (SDF) для текста. Это означает:
Fallback-шрифты должны быть согласованы по метрикам:
Иначе текст «прыгает» при переходе между fontstack.
"text-font": ["Arial", "Helvetica"]
Ошибка: MapLibre не использует локальные системные шрифты.
"text-font": ["NotoSans"]
Но сервер ожидает:
"Noto Sans Regular"
Результат — отсутствие текста.
Если указан только один шрифт, любые отсутствующие символы превращаются в пустые квадраты.
Слишком длинный список:
"text-font": ["A", "B", "C", "D", "E", "F"]
увеличивает стоимость поиска glyph range.
Каждый fontstack увеличивает вероятность дополнительных запросов:
Оптимальная стратегия:
На практике наиболее устойчивый подход — использование семейства Noto:
Они покрывают большинство Unicode-блоков и минимизируют необходимость сложных fallback-цепочек.
В больших картографических системах это становится стандартом, так как обеспечивает предсказуемый результат вне зависимости от языка данных.
Если строка содержит:
"Москва Tokyo 北京"
MapLibre разбивает текст на glyph runs:
Fallback применяется не к строке целиком, а к отдельным сегментам, что позволяет корректно комбинировать разные системы письма в одном label.
Fallback определяется исключительно в:
layout: {
"text-font": [...]
}
CSS-правила не влияют на выбор шрифтов. Любые
font-family из DOM игнорируются, поскольку WebGL-canvas
изолирован от браузерного текстового рендеринга.
Это фундаментальное отличие от HTML-типографики, где fallback управляется CSS каскадом.
Надёжная конфигурация обычно строится по принципу:
Такой подход снижает вероятность «провалов» текста и обеспечивает стабильный визуальный результат при любых данных слоя.