Как изменить размеры svg через css

Управление размерами — тема важная, и чтобы максимально использовать возможности SVG, нужно хорошо понимать как всё работает.

Управление размерами — тема важная, и чтобы максимально использовать возможности SVG, нужно хорошо понимать как всё работает.

Спецификация.

Вьюпорт

Содержимое SVG-элемента отрисовывается на бесконечном холсте и может быть сколь угодно большого размера, но видимая часть холста соответствует размерам SVG-элемента. Эта область отрисовки называется viewport (вьюпорт).

SVG позволяет управлять как размерами вьюпорта, так и поведением содержимого относительно него: оно может обрезаться или показываться полностью, может растягиваться с потерей пропорций или стараться уместиться целиком, даже если при этом появляются пустые поля. Этим поведением можно управлять с помощью атрибутов.

Если просто вставить SVG на страницу и не задавать ему никакие размеры, он отобразится размером 300px на 150px, что не поместилось — обрежется:

Ширина и высота

Шириной и высотой элемента можно управлять стандартными свойствами width и height:

<svg width="350" height="200">
  ...
</svg>

Их можно задавать как атрибутами, так и в CSS:

.mysvg {
  width: 350px;
  height: 200px;
}

Для размеров в пикселях, задаваемых в атрибутах, единицы измерения можно не указывать.

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

viewBox

Похожим образом не изменяя размеры содержимого ресайзится iframe, но в случае с SVG это поведение можно изменить, если определить размеры области с помощью свойства viewBox:

<svg width="350" height="200"
    viewBox="0 0 180 180">
  ...
</svg>

Первые два значения — координаты X и Y верхнего левого угла отображаемой области, последние два — ширина и высота. viewBox задаётся только атрибутом.

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

viewBox можно использовать, например, для кадрирования изображения, чтобы показывать не всю картинку, а только какую-то её часть:

Это очень простое демо, вот пример посложнее от Sarah Drasner.

Интересно, что если у SVG нет размеров, но задан viewBox, изображение займёт собой всё доступное пространство:

<svg viewBox="0 0 180 180">
  ...
</svg>

Это поведение может стать проблемой: если размеры у иконок задаются в стилях, а они не загрузились — страница может превратиться в парад гигантских SVG-иконок. Чтобы этого не произошло, всегда явно задавайте в атрибутах SVG ширину и высоту, их потом легко переопределить в CSS.

preserveAspectRatio

Как мы видели в примере выше, если у SVG заданы размеры и viewBox, содержимое будет сжиматься и растягиваться с сохранением пропорций, чтобы поместиться целиком, но этим поведением тоже можно управлять — с помощью свойства preserveAspectRatio (оно задаётся только атрибутом).

Например, с помощью значения none можно указать, что сохранять пропорции не нужно:

<svg width="350" height="200"
    viewBox="0 0 180 180"
    preserveAspectRatio="none"
    >
  ...
</svg>

SVG с viewBox и preserveAspectRatio='none' ведёт себя очень похоже на img: при изменении размеров содержимое масштабируется под размеры вьюпорта не сохраняя пропорции.

none будет полезно для резиновых фонов:

Остальные значения preserveAspectRatio состоят из двух частей: первая задаёт выравнивание, вторая — поведение элемента относительно вьюпорта.

Выравнивание задаётся одним значением, определяющим положение по вертикали и по горизонтали, например: xMaxYMin. Для обеих осей можно задать положение в начале, в середине и в конце:

xMin, YMin — в начале оси
xMid, YMid — в середине
xMax, YMax — в конце

Эти значения можно комбинировать в любых сочетаниях, но порядок должен сохраняться: первым всегда идет значение для X, вторым для Y. Значение для Y всегда пишется с большой буквы.

Поведение элемента определяется второй частью preserveAspectRatio. Возможные значения:

meet — содержимое стремится уместиться целиком (как фон с background-size: contain)
slice — содержимое заполняет собой всю область видимости (как background-size: cover: что не поместилось, обрежется)

Важно помнить, что preserveAspectRatio не работает без viewBox. viewBox задает область, которая должна масштабироваться, preserveAspectRatio определяет как именно она должна это делать.

Также нужно понимать, что preserveAspectRatio срабатывает, если вьюпорт и вьюбокс имеют разные соотношения сторон. Если соотношения сторон совпадают, и содержимое умещается без полей, preserveAspectRatio работать не будет (в этом случае в нём просто нет необходимости).

Для использования SVG в качестве иконок достаточно viewBox и размеров, но если предполагается делать что-то более сложное, имеет смысл разобраться с единицами измерения и системой координат.

Единицы измерения

Внутри SVG можно использовать em, ex, px, pt, pc, cm, mm, in, проценты, а также единицы системы координат (user space units). Единицы системы координат соответствуют пикселям, поэтому для значений в пикселях единицы измерения указывать не нужно.

Системы координат

В SVG-документе есть две системы координат:

  1. Система координат области отрисовки — viewport space.
  2. Система координат содержимого — user space.

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

По умолчанию система координат содержимого соответствует системе координат вьюпорта, а единицы измерения содержимого — единицам измерения вьюпорта, но при использовании трансформаций или viewBox масштабируется вся система координат с единицами измерения, то есть пиксели из user space больше не равны пикселям из viewport space.

Поизменяйте размеры элемента и посмотрите что происходит с системой координат содержимого (она показана бирюзовым):

Система координат содержимого начинается из точки 0,0, и если вьюпорт и вьюбокс не совпадают, точка отсчета, как и вся система координат содержимого, будет ездить и масштабироватся вместе с вьюбоксом.

Масштабирование единиц измерения хорошо видно на примере обводки: изначально её толщина равна единице, но при изменении размеров видимая толщина обводки будет изменяться вместе с фигурой:

Если такое поведение нежелательно, это можно исправить с помощью свойства vector-effect со значением non-scaling-stroke, оно добавляется к содержимому SVG:

<circle r="60" cx="75" cy="75"
  stroke="black" stroke-width="1"
  vector-effect="non-scaling-stroke"/>

vector-effect можно задавать как атрибутом, так и в CSS.

Также новая система координат создается при добавлении трансформаций:

Внутри трансформируемого элемента будет своя своя система координат, отличная от систем координат вьюпорта и вьюбокса.

Тема может выглядеть сложной, но на самом деле, достаточно немного поиграться с кодом, и всё станет понятно. Для лучшего понимания систем координат, размеров и трансформаций в SVG рекомендую демо Сары Суайдан, а также её статьи:

  • Understanding SVG Coordinate Systems and Transformations (Part 1) — The viewport, viewBox, and preserveAspectRatio
  • Understanding SVG Coordinate Systems and Transformations (Part 2) — The transform Attribute
  • Understanding SVG Coordinate Systems and Transformations (Part 3) — Establishing New Viewports

The Question:
Is there a way to change the size of the SVG viewbox with CSS, but preserve the aspect ratio? OR is there another way to preserve the aspect ratio of the SVG without a view box.

The Problem:
I want to responsively adjust the size of the SVG, but keep the aspect ratio. The width of the viewbox adjusts with the page, but the height doesn’t adjust with the width. The problem with that is that the height of the container div is dependent on the height of the viewbox. So the container div may be really tall even if there’s nothing showing in the bottom half of the viewbox.

Fiddle:
http://jsfiddle.net/hT9Jb/1/

<style>
    div{
        width: 100%;
        height: 500px;
        background-color: #00ffff;
    }

    svg{
        width: 50%;
        background-color: #ffff00;
    }
</style>

<div>
    <svg version="1.1" id="Layer_1" x="0px" y="0px" width="250px" height="400px" viewBox="0 0 250 400" enable-background="new 0 0 250 400" aspect-ratio="XminYmin">
        <rect x="0" y="0" fill="#FF0000" width="250" height="400"/>
    </svg>
</div>

(Object SVGs and img SVGs wont work for my purposes. It has to be inline. The solution doesn’t have to be CSS…javascript is definitely an acceptable solution.)

asked Jun 28, 2014 at 2:44

Geoffrey Burdett's user avatar

Geoffrey BurdettGeoffrey Burdett

1,8461 gold badge14 silver badges25 bronze badges

4

You could use a transform:

transform: scale(0.75); // 75% of original size

answered Apr 23, 2019 at 17:27

pruhter's user avatar

5

I haven’t yet found a way to change the viewBox property with CSS. However this Javascript solution works well:

var mySVG = document.getElementById('svg');
mySVG.setAttribute("viewBox", "0 0 100 100");

Also remove any references to width and height from the SVG and set them in CSS. Even though your working with an SVG, it’s inline so cascading rules apply.

answered Sep 8, 2017 at 4:36

sansSpoon's user avatar

sansSpoonsansSpoon

2,0652 gold badges23 silver badges43 bronze badges

3

In order to have a flexible SVG, that allows you to change its width and height, you need to remove completely the width and height and work with viewbox instead.

And, contrary to what sansSpoon said, you do not need javascript to do this.

In your css, refer to your svg and define its max-width and max-height, for example:

.my_svg_element {
    max-width: 250px;
    max-height: 400px;

}

After that, your SVG will be elastic and, at the same time, will respect the max width and height you have defined before.

Nodira's user avatar

Nodira

6561 gold badge9 silver badges22 bronze badges

answered Feb 7, 2018 at 13:22

Paulo Coghi's user avatar

Paulo CoghiPaulo Coghi

13k14 gold badges67 silver badges89 bronze badges

4

The width and height values specified in your SVG are the cause of your problem.

The solution is to fix your SVG file. Change:

width="250px" height="400px"

to

width="100%" height="100%"

Or with CSS:

width: 100%;
height: 100%; 

answered Aug 21, 2016 at 8:54

Paul LeBeau's user avatar

Paul LeBeauPaul LeBeau

95.1k8 gold badges149 silver badges177 bronze badges

1

What helped me was setting height and width on an img tag:

<img src="./logo.svg" height="150px" width="150px"/>

answered Feb 9, 2020 at 8:28

Sasha Shpota's user avatar

Sasha ShpotaSasha Shpota

8,87411 gold badges69 silver badges136 bronze badges

To build on the answer on @Paulo Coghi which is the best answer for me (and who saved me after a few hours of failing tests and useless googling:

Just tranform your svg from:

<svg version="1.1" id="Layer_1" x="0px" y="0px" width="250px" height="400px" viewBox="0 0 250 400" enable-background="new 0 0 250 400" aspect-ratio="XminYmin">
        <rect x="0" y="0" fill="#FF0000" width="250" height="400"/>
</svg>

into:

<svg version="1.1" id="Layer_1" viewBox="0 0 250 400" >
    <rect x="0" y="0" fill="#FF0000" width="250" height="400"/>
    // and/or whatever you want
</svg>

then you can use in your CSS:

svg {
    max-width: 100%;
    max-height: 100%;
    // or any other units or measurements you want
}

answered May 14, 2021 at 11:41

Skratt's user avatar

SkrattSkratt

2444 silver badges11 bronze badges

    svg{
        width: 50%;
        background-color: #000;
    }
 <svg version="1.1" id="Layer_1" x="0px" y="0px" width="250px" height="400px" viewBox="0 0 250 400" enable-background="new 0 0 250 400" aspect-ratio="XminYmin" preserveAspectRatio="none">
        <rect x="0" y="0" fill="#FF0000" width="250" height="400"/>
    </svg>

Just use this and see if it works(worked for me).

<svg .... .... ...  preserveAspectRatio="none">

This should work.

answered Apr 19, 2020 at 8:23

Debu Shinobi's user avatar

Debu ShinobiDebu Shinobi

1,78816 silver badges20 bronze badges

I found a simple javascript solution:

function setSvgSize(){
    var width = document.getElementById('svg-container').offsetWidth;
    var x = parseInt( $('#svg').attr('width') );
    var y = parseInt( $('#svg').attr('height') );
    var height = (width / x) * y;
    $('#svg-container').css('height',height);
}

answered Jun 29, 2014 at 12:41

Geoffrey Burdett's user avatar

Geoffrey BurdettGeoffrey Burdett

1,8461 gold badge14 silver badges25 bronze badges

demosourse

SVG может быть встроен в веб-страницу множеством способов; однин из них — использование HTML5 тэга <svg>. Другие способы включают в себя встраивание SVG при помощи тэгов <img>, <object>, а так же, используя iframe, либо как фон при помощи CSS.

В принципе, задавать масштаб SVG должно быть так же просто, как выставлять любое значение высоты или ширины контейнера. Однако, в силу разных настроек браузеров, сделать SVG адаптивным не так-то просто.

Тем не менее, существуют определенные уловки, которые мы можем воспользоваться для достижения нужного результата. В этой статье мы рассмотрим несколько способов, которые помогут сделать SVG адаптивными.

Как сделать SVG «резиновыми» при помощи CSS

Для того чтобы заставить SVG быть «резиновым», прежде всего необходимо удалить атрибуты height и width. Когда указаны точные значения высоты и ширины SVG никак не сможет автоматически растягиватся. Стоит, однако, оставить атрибут viewBox. После очистки свойств высоты и ширины SVG можно вставить на страницу одним из нескольких способов.

Встраивание SVG при помощи <img>

Когда SVG встроен как изображение при помощи тэга <img> высота и ширина, указанные в тэге используются браузером для контроля размеров SVG. Содержимое SVG затем располагается внутри окна просмотра в зависимости от значения viewBox, указанного в <svg>.

<img src="my_SVG_file.svg" alt="Image description." /><img src="my_SVG_file.svg" alt="Image description." />

Обычно браузеры достаточно функциональны для определения ширины и высоты SVG даже если не указывать ширину и высоту <img> элемента. Например, если вам нужно поместить img в div без указания высоты и ширины, Chrome и Firefox решат, что ширина img = 100%; SVG затем растягивается для заполнения содержащего div, и его высота соответствующе подгоняется для сохранения пропорций. Затем изменяется размер самого div-а, а img SVG подгоняется под него. Однако при работе с растровым изображением, например рисунком PNG это бы не проканало; в этом случае нам бы пришлось специально задавать ширину img в 100% при помощи CSS.

В Internet Explorer дела обстоят по-другому. Если не указывать ширину img, браузер решит, что высота равняется 150px, так этот размер указан в CSS спецификации как стандартный; стандартная ширина изображения равняется 300px. Затем SVG располагается внутри содержащего div так, что его высота равна 150px; хотя предполагается что ширина будет 100%; SVG принимает высоту всегда 150px независимо от того, насколько широким становится контейнер, что в результате приводит к широким белым пробелам с обеих сторон. Чтобы разобраться с этим вопросом в IE достаточно специально задавать ширину img в 100%. Эти результаты были получены в следствие тестов, проведенных в Internet Explorer 9 и 11.

Таким образом, для того чтобы сделать SVG “резиновым”, сначала необходимо удалить значения высоты и ширины, указанных в <svg>, а затем добавить одну строчку CSS для Internet Explorer:Таким образом, для того чтобы сделать SVG “резиновым”, сначала необходимо удалить значения высоты и ширины, указанных в <svg>, а затем добавить одну строчку CSS для Internet Explorer:

/* fix for IE */
img {
    width: 100%;
}

Обратите внимание, что если вы решите задать ширину и высоту тэгу <img> более чем 100%, то размер SVG будет расчитан как будто ширина и высота были заданы непосредственно <svg> элементу.

Встраивание SVG при помощи <object>

Встраивание SVG через <object>, во многом похоже на тот же самый процесс при работе с <img>.

<object type="image/svg+xml" data="my_SVG_file.svg">
    <!-- fallback here (<img> referencing a PNG version of the graphic, for example) -->
</object>

Так же, как и с тэгом img, Firefox и Chrome определяют ширину SVG-объекта в 100% и высота изменяется пропорционально увеличению ширины экрана. Если же object-у задать ширину и высоту, то SVG-графика поместится в отдельную область просмотра с заданными размерами.

В случае с Internet Explorer возникает та же проблема, о которой мы упоминали ранее, когда высота SVG по умолчанию равна 150px. Проблема также устраняется путем задания ширины в 100%:

/* fix for IE */
object {
    width: 100%;
}

Встраивание SVG при помощи <iframe>

<iframe> очень похож по своему функционированию и особенностях на <object>.

<iframe src="my_SVG_file.svg">
    <!-- fallback here (<img> referencing a PNG version of the graphic, for example) -->
</iframe>

Однако браузеры реагируют на данный способ по-разному. На сегодняшний день Chrome, Firefox и Internet Explorer выставляют вставленному в iframe SVG: 300px ширины и 150px высоты. В предыдущих случаях, когда IE использовал стандартную высоту 150px, он использовал ширину в 100%. Однако когда речь идёт об iframe все три браузера устанавливают высоту и ширину iframe’а в фиксированном размере 300px на 150px.

Применение width:100% растягивает iframe для заполнения ширины контейнера, однако высота не меняется – она по-прежнему равна 150px; даже когда контейнер и iframe уменьшаются до ширины меньшей, чем оригинальная ширина SVG, iframe по-прежнему поддерживает высотку в 150рх, приводя к появлению белых пробелов сверху и снизу SVG-изображения. Это происходит во всех трёх браузерах.

Единственный способ изменить высоту SVG – точно задать ее на iframe. Высота затем, конечно, вместе с шириной сформирует окно просмотра, внутри которого будет расположен SVG. Если вы хотите, чтобы SVG поместился внутри окна просмотра без всяких белых пробелов над/под или по сторонам, необходимо будет удостовериться в том, что заданные высота и ширина окна просмотра (iframe) соответствуют соотношению высоты и ширины SVG-изображения.

Не существует “стандартного” способа создать элемент с конкретным соотношением высоты-ширины в CSS. Однако, несколько лет назад Тьерри Кобленц разместил статью на A List Apart, в которой описывается прием, который сегодня известен как Хак заполнения; хак, позволяющий создавать внутренние соотношения для видео и iframe-ов.

Идея padding hack’а заключается в использовании отношения внутренних отступов элемента к его ширине. Когда внутрение отступы установлены в процентном соотношении, проценты вычисляются относительно ширины элемента, даже если мы выставили только верхний внутренний отступ. Аналогичный прием можно использовать в случае с SVG, чтобы сделать элемент “резиновым”. Ниже описаны шаги для достижения нужного нам эффекта.

Пусть тестовый SVG выглядит вот так:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="194" height="186" viewBox="0 0 194 186">
    <!-- SVG content -->
</svg>

Padding hack – Шаг 1

Для того чтобы сделать SVG адаптивным, когда он встроен в iframe необходимо сделать то же самое, что мы делали ранее: убрать атрибуты height и width из <svg> элемента.

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186">
    <!-- SVG content -->
</svg>

Padding hack – Шаг 2

Далее, убедимся в том, что задали атрибут viewBox. В большинстве случаев SVG будет иметь указанный viewBox.

Нет необходимости специально задавайте preserveAspectRatio так как его стандартное значение (xMidYMid meet) является значением, которое нам вполне подходит. Поэтому нет необходимости задавть его, если только значение preserveAspectRatio не должно быть оличным от стандартного.

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186" preserveAspectRatio="xMidYMid meet">
    <!-- SVG content -->
</svg>

Padding hack – Шаг 3

Для того, чтобы padding hack сработал, SVG необходимо поместить в контейнер. Для этой цели нам подойдёт элемент div. Этот контейнер получит внутреннее соотношение при помощи padding hack’а (следующий шаг), и затем iframe будет автоматически масштабирован внутри контейнера.

<!-- wrap svg in a container -->
<div class="container">
    <iframe src="my_SVG_file.svg">
        <!-- fallback here -->
    </iframe>
</div>

Padding hack – Шаг 4

Далее, мы применяем несколько стилей к контейнеру соблюдая следующие правила:

.container {
    height: 0;
    width: width-value;
    padding-top: (svg height / svg width) * width-value;
    position: relative;
}

Итак, что конкретно делают вышеуказанные правила?

Во-первых, мы сбрасываем значение высоты контейнера. Так как внутренние отступы рассчитывается относительно ширины элемента, нам понадобится задать их относительно элемента для его повторного расширения по вертикали.

После того, как мы указали ширину контейнера – которая должна автоматически растягиваться, используя процентное значение, задаём значение верхнего внутреннего (или нижнего) отступа контейнера при помощи следующей формулы. Эта формула использует значения атрибутов <svg> height и width, которые мы убрали в Шаге 1) для указания значения заполнения, которое позволит внуреннему отступ контейнера соответствовать размерам svg.

В нашем логотипе ширина svg составляет 194px, а высота – 186рх. Я установил ширину контейнера на 50% чтобы он занимал половину доступного горизонтального пространства. Примененное к контейнеру заполнение равняется (186 / 194) * 50 = 48%. То есть, код для контейнера выглядит вот так:

.container {
    width: 50%;
    height: 0;
    padding-top: 48%;
    position: relative;
}

Так как высота контейнера была сбита и мы выставили большое знаечение верхнему внутреннему отступу, то содержимое будет смещено вниз.

Чтобы «вытянуть» SVG обратно мы разместим iframe внутри контейнера. Тут вступает в игру position: relative, что помогает выставить правильную позицию для SVG.

Padding hack – Шаг 5

Теперь, когда у нас есть позиционируемый контекст, разместим iframe внутри контейнера и выставим его размеры таким образом, чтобы они совпадали с высотой и шириной контейнера:

iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

Это всё, что необходимо для того чтобы сделать SVG адаптивным. iframe отображается в стандартной рамке, от которой по всей видимости вы захотите избавиться. Для этого достаточно добавить одно правило: border: none;

Встраивание SVG при помощи <svg>Встраивание SVG при помощи <svg>

SVG может быть встроен в HTML документ при помощи тега <svg>.

<!-- Note: the xmlns is not required in an HTML5 document -->
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186">
    <!-- SVG content -->
</svg>

Ширина и высота встроенного окно просмотра svg будет такой же, какую вы задали непостредственно <svg> элементу. Когда атрибуты ширины и высоты убраны все браузеры будут воспринимать ширину равной 100% и растягивать SVG по горизонтали чтобы заполнить ширину контейнера.

В Chrome и Firefox высота SVG рассчитывается как раз так, как нам нужно. В этом случае адаптивность достигается без особых потерь.

В Internet Explorer (проверено на версиях 9 и 11) высота снова равна 150рх, а ширина 100%. Как и в предыдущих случаях, при изменении размера экрана, сверху и снизу SVG появится белое пространство. При использовании img было достаточно указать width: 100%; однако, выставив ширину в 100% самому svg такой же эффект не будет достигнут. В этом случае лучшим решением будет применение padding hack-а.

<div class="container">
    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186">
        <!-- SVG content -->
    </svg>
</div>

.container {
    width: 50%;
    height: 0;
    padding-top: 48%;
    position: relative;
}

svg {
    position: absolute;
    top: 0;
    left: 0;
}

SVG встроенный как фоновый рисунок при помощи CSS

Одним из популярных способов встраивания SVG является использование фонового рисунка:

.element {
    background-image: url(my_SVG_image.svg);
    /* other styles */
}

К счастью, нам не нужно применять никакие фиксы или хаки чтобы заставить фоновый рисунок SVG вести себя как необходимо — фоновый рисунок SVG может быть расположен, наложен, изменен в размере и масштабирован как любой фоновый рисунок.

Делаем SVG адаптивными при помощи CSS медиа запросов

Тот факт, что графические элементы внутри SVG создаются при помощи XML, делает работу с SVG очень удобной. Так как SVG-контент состоит из XML тэгов, которые отображают графику мы можем выбирать отдельные элементы и применять к ним конкретные стили точно так же, как мы выбираем элементы HTML, используя CSS селекторы.

Элементы SVG обычно стилизуются при помощи презентационных атрибутов вроде fill, stroke, transform и других. Однако только подмножество всех презентационных атрибутов может быть задано при помощи CSS. Вы можете найти список задаваемых стилей, в спецификации стилей SVG. Список задаваемых при помощи свойств CSS атрибутов на данный момент не включает атрибуты x, y, width и height; однако эта четвёрка будет добавлена в список, и мы сможем задавать их при помощи CSS.

Некоторые из самых часто задаваемых свойств: fill, который работает подобно фоновому цвету; stroke, который схож с border; opacity, display, transform и некоторые другие.

Далее мы добавим медиа запросы внутрь тэга <style> внутри <svg>:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186">
    <style>
        /* CSS styles and media queries here */
    </style>
    <!-- SVG elements here -->
</svg>

Вот так вставляем логотип:

<img src="logo.svg" alt="Logo" />

Пора отметить, что размеры, указанные в медиа запросах, ссылаются на размеры окна просмотра SVG. В зависимости от способа, которым вы встраиваете SVG, окно просмотра может быть либо размера самого <svg> (для встроенных SVG), либо размера ссылаемого SVG элемента.

У каждого из элементов внутри SVG есть ID, который мы можем использовать в CSS:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186">
    <path id="curved_bg" fill="#195463" d="..."/>
    <g id="primary_content" fill="#ECECEC">
        <path id="icon" d="..."/>
        <path id="inner-circle" d="..."/>
        <path id="middle-circle" d="..."/>
    </g><!-- /primary content -->
    <g id="secondary_content" fill="#ECECEC">
        <path id="bottom-text" d="..."/>
        <path id="upper-text" d="..."/>
        <path id="outer-circle" d="..."/>
        <circle id="left-dot" cx="31.1" cy="91.5" r="3"/>
        <circle id="right-dot" cx="163.4" cy="91.5" r="3"/>
    </g><!-- end secondary content -->
</svg>

Используя <style> внутри SVG, мы создаём медиа запросы, которые изменят стили в зависимости от размера окна. SVG изменится как показано на изображениях ниже:

Мы будем использовать свойства CSS fill и opacity. Уменьшая размер окна, фон логотипа исчезнет, а цвет заполнения поменяется с белого на тёмно-синий. По мере того, как экран уменьшается, текстовая часть логотипа убирается, чтобы занимать меньше экранного пространства. И, наконец, круг, охватывающий иконку, убирается и на очень маленьких экранах остается только иконка якоря.

Вместе с медиа запосами, наш SVG файл будет выглядеь следующим образом:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186">
    <style>
        svg * {
            transition: fill .1s ease-out, opacity .1s ease-out;
        }
        @media all and (max-width: 250px) {
            #curved_bg {
                opacity: 0;
            }
            #secondary_content, #primary_content {
                fill: #195463;
            }
        }
        @media all and (max-width: 200px) {
            #secondary_content {
                opacity: 0;
            }
        }
        @media all and (max-width: 150px) {
            #inner-circle, #middle-circle {
                opacity: 0;
            }
        }
    </style>
    <path id="curved_bg" fill="#195463" d="..."/>
    <!-- ... -->
</svg>

Изменение логотипа в зависимости от размеров экрана — тоже адаптивность. Некоторые логотипы компаний могут занимать слишком много пространства на маленьких экранах, поэтому мы всё чаще видим, как множество логотипов адаптируются, путем избавления от текстовой части. Без SVG этого можно было бы достигнуть путем переключения PNG на экранах различных размеров. Однако такой подход не очень эффективен, ведь вам потребуется хранить на сервере множество картинок. В данном случае явно видны преимущества SVG: гибкость в использовании и прекрасное отображение на экранах.

В завершении

С выходом всё новых и новых версий Chrome и Firefox, увеличивается поддержка SVG, поэтому информация в данной статье в какой-то момент может стать не актуальна. Internet Explorer как всегда замедляет всю движуху, поэтому упомянутые фиксы будут актуальны долгое время.

Базовые трансформации

  • « Предыдущая статья
  • Следующая статья »

Теперь мы готовы начать изменять наши замечательные изображения. Но сначала давайте ознакомимся с <g> элементом. С его помощью вы можете назначить свойства для любого набора элементов. На самом деле, в этом и состоит его единственная цель. Например:

<svg width="30" height="10">
    <g fill="red">
        <rect x="0" y="0" width="10" height="10" />
        <rect x="20" y="0" width="10" height="10" />
    </g>
</svg>

Все последующие преобразования суммируются в атрибуте преобразования элемента transform . Преобразования могут быть последовательно суммированы, разделителем выступает пробел.

Перемещения

Иногда необходимо сместить элемент, хотя вы спозиционировали его согласно определённым атрибутам. Для этого используется translate().

<svg width="40" height="50" style="background-color:#bff;">
    <rect x="0" y="0" width="10" height="10" transform="translate(30,40)" />
</svg>

Пример генерирует прямоугольник, перемещённый в точку (30,40) вместо точки (0,0).

если второе значение не задано, то оно приравнивается 0.

Вращение

Вращение элементов — это достаточно типичная задача. Используйте rotate() для этого:

<svg width="31" height="31">
    <rect x="12" y="-10" width="20" height="20" transform="rotate(45)" />
</svg>

Данный пример показывает квадрат который повернули на 45 градусов. Значение для rotate() задаётся в градусах.

Смещение углов

Чтобы сделать ромб из нашего прямоугольника, доступны преобразования skewX () и skewY (). Каждый из них принимает угол, определяющий, насколько элемент будет искажён.

Масштабирование

scale() изменяем размер элемента. Он использует 2 параметра. Первый — это коэффициент масштабирования по оси Х, а второй — по оси Y. Коэффициенты выражают сжатие по отношению к оригинальному изображению. Например, 0.5 уменьшает на 50%. Если второй параметр отсутствует, то тогда он принимается равным первому.

Комплексные перемещения с matrix()

Все приведённые выше преобразования могут быть описаны с помощью матрицы перемещений 2×3. Чтобы объединить несколько перемещений, можно установить результирующую матрицу с помощью matrix(a, b, c, d, e, f), которая преобразует координаты из предыдущей системы координат в новую систему координат посредством:

{

x

new

C
o
o
r
d
S
y
s

=
a

x

prev
C
o
o
r
d
S
y
s

+
c

y

prev

C
o
o
r
d
S
y
s

+
e

y

new

C
o
o
r
d
S
y
s

=
b

x

prev

C
o
o
r
d
S
y
s

+
d

y

prev
C
o
o
r
d
S
y
s

+
f

left{ begin{matrix} x*{mathrm{prevCoordSys}} = a x*{mathrm{newCoordSys}} + c y*{mathrm{newCoordSys}} + e y*{mathrm{prevCoordSys}} = b x*{mathrm{newCoordSys}} + d y*{mathrm{newCoordSys}} + f end{matrix} right.

См. конкретный пример документации SVG. Подробную информацию об этом свойстве можно найти в SVG Рекомендациях.

Эффекты на системе координат

В случае использования преобразований вы устанавливаете новую систему координат внутри элемента, к которому применяются изменения. Это означает, что единицы измерения которые вы определяете и его дочерние еи не будут соответствовать 1:1, но также будут искажены, повёрнуты, перемещены и смаштабированы в соответствии с преобразованиями.

<svg width="100" height="100">
    <g transform="scale(2)">
        <rect width="50" height="50" />
    </g>
</svg>

В результата прямоугольник в примере выше будет 100x100px. Более интригующие эффекты возникают, когда вы используете такие атрибуты, как userSpaceOnUse.

В отличие от HTML, SVG позволяет встраивать другие svg элементы без разрыва. Таким образом вы можете запросто создать новую координатную систему используя viewBox, width и height внутреннего svg элемента.

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100" height="100">
  <svg width="100" height="100" viewBox="0 0 50 50">
    <rect width="50" height="50" />
  </svg>
</svg>

На примере выше, так же как и на других примерах ранее, вы можете видеть такой же эффект увеличения изображения в два раза.

  • « Предыдущая статья
  • Следующая статья »

svg width и svg height будем рассматривать как одно целое! Не хочу делать отдельные страницы!

  • Как поставить или извинить svg width и height

    Загрузку svg векторной графики — мы выделили в отдельный пункт — оттуда возьмем экземпляр для экспериментов :

    https://dwweb.ru/__img/__svg/bell/bell_95.svg

    Выведем прямо здесь:

    <img src=»https://dwweb.ru/__img/__svg/bell/bell_95.svg»>

    Результат:
    Как видим наш svg без width и height растянулся на всю ширину, которая доступна.
    Как поставить  или извинить svg width и height

    Зададим svg width и svg height

    Как вы знаете есть «3 способа css» — воспользуемся одним из этих способов!

    <img style=»width:50px;height:50px;» src=»https://dwweb.ru/__img/__svg/bell/bell_95.svg»>

    Результат:
    Зададим svg width и svg height

  • Изменить svg width и height если это код svg<

    Выше приведенный пример не будем рассматривать, поскольку код этого svg очень большой, поэтому возьмем попроще — мы в одних из первых статьях рассматривали круг.

    Зададим svg width и svg height прямо внутри кода

    Возьмем код svg и зададим svg width и svg height прямо внутри кода :

    <svg width=»100″ height=»100″><circle cx=»50″ cy=»50″ r=»50″ fill=»green»></svg>

    Результат:

    Изменим svg width и height

    Заменим выше приведенные значения в нашем svg -выделено красным.

    <svg width=»

    300

    » height=»

    300

    «><circle cx=»50″ cy=»50″ r=»50″ fill=»green»></svg>

    Результат изменения svg width и height

    Как видим высота и ширина никак не повлияли на наш svg — блок внешний увеличился, а сама картинка нет!

    В чем может быть проблема!?

    Дело в том. что для данного svg — это у нас круг, нужно изменить некоторые параметры внутри кода svg.

    Нам нужно изменить:

    координаты по оси «x» — половину ширины width=»300″ -> cx=»150″

    координаты по оси «y» — половину ширины height=»300″ -> cy=»150″

    радиус круга половина внешнего размера 300/2 = 150 -> r=»150″

    Html:

    <svg width=»300″ height=»300″><circle cx=»150″ cy=»150″ r=»150″ fill=»green»></svg>

    Результат изменения svg width и height

  • Не меняется высота(width) и ширина(height) у svg

    Иногда ширина и высота svg не меняется при изменении width и height.

    Давайте приведу пример:

    Html:

    <svg width=»25″ height=»25″> <path d=»M12 21.35l-1.45-1.32c-5.15-4.67-8.55-7.75-8.55-11.53 0-3.08 2.42-5.5 5.5-5.5 1.74 0 3.41.81 4.5 2.09 1.09-1.28 2.76-2.09 4.5-2.09 3.08 0 5.5 2.42 5.5 5.5 0 3.78-3.4 6.86-8.55 11.54l-1.45 1.31z»/> </svg>

    Результат:

    Html:

    <svg width=»125″ height=»125″> <path d=»M12 21.35l-1.45-1.32c-5.15-4.67-8.55-7.75-8.55-11.53 0-3.08 2.42-5.5 5.5-5.5 1.74 0 3.41.81 4.5 2.09 1.09-1.28 2.76-2.09 4.5-2.09 3.08 0 5.5 2.42 5.5 5.5 0 3.78-3.4 6.86-8.55 11.54l-1.45 1.31z»/> </svg>

    Результат:

    Картинка svg не меняет высоту(width) и ширину(height)

    Как видим, наружный размер изменился — я специально добавил бордюр. А картинка нет. Почему!?

    Все просто!

    Для картинок svg нужен атрибут «viewBox»!

    Не буду подробно рассказывать о viewBox — это надо делать отдельную страницу.

    Совсем кратко:

    Первые два числа — координаты X и Y верхнего левого угла масштабируемой области, два других — её ширина и высота.

    Изменим размер и позицию внутри обертки с размером «150», а то 50 — как-то совсем маловато…

    Смотрим, что у нас получилось:

    Html:

    <svg width=»150″ height=»150″ viewBox=»1 2 22 20″> <path d=»M12 21.35l-1.45-1.32c-5.15-4.67-8.55-7.75-8.55-11.53 0-3.08 2.42-5.5 5.5-5.5 1.74 0 3.41.81 4.5 2.09 1.09-1.28 2.76-2.09 4.5-2.09 3.08 0 5.5 2.42 5.5 5.5 0 3.78-3.4 6.86-8.55 11.54l-1.45 1.31z»></path> </svg>

    Результат изменения высоты(width) и ширины(height) у svg

    И далее

    Когда у вас уже есть «viewBox» вы можете использовать «3 способа css», давайте изменим на 350 внутри тега:

    Html:

    <svg width=»350″ height=»350″ viewBox=»1 2 22 20″ fill=»red»> <path d=»M12 21.35l-1.45-1.32c-5.15-4.67-8.55-7.75-8.55-11.53 0-3.08 2.42-5.5 5.5-5.5 1.74 0 3.41.81 4.5 2.09 1.09-1.28 2.76-2.09 4.5-2.09 3.08 0 5.5 2.42 5.5 5.5 0 3.78-3.4 6.86-8.55 11.54l-1.45 1.31z»></path> </svg>

    Результат изменения высоты(width) и ширины(height) у svg

    Время прочтения
    6 мин

    Просмотры 64K

    Привет, Хабр.
    Сразу хочу отметить, что если мы говорим об иконках, их можно масштабировать двумя способами (других я просто не знаю): конвертировать иконки в шрифт и подключать их через @font-face, либо использовать SVG в качестве формата для этих иконок.

    Немного отойду от темы и расскажу предысторию.

    Предыстория

    Я было решил использовать у себя на сайте шрифтовые иконки, казалось бы все хорошо: и размер менять можно, и цвет задавать и запрос к серверу всего один (на подключение шрифта). Другими словами, подключаемый шрифт это и есть своеобразный «CSS спрайт», верно?

    Я давай проверять, везде ли все красиво выглядит. Оказалось, что не все так хорошо как хотелось бы, потому как в некоторых размерах иконки выглядели кособокими, а при отключенном сглаживании вообще противно смотреть на них стало. Что делать? Использовать второй вариант — SVG, о чем и пойдет речь.

    CSS спрайт с SVG

    Идея складывать спрайт в SVG формат не нова. Наверняка, многие читали этот пост на smashingmagazine. Так вот, я решил развить мысль автора, поэкспериментировать и предложить более гибкий вариант. А чтобы стало все понятно, некоторые примеры повторю здесь.

    Итак, для начала нам нужно сделать SVG спрайт. Как сделать SVG файл программно я пока не разобрался (надеюсь сообщество меня простит и даст ссылку где про это почитать). Поэтому я буду делать свой спрайт в CorelDRAW (Illustrator думаю тоже подойдет) и сохранять в SVG.

    Для быстрой реализации я использовал шрифт и напечатал вот такие иконки (кликабельно):

    svg иконки

    Возьмем произвольный HTML код для примера:

    <div class="icons">
    	<a class="tw" href="#">Twitter</a>
    	<a class="fb" href="#">Facebook</a>
    	<a class="vk" href="#">Вконтакте</a>
    	<a class="gl" href="#">Google+</a>
    	<a class="rs" href="#">RSS</a>
    </div>
    

    Напишем в CSS самое основное:

    .icons a {
    	float: left;
    	display: inline-block;
    	padding: 4px 0 4px 25px;
    	margin-right: 5px;
    	text-decoration: none;
    	color: #444;
    	/* вызов спрайта и задание размеров */
    	background-image: url('sprite.svg');
    	background-repeat: no-repeat;
    	background-size: 20px auto;
    }
    /* такой вариант рассмотрен на smashingmagazine.com, только 
    вместо px используются em как относительная величина */
    .icons .tw {background-position: 0 0;}
    .icons .fb {background-position: 0 -48px;}
    .icons .vk {background-position: 0 -96px;}
    .icons .gl {background-position: 0 -144px;}
    .icons .rs {background-position: 0 -192px;}
    

    Стоит отметить одну особенность, что sprite.svg создан с четко заданными размерами 76×520, т.е. максимальный размер до которого мы можем увеличить нашу иконку будет 76×76.

    А что если сохранить SVG с относительными размерами, те. в процентах? Это ведь лучше, т.к. иконки теперь можно будет масштабировать до абсолютно любого размера и не терять при этом их качества.

    Немного подправим стили в CSS:

    /* этот блок остается без изменений */
    .icons a {
    	float: left;
    	display: inline-block;
    	padding: 4px 0 4px 25px;
    	margin-right: 5px;
    	text-decoration: none;
    	color: #444;
    	/* вызов спрайта и задание размеров */
    	background-image: url('sprite.svg');
    	background-repeat: no-repeat;
    	background-size: 20px auto;
    }
    /* а здесь меняем абсолютную величину на относительную */
    .icons .tw {background-position: 0 0;}
    .icons .fb {background-position: 0 -25%;}
    .icons .vk {background-position: 0 -50%;}
    .icons .gl {background-position: 0 -75%;}
    .icons .rs {background-position: 0 -100%;}
    

    Результат одинаковый, но background-size может быть любым, каким угодно.

    Создание сложных спрайтов

    В примере выше использовано всего 5 иконок и высчитать проценты не так сложно. Давайте рассмотрим более сложный пример. Пока с теми же «шрифтовыми» иконками. Допустим у нас такой спрайт:

    Что мы делаем, либо добавлем в html новый тег i, для которого можем написать стили с иконкой:

    <div class="icons">
    	<a class="tw" href="#"><i></i>Twitter</a>
    	<a class="fb" href="#"><i></i>Facebook</a>
    	<a class="vk" href="#"><i></i>Вконтакте</a>
    	<a class="gl" href="#"><i></i>Google+</a>
    	<a class="rs" href="#"><i></i>RSS</a>
    </div>
    

    Либо оформляем иконку используя псевдоэлементы ::before или ::after. Я буду использовать псевдоэлемент ::before, вы — как вам больше нравится.

    Обратите внимание, что я не стал придумывать новые классы для ссылок (ведь спрайт поменялся) и оставил прежние, разумеется для новых иконок классы будут свои. А мы рассмотрим с этими, чтоб не захламить кодом пост.

    Итак, внесем изменения в CSS:

    .icons a {
    	float: left;
    	display: inline-block;
    	padding: 4px 0 4px 25px;
    	margin-right: 5px;
    	text-decoration: none;
    	color: #444;
    	/* добавляем */
    	position: relative;
    }
    /* создаем общий стиль для ::before */
    .icons a::before {
    	position: absolute;
    	left: 0;
    	top: 0;
    	content: '';
    	width: 25px;
    	height: 25px;
    	/* вызов спрайта и задание размеров */
    	background-image: url('sprite.svg');
    	background-repeat: no-repeat;
    	background-size: 20px auto;
    }
    /* а здесь дописываем псевдоэлемент и задаем позицию в спрайте
    (соответственно для нового спрайта позиции будут другие, о чем ниже) */
    .icons .tw::before {background-position: 0 0;}
    .icons .fb::before {background-position: 0 -25%;}
    .icons .vk::before {background-position: 0 -50%;}
    .icons .gl::before {background-position: 0 -75%;}
    .icons .rs::before {background-position: 0 -100%;}
    

    Сделаю несколько пояснений, а то я уже сам чуть было не запутался :).

    В background-size: 20px auto; число «20» это необходимый нам размер иконки, а «auto» это оставшийся размер спрайта. Если мы заменим «auto» например на 20px, то у нас вместо одной иконки получится весь спрайт размером 20×20 пикселей.

    Кроме того, на размер иконки теперь еще влияет ширина и высота блока формируемая псевдоэлементом, т.е. вместе с background-size теперь нужно менять width и height, чтобы иконка не обрезалась.

    Высчитываем относительные размеры

    Пожалуй, это ключевой момент и здесь стоит сделать выбор, либо вы задаете абсолютные размеры и при изменении background-size, width и height меняете их тоже, либо (что сложнее) высчитываете относительные размеры и при изменении background-size, width и height больше ничего не меняете.

    Итак, фактический размер спрайта 500×250 пикселей, по 10 иконок в строчку и по 5 в столбик, итого 50 иконок (в примере 49) размером 50×50 пикселей каждая.

    Высчитать размер довольно просто, т.к. будем отталкиваться от фактического размера спрайта. Кто работал со спрайтами объяснять не стоит. Правда здесь есть одна тонкость — размер иконки у нас уменьшен до 20 пикселей, соотвественно спрайт тоже изменился и стал равен 200×100 пикселей (10*20 и 5*20), а значит и размеры (background-position) мы будем считать, либо 0 0, 0 -20px, -20px 0, -20px -20px, 0 -40px, -40px 0, -40px -40px и т.д., либо 0 0, 0 -11,1%, 0 -22,2%, 0 -33,3, 25% 0, 25% -11,1%, 25% -22,2%, 25% -33,3 и т.д.

    Таким образом мы можем сделать любой сложности спрайт и высчитать background-position для каждого элемента. К счастью или сожалению, пытливый ум не дает остановиться на сказанном, поэтому бегло рассмотрим еще более сложный пример.

    Более сложный спрайт с SVG

    Допустим, у нас есть некий дизайн, совсем приблизительно изобразил (кликабельно):

    any site

    Предположим, что прямоугольники это какие-то красивые клипарты, трудно, но предположим. Что мы можем сделать:
    1. Сложить все слои в спрайт не меняя исходный размер и позиционировать каждый объект в соответствующем элементе;
    2. Сложить все слои в спрайт, предварительно приведя все объекты к одному размеру и позиционировать каждый объект в соответствующем элементе меняя размер объекта до неоходимой величины.

    Приводить пример HTML или CSS кода, думаю, уже не имеет смысла. И так все понятно, настраивается по аналогии с предыдущими примерами.

    В заключении

    Теперь хочу подвести итог и отметить плюсы спрайтов с SVG. Во-первых, у нас получился всего один файл, а значит один запрос к северу — заяц1 убит, во-вторых, вес SVG файла гораздо меньше, чем например PNG или JPG, а значит и скорость загрузки выше — заяц2 убит, в-третьих, мы получили неограниченных размеров спрайт без потери качества изображения, а значит решили задачу с неограниченным масштабированием изображения — заяц3 убит.

    Единственный минус SVG перед шрифтовыми иконками: нельзя украшать иконки с помощью CSS, например, добавлять text-shadow или менять цвет. И очень большой плюс, что при отключенном сглаживании все линии в SVG будут ровные и четкие в отличае от шрифта.

    P.S. SVG дает нам огромное поле для деятельности и на примере CSS спрайтов я в этом полностью убедился. Конечно, можно было обойтись сухими словами и сказать «сохраняйте SVG в относительных размерах», но у меня это вылилось в целый пост.

    Спасибо за внимание. До новых встреч.

    UPD: ::before и ::after это псевдоэлементы, а не псевдоклассы — простите, ошибся, поправил. Спасибо psywalker вовремя подсказал.
    UPD: А про «::» я и не вспомнил :( Пруф

    Понравилась статья? Поделить с друзьями:

    Читайте также:

  • Как изменить размеры stl модели
  • Как изменить размеры select
  • Как изменить размеры jpg рисунка
  • Как изменить размеры input
  • Как изменить размеры canvas unity

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии