Долой абсолютные единицы в иконках-спрайтах


    Спрайты — классный способ сократить количество запросов к серверу. Можно упаковать кучу иконок в один спрайт и прописать в CSS смещения для каждой иконки. Однако, очень неудобно, что нужно попиксельно всё это считать. Пиксели — значит никакой динамики. Если использовать пиксели, то кусочек спрайта будет отображаться фиксированным размером — независимо от того, выводится он внутри параграфа, или внутри заголовка. Это неправильно, мне кажется, и неудобно. Но, похоже, я нашёл интересный способ выводить иконки динамического размера.

    В первую очередь, нужно перестать думать о спрайте, как о вещи с шириной и высотой, выраженной в пикселях. Спрайт на картинке в заголовке имеет размеры 500 на 100 пикселей, но его нужно воспринимать как спрайт, который имеет размер 10х2. В самом деле, какая разница, сколько у него пикселей? Главное то, что он содержит 10 иконок в ширину и две в высоту.

    Во время вёрстки при описании спрайта просто нужно указать ширину и высоту фонового изображения в относительных единицах — я буду использовать EM. Так как спрайт имеет размер 10 на 2, его можно описать так:

    .icon {
        background-image: url(http://i.imgur.com/DV0Bl7B.png);
        display: inline-block;
    
        /* Ширина — 10, высота — 2. */
        background-size: 10em 2em;
    
        /* Размеры иконки 1х1 — снова относительные единицы, а не абсолютные */
        width: 1em;
        height: 1em;
    }
    
    /* Конкретная иконка. Смещение прописывается опять же в относительных единицах */
    .icon-ok-black {
        background-position: -7em -1em;
    }
    


    За счёт того, что все размеры указываются в относительных единицах, иконка будет автоматически подстраиваться под размер шрифта — в заголовке она будет соответствовать размеру шрифта заголовка, в абзаце — размеру шрифта абзаца, и так далее. Можно сделать один спрайт, например, с размером каждой иконки в 50 пикселей, и эти 50 пикселей будут всегда масштабироваться до размера 1em в текущем контексте.

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

    Пример на JSFiddle: jsfiddle.net/vdfqdfen
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 54

      +17
      Ну да, ну да. И получаем смазанные (нечеткие) иконки. Если уж использовать данный метод, то точно не для раста, а для вектора (SVG).

      Использовать подобное для растра — вредный совет, достойный книги Г. Остера.
        –7
        Я до SVG пока что не добрался просто — не было связанных с этим проектов.
          0
          А для растровых изображений, если хоть немного думать о глазах пользователя, гораздо лучше подойдут другие инструменты. Например, gulp.spritesmith.
            0
            Это немного не то. Gulp.spritesmith создаёт спрайты и CSS-код из набора изображений. Создание спрайтов — немного выходит за пределы этой статьи. Она — про использование готовых спрайтов. К тому же, gulp.spritesmith прописывает всё в абсолютных единицах — это прямо противоположно тому, о чём я писал и чего я пытался добиться в статье.
              +2
              мой вам совет не пишите велосипеды, тем более там где есть готовые крутые решения в виде автоматизации, взять например тот же compass
                +1
                В определённых ситуациях, согласитесь, мой метод выглядит элегантно — минимум кода, и иконки сами подстраивают свой размер. Если подходить к нему без фанатизма и не пихать везде, где это возможно, он тоже имеет право на жизнь. Технически, метод работает. Кому-то не нравится результат, кому-то нравится.

                В остальном: как я вообще смогу развиваться, если я буду только использовать всё готовое? Мне важно развиваться. И дело не только в том, что подход, который я описал, можно или нельзя применить. Дело в том, что он развивает моё мышление — я учусь смотреть на вещи с разных сторон. Если использовать только всё готовое и вообще не напрягаться, то, по-моему, это самый верный способ прекратить своё развитие.

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

                  ЗЫ, тоже не обижайтесь только, но не говорите никогда ни кому что вам не пригодятся решения автоматизации)) еще скажите галп/грант это для чудаков. Автоматизация признак профессионализма нежели выпендреж.
                    0
                    Именно поэтому я написал «конкретно эти» и упомянул, что они не совсем корректно подходят к ситуации — чтобы никто не подумал, будто я вообще против любых готовых решений, которые могут облегчить жизнь.

                    Но профессионалом я тоже быть не хочу. Они: а) аномально много работают; б) болеют снобизмом чаще, чем непрофессионалы и ещё куча всяких плохих пунктов «ц».
              0
              Но, в целом, за ссылку спасибо. Сам по себе gulp.spritesmith — классный инструмент.
            +1
            Почему? а если у нас в спрайте (PNG) размер одной иконки допустим 256*256 пикселей? Разве тоже мутные получатся?

            А вот SVG спрайты это ад, в FF кажется, оно перерисовывается с дикими мерцанием, если изменять размер окна.
              +15
              ни разу не изменял размер окна, кроме как для того, чтобы проверить мерцает ли.
                0
                Вы не верстаете резиновые/адаптивные макеты?
                  +6
                  Конечно же верстаю как программист. Но как юзер я не занимаюсь глупостями.
                +4
                Если уменьшить иконку 256х256 до 16х16, ничего хорошего, скорее всего, не выйдет. Не говоря уже о некратных размерах.
                  0
                  Я не уверен но вроде бы в макоси то как раз иконки по 2048х2048 и ресайзяца повсюду. Вроде норм.
                    0
                    1) Не МакОсью единой жив компьютер. МакОсь, особенно системное сглаживание (особенно шрифтов), всегда славилось своей элегантностью и красотой.

                    2) Рендеринг в браузере можешь сильно отличаться от системного рендеринга, зависит не только от оси, но и браузера и алгоритмов, а текже, иногда и аппаратного ускорения (включено/выключено)

                    3) Ну и главное — ЗАЧЕМ грузить картинку такого разрешения? Вы представляете размер файла при градиенте например?
                    Полтора года назад писал материал "Кроссбраузерный SVG логотип", там я приводил сравнение размера файла
                    SVG версия логотипа весит в несколько раз меньше. Для примера логотип из статьи в PNG 300×83 весит 6 Кб, в SVG — 2,8 Кб, в SVGZ — 1,2 Кб.

                    Хотя это в любой статье можно встретить про преимущества SVG на растром.
                      0
                      Я не против SVG, мое сообщение на которое вы отвечаете не о том что PNG лучше.
                      А о том что даунсайз иконок это нормально так как пример такого даунсайзы есть в промышленных продуктах. (Например в макоси).

                      Касательно темы в целом мое мнение изложено ниже, я считаю что подход хоть и заслуживает внимания но только в академических целях. На практике проще и удобней использовать icon fonts.
                      0
                      Иконки приложений в макосе имеют расширение icns – icon set, внутри, как и у виндовых ico, набор кратных размеров: 1024, 512…
                      Иконки для интерфейсов, как и в iOS-приложениях, прикладываются в двух размерах – обычный и увеличенный в два раза для ретины, с приставкой @2x. Лишь векторные данные (обычно в виде pdf) не нуждаются в экспорте под конкретные размеры.
                      0
                      В современных браузерах масштабирование и сглаживание работает уже неплохо. Даже на некратных размерах.
                      Хотя глаз перфекциониста может заметить некоторые артефакты, но с SVG они тоже будут.
                        0
                        Когда речь начинает идти о иконках совсем низкого разрешения вроде 16х16 или 10х10, то тут любой способ масштабирования пасует, приходится править руками. Сглаживание даст лишь сильно замыленную версию оригинала.
                    +2
                    Или создавать из этих SVG иконочный шрифт(если иконки именно такие как в КДПВ, одноцветные) — и весит немного, и работать удобнее, чем со спрайтами.
                      +1
                      Десять причин нашего перехода с иконочного шрифта на SVG. И кстати, иконки могут быть многоцветные.
                        0
                        Да я и не претендую на идеальность решения. Во всём есть свои плюсы и минусы.
                          0
                          Разумеется, но лучше о них знать и показал другую сторону медали: «против шрифтов», а то многие же кинуться их внедрять везде и всюду не подумав, учитывая, что у статьи метка tutorial.

                          Материал по приведенной мной выше ссылке считаю очень хорошим и познавательным, поэтому и дал. Правда в ней мало технической стороны.
                    0
                    > Однако, имейте ввиду, что при масштабировании растровых изображений графика может размываться. Возможно, этот способ лучше всего подходит для векторной графики — SVG, например.
                    Если у нас будет сотня векторных иконок, не начнет ли тормозить браузер?
                      0
                      Я честно не знаю. Если бы вы процитировали весь абзац, то было бы видно, чьё это было замечание и кто может лучше ответить на этот вопрос. У меня нет опыта работы с векторной графикой — я об этом писал чуть выше. Я боюсь, что буду глупо выглядеть, если начну рассуждать о вещах, в которых не разбираюсь.

                      Но я буду очень благодарен, если вы этот момент протестируете и напишете, как это может сказаться на производительности.
                      • UFO just landed and posted this here
                          +1
                          Можно ссылку на тест?
                          Проверю на паре мобильных устройств: производительном и слабом.
                          • UFO just landed and posted this here
                              0
                              Ну зуб хотя-бы дадите? :)
                        +3
                        Вы на несколько лет опоздали со своим постом. Проблема спрайтов давно решена. compass-style.org/help/tutorials/spriting/
                          +1
                          Автор не описывает способ создавать спрайты.
                          Суть проблемы: У вас есть спрайт с иконками 10х10 пикселей.
                          Теперь где бы вы не вставили вы увидите иконку размером 10х10.
                          Описаный же способ делает размеры иконок относительными размеров текстового блока в которых они отображаются.

                          Остается только подготовить спрайт с иконками достаточного размера так что бы на любых размерах они не размывались
                            –2
                            Compass собирает спрайт из иконок любого размера, автоматически проставляя необходимые смещения.
                              +2
                              Так ведь не в смещениях дело.

                              Покажу на примере.

                              <p>
                                  <span class="icon-ok"></span>
                              </p>
                              
                              <h2>
                                 <span class="icon-ok"></span>
                              </h2>
                              


                              Размер иконки будет соответствовать размеру шрифта p и h2
                                0
                                автоматически проставляя необходимые смещения

                                [...] в абсолютных единицах. И, получается, такая иконка не будет реагировать на контекст, в котором используется — всё время будет фиксированного размера — и в заголовке, и в обычном тексте.
                                0
                                Остается подготовить спрайт в котором все элементы имеют кратные пропорции. Да еще и вручную.
                                  0
                                  Ну тут как бы и не декларируется универсальность способа. Он имеет смысл как раз для однотипных элементов типа иконок.
                                  А что до «ручной генерации» так на то вам sass и дан что бы написать свой sprite-генератор на em'ах.

                                  Вообще читая комментарии к этому топику я встретил бездну непонимания проблемы от вроде-бы осведомленных людей (знают что такое compass)

                                  И никто не упомянул про то что юзать иконки из спрайтов уже не модно, гораздо прогрессивней юзать иконковые шрифты наподобие Font Awesome.
                                    0
                                    Непонимание от того, что описание проблемы имеет широкую смысловую расплывчатость. Если оратор не понят — виноват оратор.
                                      +1
                                      Не ну там даже fiddle есть, но тем не менее люди почему-то начинают писать про «компасс уже придумали для этого». Т.е человек прочитал невнимательно, по ссылке не прошел, но высокомерные советы уже раздает. Как-то это не правильно кмк.
                                        0
                                        Еще раз: проблема описана не однозначно, отсюда — решение выглядит непонятным. Вы предлагаете совершить слишком много действий, для того, чтобы понять, что автор имел в виду в той или иной фразе.
                                          0
                                          Я предлагаю всего лишь прочитать весь текст поста. Код на фиддле де-факто тоже часть поста.
                                            0
                                            А я предлагаю четко изъясняться. Тупик!
                                              0
                                              У вас есть какие-то проблемы с пониманием поста? Скажите, что нужно изменить, чтобы он легче воспринимался? Я буду рад его поправить.
                                      0
                                      Мне в шрифтах нравится только то, что монохромные иконки можно раскрашивать, задавая цвет текста. А вообще, спрайты универсальнее. В них можно хранить и иконки и куски фона и даже нарисованные буквы. И спрайты ведут себя более предсказуемо. Они решают больше проблем, чем создают. Спрайты, возможно, — не модно. Но у людей с модой всё время такие отношения: они начинают фанатеть и надевают на себя все модные вещи сразу, из-за чего выглядят некрасиво.

                                      Со шрифтовыми иконками могут быть тоже проблемы. Они ведь зависят от области частного использования Unicode. На отдельных устройствах из-за этого могут выводиться совсем другие глифы. У вас на нескольких устройствах всё будет замечательно выглядеть во время тестирования, но отдельные посетители получат не ту картинку, которую вы хотели показать. И вы об этом никогда не узнаете. Разве это хорошо — такая непредсказуемость? Спрайты отрисовывают одну и ту же картинку. По одним и тем же координатам спрайта всегда будет находиться одна и та же картинка на любом устройстве.

                                      Шрифт может отображаться по-разному в разных браузерах на разных платформах. Где-то он будет выглядеть жирнее, где-то — тоньше. Где-то он вообще не подгрузится из-за того, что вы забыли ещё какой-нибудь дублирующий формат шрифта прикрутить — какой-нибудь браузер не хочет грузить WOFF — и всё, нет иконок (для самой полной гарантии нужно подключить SVG, WOFF, WOFF 2.0, EOT, и TTF/OTF). С другой стороны, спрайт не будет грузиться только в том случае, если в браузере отключены картинки, если он, конечно же не в каком-нибудь экзотическом формате.

                                      Одной шрифтовой иконкой нельзя вывести разноцветное изображение. У шрифтовой иконки только два цвета: прозрачность и цвет шрифта. Если понадобятся 3-4-5-∞-цветные иконки, то понадобится что-то ещё, отличное от шрифтов — спрайты, например (ну, или, отдельные картинки, каждая из которых будет добавлять ещё один лишний HTTP-запрос). Картинка 10х10, например, может состоять из 100 разных цветов. Шрифт так не умеет.

                                      Чтобы анимировать шрифтовую иконку нужно писать сложный CSS. И чем сложнее нужна анимация, тем больше будет CSS-кода. В определённых ситуациях GIF-файл с анимацией будет весить меньше, чем CCS-код, который требуется, чтобы повторить такую анимацию на иконочном шрифте.

                                      Со шрифтами нужно быть аккуратнее в плане «same origin» (см. Known Issues — вот здесь). Просто так прицепить шрифты со стороннего ресурса может и не получиться. Для большей уверенности нужно будет располагать CSS-файл со ссылками на шрифт на том же домене, что и сами файлы шрифта. Спрайты можно откуда угодно тянуть и не париться насчёт «same origin».

                                      Что вы будете делать, если вам не нравится иконка в шрифте, но её аналога нет? Как вы думаете, что проще: отредактировать одну картинку со спрайтом или 3-4 файла со шрифтами? Это ещё одна сложность, которую даёт иконочный шрифт: приходится хавать то, что дают, потому что нет простых способов настроить под себя иконочный шрифт. Картинки править намного легче.

                                      Я могу ещё пару примеров написать, но что-то и так слишком объёмно получилось. Мне кажется, что куча сложностей, геморроя и дополнительной работы, которые добавляют иконочные шрифты, если ситуация хоть чуть-чуть отличается от стандартной — это основная причина, по которой никто не упоминает, что иконочные шрифты — гораздо лучше спрайтов.
                                        0
                                        Вы все верно говорите, просто для каждой задачи свой инструмент.
                                        Для квадратных стандартных одноцветных иконок — шрифт.
                                        Для разномастных разнораpмерных картинок — спрайт.
                                        emoji опять же
                                        просто не надо пытаться придумать универсальную отвертку
                                +3
                                Есть проблема в этом способе, IE округляет em до двух знаков после запятой, иногда спрайты начинают мылицца
                                  0
                                  Способ никуда не годится если речь идет о четкости иконок. Вариант приемлем только для SVG, и то там немного иной воркфлоу.

                                  Кроме того, за бортом остаются старые IE и по-моему еще Opera mini.
                                    +2
                                    а почему бы не использовать icon font? Тогда вместо дублирования изображений можно будет просто цвет использовать
                                      0
                                      У шрифтов есть свои минусы тоже:
                                      — вес чаще всего больше, чем у локального спрайта (когда нужно показать несколько иконок)
                                      — фонты всякими опера мини тупо режутся и пользователь наблюдает квадратики
                                      — стили шрифтов обычно используют псевдоэлементы, а они несколько тупят на больших проектах, если явно не задавать размеры.
                                        +1
                                        А еще рендеринг шрифтов отличается между браузерами и платформами, поэтому значки так или иначе будут выглядеть везде по разному — мелочь, конечно, но точно не подойдет тем, кто вынужден работать с любителями pixel perfect верстки.
                                          0
                                          Ну не могу согласиться.

                                          вес чаще всего больше, чем у локального спрайта (когда нужно показать несколько иконок)

                                          Можно же создать свой набор иконок (небольшой), а не использовать font awesome (хотя для больших проектов он точно подойдет).

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

                                          В смысле? А что мешает задавать размеры явно? Вы же знаете какого размера должна быть иконка.

                                          фонты всякими опера мини тупо режутся и пользователь наблюдает квадратики

                                          Какой нынче процент пользователей Opera Mini? Давайте еще IE 6 вспомни, им тоже наверняка еще кто-то пользуется

                                          ИМХО
                                            +1
                                            Вы делали «свой набор» иконок? У того же font-awesome получается несколько файлов шрифта, да и геморройнее это.
                                            Можно задать, да, никто не мешает, просто об этом часто забывают, мол символ и так занимает место, от чего страница дергается, когда подгружается сам шрифт (пустой тег вдруг получает ширину).
                                            Это вы лихо мини сравнить с ие6.
                                          0
                                          Выше уже частично ответили, а так же я выше уже давал ссылку, но продублирую, ибо статья заслуживает внимания: Десять причин нашего перехода с иконочного шрифта на SVG, также стоит обратить внимание, что в некоторых случаях можно получить доступ DOM к SVG (раз, два, разумеется это не спрайты, хотя через ссылки вроде и спрайтами можно реализовать, ни как не доберусь изучить этот вопрос), а также сделать анимацию и не только.

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

                                          Only users with full accounts can post comments. Log in, please.