8

Подскажите, пожалуйста, почему не работает viewBox у svg(изображение крестика):

<svg style="border: 1px solid red" viewBox="0 0 24 24">
   <path fill="currentColor" d="M13.205 12L20 5.205 18.795 4 12 10.795 5.205 4 4 5.205 10.795 12 4 18.795 5.205 20 12 13.205 18.795 20 20 18.795 13.205 12z"></path>
</svg>

В описании написано: "Аттрибут viewBox определяет расположение и размеры окна отображения SVG. Значение атрибута viewBox — это набор четырех чисел: min-x, min-y, width и height,"

В моем случае координаты равны 0 и 0. А значения width и height по 24px. Но почему-то это изображение рендерится очень большим. Почему так происходит и как это исправить?

Пример: https://jsfiddle.net/0esaf1rd/1/

Спасибо!

Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384
Pavel
  • 467
  • всё правильно - укажите width либо оберните блоком div и для него укажите width вот так https://jsfiddle.net/f410ug9s/ – Резидент Казахстана Oct 13 '20 at 08:17
  • @MaximLensky да, так работает. Но какой смысл в viewBox, где я указываю 24px? И почему, если я уберу этот атрибут изображение станет маленьким, а с этим атрибутом большим? – Pavel Oct 13 '20 at 08:19
  • viewBox это внутренняя сетка для самого SVG ...но не для html - это примерно как полотно на котором вы разложите гербарий - то что вылезет за полотно ОБРЕЖЕТСЯ – Резидент Казахстана Oct 13 '20 at 08:21
  • или скажу по другому - к примеру если вы не указывая viewBox напишите width для svg то часть изображения потеряете так как его не будет видно ..viewBox это своего рода полотно на котором вы заранее рисуете руками или же в программе или же программно – Резидент Казахстана Oct 13 '20 at 08:25
  • @MaximLensky Немного не понятно. Я читал, что SVG рендерится на бесконечном холсте, но видимая часть хоста соответствует размерам SVG элемента. Размеры, как я понимаю можно выставить атрибутами width и height, как вы сделали выше. Все, что не влезет, то обрежется исходя из описания. А viewBox насколько я понял управляет размерами этого SVG и масштабом. Т.е. я могу его уменьшить и изображение не обрежется. – Pavel Oct 13 '20 at 08:27
  • нет - напишите просто svg без width и height и без viewBox и добавьте ему border увидите его настоящий размер будет что то наподобие canvas – Резидент Казахстана Oct 13 '20 at 08:28
  • и даже если укажите ширину и высоту ему оно не будет таковым без viewBox - viewBox это внутренняя персектива то есть то полотно на котором располагаются все внутренние элементы составляющих всю картину SVG – Резидент Казахстана Oct 13 '20 at 08:31
  • @MaximLensky загадка!) Честно говоря, не понимаю, почему так работает. Буду читать и разбираться. Спасибо! – Pavel Oct 13 '20 at 08:32
  • 1
    https://www.youtube.com/watch?v=zx_dhZtNJrY – Резидент Казахстана Oct 13 '20 at 08:52
  • @MaximLensky Спасибо, Максим! – Pavel Oct 13 '20 at 17:00
  • добавлю свои 5 копеек: viewbox это "окно" через которое Вы смотрите на векторное изображение, оно не имеет отношения к тому, как в дальнейшем эта картинка будет позиционирована и отмасштабирована, это легче понять если начать изменять первые 2 числа, которые у Вас 0-0 – Stranger in the Q Oct 13 '20 at 17:41
  • @Pavel Добавил ссылки на связанные вопросы по viewBox, если тема заинтересовала, то интересно будет посмотреть – Alexandr_TT Oct 13 '20 at 19:30
  • 1
    @Alexandr_TT огромное Вам спасибо! – Pavel Oct 13 '20 at 19:35
  • @Pavel вот в этом ответе есть ссылка на пример, как можно на основе viewBox сделать интересный параллакс – Alexandr_TT Oct 13 '20 at 19:41

2 Answers2

8

В моем случае координаты равны 0 и 0. А значения width и height по 24px. Но почему-то это изображение рендерится очень большим. Почему так происходит и как это исправить?

На словах трудно объяснить, как работают совместно viewport (это width и height в шапке SVG) и viewBox. Поэтому я попытаюсь сделать это на примерах.
Возможно я повторю какие-то моменты, которые комментировал @MaximLensky и @Eva в своем ответе, благодарность им за это!

Любое SVG изображение имеет реальные физические размеры, то есть те размеры, как оно нарисовано в векторном редакторе или в аналогичном коде, написанном в текстовом редакторе.

Узнать эти размеры можно с помощью метода JS getBBox()

<svg style="border: 1px solid red" viewBox="0 0 24 24">
    <path id="cross" fill="currentColor" d="M13.205 12L20 5.205 18.795 4 12 10.795 5.205 4 4 5.205 10.795 12 4 18.795 5.205 20 12 13.205 18.795 20 20 18.795 13.205 12z">
    </path>
    </svg>
    <script>
    let bb = cross.getBBox();
    console.log(bb);
    </script>

Видим, что 4px - отступ слева + 16x ширина самого изображения + 4px отступ справа, то есть физический размер ширины иконки составляет 24px, тоже самое и по высоте 24px.

Выбран viewBox="0 0 24 24" то есть изображение иконки захвачено полностью, а вот как оно будет показано пользователю зависит от размеров width, height пользовательского окна просмотра.(от viewport).

  1. Если width, height не указаны в шапке SVG, то браузер устанавливает их равными 100% и растягивает изображение на весь экран, как в вашем случае
  2. width, height равны viewBox
    Изображение будет показано, как есть, без изменения физических размеров 24x24px

    <svg width="24" height="24" viewBox="0 0 24 24" style="border: 1px solid red">
    <path id="cross" fill="currentColor" d="M13.205 12L20 5.205 18.795 4 12 10.795 5.205 4 4 5.205 10.795 12 4 18.795 5.205 20 12 13.205 18.795 20 20 18.795 13.205 12z">
    </path>
    </svg>
    <script>
    let bb = cross.getBBox();
    console.log(bb);
    </script>
  1. Увеличивая width height допустим в два раза больше, чем размеры viewBox мы тем самым увеличим изображение в два раза.
    Другими словами 1px viewBox будет растянут до двух пикселей viewport

    <svg width="48" height="48" viewBox="0 0 24 24" style="border: 1px solid red">
    <path id="cross" fill="currentColor" d="M13.205 12L20 5.205 18.795 4 12 10.795 5.205 4 4 5.205 10.795 12 4 18.795 5.205 20 12 13.205 18.795 20 20 18.795 13.205 12z">
    </path>
    </svg>
    <script>
    let bb = cross.getBBox();
    console.log(bb);
    </script>
  1. width, height < viewBox в два раза
    При этом два пикселя viewBox сжимаются до одного пикселя viewport, поэтому изображение уменьшается в два раза

<svg width="12" height="12" viewBox="0 0 24 24" style="border: 1px solid red">
    <path id="cross" fill="currentColor" d="M13.205 12L20 5.205 18.795 4 12 10.795 5.205 4 4 5.205 10.795 12 4 18.795 5.205 20 12 13.205 18.795 20 20 18.795 13.205 12z">
    </path>
    </svg>
    <script>
    let bb = cross.getBBox();
    console.log(bb);
    </script>

Более подробно о взаимодействии viewport c viewBox

Обратите внимание, что, как бы мы не манипулировали размерами выводимого изображения, физические размеры его, на самом деле остаются прежними. Это показывает getBBox() в каждом примере.

Почему в спрайтах иконок и других SVG изображениях не указывают width, height

Причина проста, - svg, как правило помещают в родительский контейнер и задавая размеры этого контейнера заполняют его полностью SVG

.container{
width:64px;
height:64px;
}
<div class="container">
    <svg  viewBox="0 0 24 24" style="border: 1px solid red">
    <path id="cross" fill="currentColor" d="M13.205 12L20 5.205 18.795 4 12 10.795 5.205 4 4 5.205 10.795 12 4 18.795 5.205 20 12 13.205 18.795 20 20 18.795 13.205 12z">
    </path>
    </svg>
</div>  
    

Чтобы сделать изображение адаптивным, достаточно указать размеры родительского контейнера в относительных единицах

.container{
width:3vw;
height:3vh;
}
<div class="container">
    <svg  viewBox="0 0 24 24" style="border: 1px solid red">
    <path id="cross" fill="currentColor" d="M13.205 12L20 5.205 18.795 4 12 10.795 5.205 4 4 5.205 10.795 12 4 18.795 5.205 20 12 13.205 18.795 20 20 18.795 13.205 12z">
    </path>
    </svg>
</div>

Связанные ответы:

  1. Как взаимодействуют между собой viewport и viewBox
  2. Использование параметров viewBox для масштабирования изображений
  3. Как работает viewBox?
Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384
6

Изображение отображается большим, потому что вы ему не задали width/height. Без этих свойств SVG по умолчанию отображается на всю ширину окна браузера.

Не путайте width/height у viewbox с width/height всего SVG.

0xdb
  • 51,614
Eva
  • 1,889
  • 8
  • 26