ViewBox не работает: почему SVG не масштабируется и как это исправить

Атрибут viewBox перестаёт влиять на отображение SVG чаще всего из-за четырёх конкретных причин: опечатки в регистре (viewbox вместо viewBox), жёстко заданных width и height в пикселях, лишнего пробела или запятой внутри значения и конфликта с CSS-стилями, которые переопределяют размеры элемента. Проверка начинается именно с этих пунктов — они закрывают подавляющее большинство случаев, когда масштабирование векторной графики «ломается».

Ниже разберём, как устроен механизм viewBox, почему браузер может его игнорировать и что проверить пошагово, чтобы SVG снова масштабировался корректно. Материал ориентирован на тех, кто верстает вручную или встраивает иконки и иллюстрации в HTML-страницу.

Как работает viewBox и почему он «молчит»

Атрибут viewBox задаёт внутреннюю систему координат SVG: четыре числа — min-x, min-y, width, height. Браузер берёт содержимое в этих координатах и растягивает (или сжимает) его на фактический размер элемента <svg>. Если фактический размер не определён или задан жёстко, эффект масштабирования может визуально отсутствовать — отсюда и ощущение, что viewBox «не работает».

Важно понимать: viewBox сам по себе не меняет размер элемента на странице. Он лишь определяет, какая часть внутреннего «холста» будет показана и как она впишется в те габариты, которые элемент получил из атрибутов width/height или из CSS. Когда эти габариты конфликтуют с ожиданиями, картинка обрезается, растягивается или не реагирует на изменение viewBox.

Проверка синтаксиса: регистр и формат значения

Первая и самая частая ошибка — регистр букв. SVG чувствителен к регистру атрибутов: корректно пишется viewBox с заглавной «B». Варианты viewbox или ViewBox браузер просто проигнорирует, причём без каких-либо сообщений об ошибке в консоли.

Вторая группа проблем — формат значения. Числа должны разделяться пробелами или запятыми, но не смесью, которая ломает парсинг в некоторых случаях, и их должно быть ровно четыре:

<svg viewBox="0 0 100 100">

<circle cx="50" cy="50" r="40"/>

</svg>

  • ✅ Проверьте, что атрибут написан именно как viewBox — с заглавной B.
  • px.
  • 🧹 Уберите лишние пробелы в начале и конце значения, а также двойные пробелы.
  • 🚫 Не используйте отрицательную ширину или высоту (третье и четвёртое числа) — такое значение делает viewBox невалидным, и браузер его отбрасывает.
⚠️ Внимание: если третье или четвёртое число viewBox равно нулю или отрицательно, браузер считает весь атрибут недействительным и рендерит SVG так, будто viewBox вообще не задан. Это выглядит как «атрибут не работает», хотя причина — в значении.

Конфликт с width, height и CSS

Даже корректный viewBox не даст ожидаемого эффекта, если размеры элемента заданы так, что масштабирование незаметно. Типичный сценарий: в SVG жёстко прописаны width="500" height="500", а затем через CSS элементу назначается другой размер — и разработчик путается, какой из них «победил».

Приоритет здесь такой: CSS-правила переопределяют атрибуты width и height. Если в стилях написано svg { width: 100%; height: auto; }, а в разметке стоят фиксированные пиксели, работать будут именно стили. Когда height не задан ни в атрибутах, ни в CSS, браузер вычисляет его по соотношению сторон из viewBox — и это как раз тот случай, когда механизм работает «как задумано».

📊 Что стало причиной проблемы с viewBox в вашем случае?
Опечатка в регистре (viewbox)
Конфликт с width/height или CSS
Неверные координаты внутри viewBox
Проблема в preserveAspectRatio

Практический приём: временно уберите width и height из разметки и стилей, оставив только viewBox, и задайте элементу размер через один-единственный источник (например, CSS). Так вы исключите гонку источников размеров и увидите чистое поведение viewBox.

Роль preserveAspectRatio

Атрибут preserveAspectRatio управляет тем, как содержимое viewBox вписывается во вьюпорт, когда пропорции не совпадают. Значение по умолчанию — xMidYMid meet: содержимое масштабируется с сохранением пропорций и центрируется. Если вы ожидали, что картинка растянется на весь контейнер без полей, а видите пустые полосы — дело именно в этом поведении, а не в «сломанном» viewBox.

Чтобы растянуть содержимое без сохранения пропорций, используется значение none. Чтобы заполнить весь вьюпорт с обрезкой выходящих частей — срезы вида xMidYMid slice. Выбор зависит от задачи: для иконок обычно важны пропорции, для фоновых декоративных элементов иногда допустимо растяжение.

Значение preserveAspectRatioПоведениеКогда использовать
xMidYMid meet (по умолчанию)Вписывает целиком, возможны поляИконки, логотипы
xMidYMid sliceЗаполняет вьюпорт, края обрезаютсяФоны, обложки
noneРастягивает без сохранения пропорцийДекоративные элементы
xMinYMin meetВписывает, прижимает к левому верхнему углуВыравнивание к краю

Пошаговая диагностика: чек-лист

Если быстрая проверка синтаксиса не помогла, пройдитесь по шагам ниже. Каждый шаг устраняет один класс причин, и после каждого стоит обновить страницу и посмотреть на результат.

☑️ Диагностика viewBox за 6 шагов

Выполнено: 0 / 6

Отдельно стоит сказать про координаты содержимого: если графика нарисована в диапазоне, который не пересекается с viewBox, элемент отобразится пустым. Например, при viewBox="0 0 100 100" круг с центром cx="500" окажется за пределами видимой области. Это не ошибка атрибута — просто содержимое находится «за кадром». Откройте исходный файл SVG и сверьте реальные координаты фигур с диапазоном viewBox.

Особые случаи: вложенные SVG, символы и скрипты

Элементы <symbol> и вложенные <svg> имеют собственный viewBox, который не наследуется от родителя. Если иконка подключается через <use> и выглядит обрезанной, проверьте viewBox именно на <symbol> внутри спрайта, а не только на внешнем <svg>.

Ещё один источник путаницы — JavaScript. Библиотеки и слайдеры иногда выставляют размеры SVG динамически через setAttribute или inline-стили, перезаписывая то, что вы указали в разметке. Если viewBox «сбрасывается» после загрузки страницы, поищите в коде обращения к элементу и проверьте, не меняет ли скрипт его атрибуты или стили.

Почему SVG из редактора ведёт себя иначе

Графические редакторы (Illustrator, Figma, Inkscape) при экспорте часто добавляют фиксированные width и height, а иногда — трансформации transform на группах. Эти transform смещают содержимое относительно viewBox, из-за чего ручная правка viewBox даёт неожиданный результат. Перед отладкой имеет смысл прогнать файл через оптимизатор SVG, который упрощает структуру, но проверяйте результат визуально — агрессивная оптимизация может менять геометрию.

⚠️ Внимание: при вставке SVG через тег <img> или как CSS-фон вы не сможете менять его внутренние атрибуты со страницы — такой SVG изолирован. Все правки viewBox в этом случае делаются только в самом файле .svg.

Частые вопросы

Почему viewBox игнорируется, хотя написан правильно?

Проверьте, нет ли второго атрибута viewBox на том же элементе — дубликат может прийти из шаблонизатора или скрипта. Также убедитесь, что вы смотрите на тот же самый элемент: во вложенных SVG действует собственный viewBox, а не родительский.

Можно ли использовать px или проценты внутри viewBox?

Нет. Значение viewBox — это четыре безразмерных числа в пользовательских единицах системы координат SVG. Единицы измерения вроде px или % делают значение невалидным.

SVG растягивается с полями по бокам — это из-за viewBox?

Скорее всего, причина в preserveAspectRatio: при несовпадении пропорций viewBox и вьюпорта поведение по умолчанию (meet) вписывает содержимое с полями. Либо подгоните пропорции контейнера под viewBox, либо измените режим вписывания.

Работает ли viewBox у элементов внутри SVG, например у <g>?

Нет, атрибут viewBox поддерживается только у элементов, создающих собственный вьюпорт: <svg>, <symbol>, а также у некоторых других (например, <marker>, <pattern>, <view>). У групп <g> он не действует — для трансформации групп используйте атрибут transform.

Как быстро проверить, что именно видит браузер?

Выделите элемент в DevTools и посмотрите вкладку атрибутов и вычисленных стилей. Если viewBox присутствует в разметке, но результат не меняется, почти наверняка дело в размерах вьюпорта или в координатах содержимого, а не в самом атрибуте.