Создание спрайтов в GULP 4 с поддержкой Retina

Для оптимизации запросов на сервер можно объединить иконки и небольшие картинки, которые используются в css, в один файл — спрайт. Есть различные сервисы для автоматической сборки иконок и создания для них файла стилей, чтобы не высчитывать самому пиксели, но мы будем делать сборку спрайтов внутри своего проекта с использованием GULP 4.

Исходные данные:
В папке images/sprite-icons лежат файлы с такими именами: icon-fb.png, icon-fb@2x.png, icon-gp.png, icon-gp@2x.png и т.д.

Создание спрайтов в GULP 4 с поддержкой Retina

Устанавливаем данные пакеты
gulp
gulp.spritesmith
merge-stream

Подключаем модули

var gulp         = require('gulp'),
    spritesmith  = require('gulp.spritesmith'),
    merge        = require('merge-stream');

Базовый вид задачи для сборки спрайта выглядит так:

gulp.task('sprite', function () {
  var spriteData = gulp.src('images/*.png').pipe(spritesmith({
    imgName: 'sprite.png',
    cssName: 'sprite.css'
  }));
  return spriteData.pipe(gulp.dest('path/to/output/'));
});

Кастомизированная версия сборки спрайта для моего проекта на GULP 4 (разъяснения ниже):

// Generate Sprite icons
gulp.task('sprite', function () {
  // Generate our spritesheet 
  var spriteData = gulp.src('app/images/sprite-icons/*.*')
  .pipe(spritesmith({
    imgName: 'sprite.png',
    imgPath: '../images/sprite.png',
    cssName: '_sprite.scss',
    retinaSrcFilter: 'app/images/sprite-icons/*@2x.png',
    retinaImgName: 'sprite@2x.png',
    retinaImgPath: '../images/sprite@2x.png',
    padding: 5
  }));
 
  // Pipe image stream onto disk 
  var imgStream = spriteData.img
    .pipe(gulp.dest('app/images/'));
 
  // Pipe CSS stream onto disk 
  var cssStream = spriteData.css
    .pipe(gulp.dest('app/scss/mixins'));
 
  // Return a merged stream to handle both `end` events 
  return merge(imgStream, cssStream);
});

gulp.src('app/images/sprite-icons/*.*') — путь, по которому берутся иконки для создания спрайта.
imgName: 'sprite.png' — имя сгенерированного спрайта-картинки.
imgPath: '../images/sprite.png' — относительный путь, который будет указан в файле CSS к спрайту.
cssName: '_sprite.scss' — имя сгенерированного файла стилей, если имя будет с расширением .css, то в нем будут все правила для спрайтов, если это будет scss, то будет сгенерирован файл с миксинами .scss.
retinaSrcFilter: 'app/images/sprite-icons/*@2x.png' — путь к файлам для создания спрайта для ретины, если вы хотите поддерживать Retina, тогда количество иконок @2x.png должно быть таким же как и для обычных экранов, и их размер должен быть 2x.
retinaImgName: 'sprite@2x.png' — имя сгенерированного спрайта-картинки для Retina.
retinaImgPath: '../images/sprite@2x.png' — относительный путь, который будет указан в файле CSS к спрайту для Retina sprite@2x.png.
padding: 5 — отступ между иконками внутри спрайта (по умолчанию 0) — рекомендую делать хоть небольшой отступ, потому как при плотном размещении на некоторых экранах у иконки может отображаться сбоку или снизу-сверху часть рядом стоящей в спрайте иконки.
gulp.dest('app/images/') — конечная директория, куда будет помещен спрайт с иконками.
gulp.dest('app/scss/mixins') — конечная директория куда будет помещен файл с миксинами _sprite.scss.

Оптимизацию и сжатие картинок (в том числе полученного спрайта) я делаю в отдельной задаче при билде, подробнее про правильное сжатие изображений читайте в этой статье Как оптимизировать и максимально сжать изображения в GULP 4 с помощью gulp-imagemin.

Всю подробную документацию можно найти здесь https://www.npmjs.com/package/gulp.spritesmith.

Использование сгенерированного спрайта и файла стилей для этого спрайта

Используем в html:

<i class="icon icon-fb"></i>

В своем файле стилей зададим какие-то общие правила для .icon:

.icon {
  display: inline-block;
}

Если в cssName вы используете файл с расширением .scss, тогда по моему примеру у вас сгенерируется файл с миксинами '_sprite.scss', и затем в своем файле стилей подключаете миксин с правилами для спрайтовых иконок:
@include sprites($spritesheet-sprites); — сгенерирует все правила для стандартных иконок без Retina;
@include retina-sprites($retina-groups); — сгенерирует все правила для стандартных иконок и для Retina.

Пример сгенерированного спрайта:

Пример части из сгенерированного файла стилей (после компиляции из scss):

.icon-fb {
  background-image: url(../images/sprite.png);
  background-position: 0 0;
  width: 48px;
  height: 48px
}

@media (-webkit-min-device-pixel-ratio: 2),(-o-min-device-pixel-ratio:2/1),(min-resolution:192dpi) {
  .icon-fb {
    background-image:url(../images/sprite@2x.png);
    background-size: 154px 154px
  }
}

Если в cssName вы используете файл с расширением .css, то вид сгенерированного файла стилей будет немного другой и почему-то совсем другие классы, так что осторожно с этим.

.icon-icon-fb {
  background-image: url(../images/sprite.png);
  background-position: 0px 0px;
  width: 48px;
  height: 48px;
}
.icon-icon-gp {
  background-image: url(../images/sprite.png);
  background-position: -53px 0px;
  width: 48px;
  height: 48px;
}
...
@media (-webkit-min-device-pixel-ratio: 2),
       (min-resolution: 192dpi) {
  .icon-icon-fb {
    background-image: url(../images/sprite@2x.png);
    background-size: 154px 154px;
  }
  .icon-icon-gp {
    background-image: url(../images/sprite@2x.png);
    background-size: 154px 154px;
  }
...

Если хоть кто-то дочитал это до конца, или кому-то данная информация пригодилась, то поставьте в комментариях «+» или «спасибо».

Как оптимизировать и максимально сжать изображения в GULP 4 с помощью gulp-imagemin

В общем, перепробовал десятки разных плагинов и настроек, но .jpg совсем не оптимизировались, а иногда…

Бесконечный анимированный фон с эффектом параллакса

Бесконечный анимированный фон с эффектом параллакса создан на основе варианта 2 из этой статьи HTML…

Изменение внешнего вида чекбоксов и радио-кнопок с помощью CSS

Изменение внешнего вида для чекбокса с помощью CSS HTML для чекбокса или радио-кнопок CSS для…

Бесконечный фон с автопрокруткой

Вариант 1 — с помощью JS меняем позицию фонового рисунка <div id="bg"></div> var y =…

4 комментария

Спасибо, значит не зря потратил время на данную инструкцию!)

Василий

спасибо за материал, хорошее решение с ретиной (хотя и предпочитаю svg)

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

Ответить