Css scale svg icon

Масштабируем CSS спрайты с SVG, убивая сразу трех зайцев

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

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

Предыстория

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

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

CSS спрайт с SVG

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

Читайте также:  Php form errors array

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

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

svg иконки

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

 
Twitter Facebook Вконтакте Google+ RSS
.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 .icons .fb .icons .vk .icons .gl .icons .rs

Стоит отметить одну особенность, что 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 .icons .fb .icons .vk .icons .gl .icons .rs

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

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

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

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

 
Twitter Facebook Вконтакте Google+ RSS

Либо оформляем иконку используя псевдоэлементы ::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 .icons .fb::before .icons .vk::before .icons .gl::before .icons .rs::before

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

В 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: А про «::» я и не вспомнил 🙁 Пруф

Источник

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

Все последующие преобразования суммируются в атрибуте преобразования элемента 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< \beginx*<\mathrm > = a x*<\mathrm> + c y*<\mathrm> + e \ y*<\mathrm> = b x*<\mathrm> + d y*<\mathrm> + f \end \right.

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

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

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

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

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

Встраивание SVG в SVG

В отличие от 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> 

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

Found a content problem with this page?

This page was last modified on 14 февр. 2023 г. by MDN contributors.

Your blueprint for a better internet.

Источник

Как масштабировать размеры иконок svg

При размерах 256 пикселей размер svg иконки не 256 пикселей , а где-то ~140
При указании 128 , тоже не 128 и т.д. Почему так происходит?
Я уже перечитал все эти мануалы, в примерах их иконки все нормально отображаются с размерами, а почему эта не работает как надо?!

1 ответ 1

Масштаб определяется соотношением viewport / viewBox , где viewport это width=»X» height=»Y»

В вашем примере масштабирование применяется последовательно несколько раз.
Очень легко запутаться. Поэтому я максимально упрощу ваш пример и поэтапно буду усложнять до практического применения

viewport / viewBox = 100/100=1. Масштаб будет — 1:1 То есть как нарисовано в векторном редакторе, так и будет отражаться на дисплее

введите сюда описание изображения

На скрине векторного редактора видно, что физически иконка имеет габариты — 56.6 х 56.6px

  • Теперь запускаем этот же файл в браузере. И для наглядности я добавил красный прямоугольник, через стили в шапке файла, который показывает границы SVG файла. style=»border:1px solid red;»

Границы svg определяет viewport это — width=»100″ height=»100″

Из примеров видно, что иконка 56 х 56px не полностью занимает viewport — 100 х 100px

Это очень плохо, так как эти свободные пространства добавляют отступы от других элементов верстки HTML

Убираем лишние отступы

width=»56″ height=»56″ viewBox=»0 0 58 58″

Смотрим результаты в векторном редакторе и в браузере:

введите сюда описание изображения

Масштабирование иконок до требуемых размеров

Размер 256 x 256px

Для этого увеличиваем размер viewport до требуемых размеров

введите сюда описание изображения

Размер 128 x 128px

введите сюда описание изображения

Делаем рабочую версию приложения

Основное правило последовательных масштабирований в одном файле SVG

В шапке файла SVG задается самый большой viewport — это прямоугольная область, которую видит пользователь на экране. Если задали width=»256″ height=»256″ , то последующие масштабирования, которые идут в коде ниже могут только уменьшать размер этой области.

Пример с 3 иконками 256×256; 128×128; 64×64

Источник

Оцените статью