Порядок отрисовки элементов в SVG определяется не свойством
z-index в привычном смысле из CSS, а моделью “painting
order” — последовательностью, в которой узлы описаны в дереве документа.
Каждый последующий элемент визуально перекрывает предыдущий, если они
пересекаются и находятся в одном и том же контексте наложения.
SVG не использует полноценный z-index для большинства
графических элементов. Вместо этого действует строгое правило:
<g>) влияет на целый набор
дочерних элементов;Это означает, что изменение визуального слоя чаще всего достигается не стилями, а перестановкой элементов в дереве.
Пример логики отрисовки:
<svg>
<rect x="0" y="0" width="100" height="100" fill="red" />
<rect x="30" y="30" width="100" height="100" fill="blue" />
</svg>
Синий прямоугольник будет поверх красного, потому что он объявлен позже.
Свойство z-index работает только в ограниченных
сценариях:
position, opacity < 1,
transform или isolation.Даже в этих случаях поведение отличается от HTML:
z-index влияет на контейнер, а не на отдельные SVG
primitive элементы;<svg> порядок DOM всё ещё
доминирует.Таким образом, попытка управлять слоями через CSS в SVG часто приводит к непредсказуемому результату.
<g>Группы <g> являются ключевым инструментом
управления слоями.
Каждая группа:
<svg>
<g id="background">
<rect width="400" height="200" fill="#eee" />
</g>
<g id="foreground">
<circle cx="100" cy="100" r="40" fill="black" />
</g>
</svg>
Группа foreground всегда будет поверх
background, если расположена ниже в DOM.
В сложных графиках возникают ситуации, когда визуальная логика требует независимого управления слоями:
SVG не предоставляет встроенной системы слоёв, поэтому используется комбинация:
<svg> внутри одного контейнера.Библиотека Nivo строит графики на SVG (или Canvas в отдельных режимах), и управление слоями является частью её архитектуры.
В Nivo слойность определяется не CSS, а структурой render pipeline.
Типичная схема слоёв в графиках:
Каждый из этих уровней реализуется как отдельная группа или отдельный render layer.
Во многих компонентах Nivo используется проп layers,
который задаёт порядок отрисовки:
Пример логики:
layers={[
'grid',
'axes',
'bars',
'markers',
'legends'
]}
Изменение порядка мгновенно влияет на визуальную иерархию без изменения внутренних компонентов.
Визуализация данных требует строгого разделения уровней:
Если нарушить порядок:
SVG не исправляет эти конфликты автоматически, поэтому ответственность лежит на структуре слоёв.
Дополнительный уровень сложности создают:
clipPathmaskdefsuseЭти элементы влияют не только на видимость, но и на порядок композиции.
Например, clipPath применяется до финального
отображения, но не участвует в визуальном stacking order. Это часто
вызывает путаницу: элемент может быть “поверх”, но визуально
обрезан.
В Nivo интерактивность часто реализуется через:
Такие слои почти всегда должны находиться последними в DOM.
Пример логики:
onMouseMove;Tooltip и модальные подсказки часто не находятся внутри SVG вообще.
Причины:
z-index.Это создаёт гибридную модель:
isolationCSS свойство isolation: isolate создаёт новый stacking
context, что иногда используется для контроля наложения SVG внутри HTML
контейнеров.
Это полезно в случаях:
Однако внутри самого SVG это не заменяет DOM-порядок.
Любое применение transform:
В SVG это особенно важно, потому что:
Нарушения логики stacking order обычно возникают из-за:
z-index на
SVG-элементах;layers в Nivo;append вместо контролируемой вставки в
DOM.Поскольку Nivo построен на React, порядок элементов часто определяется:
React reconciliation напрямую влияет на итоговый DOM SVG, а значит и на визуальный stacking order.
Устойчивый подход к проектированию SVG-графиков:
Такая структура снижает зависимость от случайного DOM-порядка и делает визуализацию предсказуемой.
Даже если элемент визуально прозрачен:
Это особенно важно для Nivo charts, где прозрачные области часто используются для hover-зон.
Отсутствие классического z-index приводит к тому, что:
В результате SVG-графики, включая Nivo, опираются на структурную композицию, а не на каскадные правила наложения.