суббота, 13 февраля 2016 г.
Масштабируем CSS спрайты с SVG, убивая сразу трех зайцев
Привет, Хабр.
Сразу хочу отметить, что если мы говорим об иконках, их можно масштабировать двумя способами (других я просто не знаю): конвертировать иконки в шрифт и подключать их через @font-face, либо использовать SVG в качестве формата для этих иконок.
Немного отойду от темы и расскажу предысторию.
Я было решил использовать у себя на сайте шрифтовые иконки, казалось бы все хорошо: и размер менять можно, и цвет задавать и запрос к серверу всего один (на подключение шрифта). Другими словами, подключаемый шрифт это и есть своеобразный «CSS спрайт», верно?
Я давай проверять, везде ли все красиво выглядит. Оказалось, что не все так хорошо как хотелось бы, потому как в некоторых размерах иконки выглядели кособокими, а при отключенном сглаживании вообще противно смотреть на них стало. Что делать? Использовать второй вариант — SVG, о чем и пойдет речь.
Идея складывать спрайт в SVG формат не нова. Наверняка, многие читали этот пост на smashingmagazine. Так вот, я решил развить мысль автора, поэкспериментировать и предложить более гибкий вариант. А чтобы стало все понятно, некоторые примеры повторю здесь.
Итак, для начала нам нужно сделать SVG спрайт. Как сделать SVG файл программно я пока не разобрался (надеюсь сообщество меня простит и даст ссылку где про это почитать). Поэтому я буду делать свой спрайт в CorelDRAW (Illustrator думаю тоже подойдет) и сохранять в SVG.
Для быстрой реализации я использовал шрифт и напечатал вот такие иконки (кликабельно):
Возьмем произвольный HTML код для примера:
Напишем в CSS самое основное:
Стоит отметить одну особенность, что sprite.svg создан с четко заданными размерами 76x520, т.е. максимальный размер до которого мы можем увеличить нашу иконку будет 76x76.
А что если сохранить SVG с относительными размерами, те. в процентах? Это ведь лучше, т.к. иконки теперь можно будет масштабировать до абсолютно любого размера и не терять при этом их качества.
Немного подправим стили в CSS:
Результат одинаковый, но
В примере выше использовано всего 5 иконок и высчитать проценты не так сложно. Давайте рассмотрим более сложный пример. Пока с теми же «шрифтовыми» иконками. Допустим у нас такой спрайт:
Что мы делаем, либо добавлем в html новый тег
Либо оформляем иконку используя псевдоэлементы
Обратите внимание, что я не стал придумывать новые классы для ссылок (ведь спрайт поменялся) и оставил прежние, разумеется для новых иконок классы будут свои. А мы рассмотрим с этими, чтоб не захламить кодом пост.
Итак, внесем изменения в CSS:
Сделаю несколько пояснений, а то я уже сам чуть было не запутался :).
В
Кроме того, на размер иконки теперь еще влияет ширина и высота блока формируемая псевдоэлементом, т.е. вместе с
Пожалуй, это ключевой момент и здесь стоит сделать выбор, либо вы задаете абсолютные размеры и при изменении
Итак, фактический размер спрайта 500x250 пикселей, по 10 иконок в строчку и по 5 в столбик, итого 50 иконок (в примере 49) размером 50x50 пикселей каждая.
Высчитать размер довольно просто, т.к. будем отталкиваться от фактического размера спрайта. Кто работал со спрайтами объяснять не стоит. Правда здесь есть одна тонкость — размер иконки у нас уменьшен до 20 пикселей, соотвественно спрайт тоже изменился и стал равен 200x100 пикселей (10*20 и 5*20), а значит и размеры (
Таким образом мы можем сделать любой сложности спрайт и высчитать
Допустим, у нас есть некий дизайн, совсем приблизительно изобразил (кликабельно):
Предположим, что прямоугольники это какие-то красивые клипарты, трудно, но предположим. Что мы можем сделать:
1. Сложить все слои в спрайт не меняя исходный размер и позиционировать каждый объект в соответствующем элементе;
2. Сложить все слои в спрайт, предварительно приведя все объекты к одному размеру и позиционировать каждый объект в соответствующем элементе меняя размер объекта до неоходимой величины.
Приводить пример HTML или CSS кода, думаю, уже не имеет смысла. И так все понятно, настраивается по аналогии с предыдущими примерами.
Теперь хочу подвести итог и отметить плюсы спрайтов с SVG. Во-первых, у нас получился всего один файл, а значит один запрос к северу — заяц1 убит, во-вторых, вес SVG файла гораздо меньше, чем например PNG или JPG, а значит и скорость загрузки выше — заяц2 убит, в-третьих, мы получили неограниченных размеров спрайт без потери качества изображения, а значит решили задачу с неограниченным масштабированием изображения — заяц3 убит.
Единственный минус SVG перед шрифтовыми иконками: нельзя украшать иконки с помощью CSS, например, добавлять
P.S. SVG дает нам огромное поле для деятельности и на примере CSS спрайтов я в этом полностью убедился. Конечно, можно было обойтись сухими словами и сказать «сохраняйте SVG в относительных размерах», но у меня это вылилось в целый пост.
Спасибо за внимание. До новых встреч.
UPD:
UPD: А про "::" я и не вспомнил :( Пруф
Сразу хочу отметить, что если мы говорим об иконках, их можно масштабировать двумя способами (других я просто не знаю): конвертировать иконки в шрифт и подключать их через @font-face, либо использовать SVG в качестве формата для этих иконок.
Немного отойду от темы и расскажу предысторию.
Предыстория
Я было решил использовать у себя на сайте шрифтовые иконки, казалось бы все хорошо: и размер менять можно, и цвет задавать и запрос к серверу всего один (на подключение шрифта). Другими словами, подключаемый шрифт это и есть своеобразный «CSS спрайт», верно?
Я давай проверять, везде ли все красиво выглядит. Оказалось, что не все так хорошо как хотелось бы, потому как в некоторых размерах иконки выглядели кособокими, а при отключенном сглаживании вообще противно смотреть на них стало. Что делать? Использовать второй вариант — SVG, о чем и пойдет речь.
CSS спрайт с SVG
Идея складывать спрайт в SVG формат не нова. Наверняка, многие читали этот пост на smashingmagazine. Так вот, я решил развить мысль автора, поэкспериментировать и предложить более гибкий вариант. А чтобы стало все понятно, некоторые примеры повторю здесь.
Итак, для начала нам нужно сделать SVG спрайт. Как сделать SVG файл программно я пока не разобрался (надеюсь сообщество меня простит и даст ссылку где про это почитать). Поэтому я буду делать свой спрайт в CorelDRAW (Illustrator думаю тоже подойдет) и сохранять в 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 создан с четко заданными размерами 76x520, т.е. максимальный размер до которого мы можем увеличить нашу иконку будет 76x76.
А что если сохранить 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, то у нас вместо одной иконки получится весь спрайт размером 20x20 пикселей.Кроме того, на размер иконки теперь еще влияет ширина и высота блока формируемая псевдоэлементом, т.е. вместе с
background-size
теперь нужно менять width
и height
, чтобы иконка не обрезалась.Высчитываем относительные размеры
Пожалуй, это ключевой момент и здесь стоит сделать выбор, либо вы задаете абсолютные размеры и при изменении
background-size
, width
и height
меняете их тоже, либо (что сложнее) высчитываете относительные размеры и при изменении background-size
, width
и height
больше ничего не меняете.Итак, фактический размер спрайта 500x250 пикселей, по 10 иконок в строчку и по 5 в столбик, итого 50 иконок (в примере 49) размером 50x50 пикселей каждая.
Высчитать размер довольно просто, т.к. будем отталкиваться от фактического размера спрайта. Кто работал со спрайтами объяснять не стоит. Правда здесь есть одна тонкость — размер иконки у нас уменьшен до 20 пикселей, соотвественно спрайт тоже изменился и стал равен 200x100 пикселей (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
Допустим, у нас есть некий дизайн, совсем приблизительно изобразил (кликабельно):
Предположим, что прямоугольники это какие-то красивые клипарты, трудно, но предположим. Что мы можем сделать:
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: А про "::" я и не вспомнил :( Пруф
Похожие публикации
- +36CSS Sprites 2: время Javascript2,7k 96 48
- +33CSS Sprites — зло, не используйте их!2,2k 43 59
- +89
Самое читаемое
- Почему я больше не использую MVC-фреймворки 38
- Медведь, расчленёнка и 14 февраля 9
- Security Week 06: банковский грабеж на потоке, взлом энергосетей, Посейдон/Амебей/Кианохет 0
- Катя, Go, Dcoin и Android 30
- Android VIPER на реактивной тяге 17
- Сколько котов на хабре? 95
- Понимание сборки мусора и отлов утечек памяти в Node.js 3
- Единорог в космосе: проверяем исходный код 'Space Engineers' 10
- Нейрореволюция в головах и сёлах 89
- 43 полезных сервиса для управления проектами. Без эпитетов 32
Комментарии (73)