CSS спрайты из командной строки

Да, инструменты для создания CSS спрайтов существуют. Я даже сделал один такой сервис. Но они время от времени ломаются (как сейчас, мой). Но и командная многого стоит, и imagemagick. Давайте посмотрим, как мы можем создавать CSS спрайты только из командной строки.

Создание картинки


Начнем с того, что у нас есть список отдельных файлов:
$ ls

1.png  2.gif  dot.png  phoney.gif  tw.gif

  • — 1.png
  • — 2.gif
  • — dot.png
  • — phoney.gif
  • — tw.gif

Сделаем из них спрайт:
$ convert *png *gif -append result/result-sprite.png

Да, это все. Смотрим результат.



Подробнее


Команда imagemagick обычно выглядит так:
$ convert image1.png image2.png image3.png -append result/result-sprite.png

Мы можем заменить список картинок звездочкой:
$ convert * -append result-sprite.png

Или как в предыдущем случае маской *.gif и *.png.
А как насчет горизонтального спрайта? Все что нужно — заменить -append на +append:
$ convert *png *gif +append result/result-sprite-horizon.png


Результат:


Также заметьте, что исходные картинки могут быть любого формата — GIF, PNG, JPEG, на выходе получаем PNG. Я бы рекомендовал начинать с PNG8:
$ convert *png *gif -append PNG8:result/result-sprite-horizon.png


CSS


Так как это все ручные операции, CSS автоматически не генерируется. Но это также довольно просто. Возьмем вертикальный спрайт:


Все картинки будут иметь свойство background-position-x равным 0px.
У первой картинки 16x16 координата background-position-y также 0px. Тогда:
.first {
  width: 16px;
  height: 16px;
  background: url(result/result-sprite.png) 0 0;
}

… где координаты 0 0 необязательны и их можно опустить.
Вторая картинки также 16x16, так удобнее. Ее X координата равна 0, а Y — высота предыдущей картинки с противоположным знаком:
.second {
  width: 16px;
  height: 16px;
  background: url(result/result-sprite.png) 0 -16px;
}

И так далее. Y координата = Y предыдущего элемента — высота предыдущего.
Но… но… каждый раз выяснять размеры и отслеживать высоту? Вы шутите?
Imagemagick приходит на помощь. 'identify' позволяет получить основную информацию о картинке:
$ identify 1.png

1.png PNG 16x16 16x16+0+0 DirectClass 8-bit 260b

'identify' также имеет опцию '-format' и поддерживает маску *. Поэтому получить всю информацию в приятной форме легко:
$ identify -format "%g - %f\n" *

16x16+0+0 - 1.png
16x16+0+0 - 2.gif
6x6+0+0 - dot.png
10x16+0+0 - phoney.gif
16x16+0+0 - tw.gif

%f — имя файла, %g — геометрия.
\n — перенос строки для удобства вывода на экран.
Поэтому если вы хотите получить Y координату 5 элемента, просуммируйте высоты предыдущих: 16+16+6+16
.last {
  width: 16px;
  height: 16px;
  background: url(result-sprite.png) 0 -54px
}


Немного оптимизаций


Imagemagick не генерирует оптимизированные PNG, поэтому немного оптимизаций необходимы. Вы можете использовать pngout, optipng и др. Или web инструменты, как smush.it или punypng.com.
Или как насчет… smush.it в командной строке:
$ curl http://www.smushit.com/ysmush.it/ws.php?img=http://www.phpied.com/files/sprt/result/result-sprite.png

Резульат — JSON объект:
{"src":"http:\/\/www.phpied.com\/files\/sprt\/result\/result-sprite.png",
 "src_size":1759,
 "dest":"http:\/\/smushit.zenfs.com\/results\/5a737623\/smush\/%2Ffiles%2Fsprt%2Fresult%2Fresult-sprite.png",
 "dest_size":1052,
 "percent":"40.19",
 "id":""}

Экономия почти вдвое. Скопируйте поле «dest»
$ curl http:\/\/smushit.zenfs.com\/results\/5a737623\/smush\/%2Ffiles%2Fsprt%2Fresult%2Fresult-sprite.png > result/smushed-sprite.png

Вот и все.

Подведем итог


1. Создаем спрайт:
$ convert *png *gif -append PNG8:result/result-sprite.png

2. Получаем размеры:
$ identify -format "%g - %f\n" *png *gif

3. И оптимизируем:
$ curl http://www.smushit.com/ysmush.it/ws.php?img=http://url... 


Перевод статьи Стояна Стефанова Command-line CSS spriting.

P. S. Тема ImageMagick уже упоминалась на хабре, но вторая часть этой статьи мне показалась полезной и я решил перевести ее целиком.
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 22
  • +5
    Спасибо за перевод. Да и сама статья хороша, все по делу, без лишней «воды».
    • 0
      Мне нравится. Но открыт вопрос — большинство верстальщиков сидят за виндовыми машинами. Что им делать? Может какой-нибудь скрипт на PowerShell?
    • 0
      В избранное! Этот пост быстро вообще мне прояснил, как делаются спрайты — вручную, в плане CSS, не говоря о таких удобствах, как imagemagick предоставляет… :)
      • +6
        Между спрайтами нужно оставлять не менее 3=х пикселей, чтобы на разных устройствах при масштабировании не было видно соседних картинок.
        • +3
          Сам пользовался этим сервисом, остался доволен. Единственный минус — результирующая картинка отдается в 64-х битах, что для веба не нужно абсолютно. Но результирующую картинку в любом случае нужно оптимизировать, поэтому это обстоятельство не слишком мешает.
          • 0
            а как с помощью imagemagic сделать такой отступ между картинками?
          • +10
            Ещё один вариант создания спрайтов — это использование compass. Приведу пример из презентации iskin:
             $icons: sprite-map("icons/*.png")
            .logo
              background: spirit($icons, logo)
            .contacts
              background: spirit($icons, contacts)
            

            Это сгенерируется код вроде такого:
            .icon {
              background: url('/images/icons.png?123') 0 0 no-repeat;
            }
            .contacts {
              background: url('/images/icons.png?123') 0 -24px no-repeat;
            }
            

            • –25
              Эх, подумал, что Counter-Strike: Source спрэи
              • +1
                Пользуюсь скриптом для фотошопа. Это самый простой вариант обработки большого количества картинок за раз.
                • НЛО прилетело и опубликовало эту надпись здесь
                  • 0
                    Думаю снижает нагрузку на сервер частыми запросами.
                    • НЛО прилетело и опубликовало эту надпись здесь
                      • 0
                        Это настолько распространенная техника, что объяснять вам здесь смысла не имеет никакого. google://CSS+спрайты
                        • НЛО прилетело и опубликовало эту надпись здесь
                          • НЛО прилетело и опубликовало эту надпись здесь
                  • +3
                    Сервисы для автоспрайтов — http://sprites.in/, SpriteMe описание, ссылка. Ещё если кому-то интересно — букмарклеты для оптимизации и тестирования как на мобильных, так и на десктопах.
                    • 0
                      Замечательно, спасибо за перевод.
                      • 0
                        Использовал такое для автогенерации листа и стиля под него в проекте, где содержимое этого листа регулярно меняется (иконки свойств товаров, всего около тысячи)
                        PS: тег source не отработал в предпросмотре

                        public function generateIconSheet() {
                        $xtraIcon = array(
                        // сюда ставил дополнительные иконки, которые хотел разместить на листе, такие как распродажа, лидер продаж, etc
                        );


                        $sql = («SELECT variantID, icoOn, icoOff FROM feature WHERE NOT ISNULL(icoOn)»);
                        $sqlRes = mysql_query($sql);
                        $sheet = new Imagick();
                        $cssCoords = array();
                        $xCoord = 0;
                        $yCoord = 0;
                        $cssStr = "";
                        while ($r = mysql_fetch_assoc($sqlRes)) {
                        extract($r);
                        if (!$sheet->addImage(new Imagick(utils::IMGDIR. $icoOn))) {
                        echo «ERROR!!!»;
                        }
                        $cssStr .= ".ON .ico".$variantID." { background-position: -$xCoord".«px -$yCoord».«px;}\r\n»;
                        $xCoord += (utils::ICONSHEET_ICON_WIDTH + 2*utils::ICONSHEET_ICON_DISTANCE);
                        if ($xCoord > utils::ICONSHEET_WIDTH) {
                        $yCoord += (utils::ICONSHEET_ICON_HEIGHT + 2*utils::ICONSHEET_ICON_DISTANCE);
                        $xCoord = 0;
                        };
                        if (!$sheet->addImage(new Imagick(utils::IMGDIR. $icoOff))) {
                        echo «ERROR!!!»;
                        }
                        $cssStr .= ".OFF .ico".$variantID." { background-position: -$xCoord".«px -$yCoord».«px;}\r\n»;
                        $xCoord += (utils::ICONSHEET_ICON_WIDTH + 2*utils::ICONSHEET_ICON_DISTANCE);
                        if ($xCoord >= utils::ICONSHEET_WIDTH) {
                        $yCoord += (utils::ICONSHEET_ICON_HEIGHT + 2*utils::ICONSHEET_ICON_DISTANCE);
                        $xCoord = 0;
                        };
                        }

                        $result = $sheet->montageImage( new ImagickDraw(),
                        utils::ICONSHEET_ICONS_PER_ROW.«x»,
                        utils::ICONSHEET_ICON_WIDTH.«x».utils::ICONSHEET_ICON_WIDTH."+".utils::ICONSHEET_ICON_DISTANCE."+".utils::ICONSHEET_ICON_DISTANCE,
                        imagick::MONTAGEMODE_UNFRAME,
                        «0x0+0+0»
                        );
                        if ($result) {
                        $result->quantizeImage(128, Imagick::COLORSPACE_YIQ, 10, FALSE, FALSE);
                        echo $result->writeImage(«sheet.gif»);
                        file_put_contents(«sheet.css», $cssStr);
                        }
                        }
                        • НЛО прилетело и опубликовало эту надпись здесь

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