Создаю спрайт с помощью gulp (плагин gulp-svg-sprites). В Mozilla отображается нормально,
в хроме открываю - всё сдвинуто.
Если из конечного svg я генерирую png-спрайт (плагин gulp-svg2png), и подключаю его
вместо svg, то во всех браузерах отображается нормально. т.е. я так понимаю это что-то
связано именно из интерпретацией браузером.
Как исправить?
Пример моего спрайта после галпа есть здесь . При изменении размеров бегунком в хроме
этот баг тоже можно увидеть (хорошо заметно при максимальном увеличении, на белых -
когда инвертировать фон).
В мозиле всё нормально.
P.S. Обновил спрайт - установил, чтобы viewBox у всех элементов начинался с "0 0.
не помогло.
Настройки gulp:
gulp.task('svg-sprites:build', function () {
return gulp.src(options.theme.img_svg_src + '*.svg')
.pipe(svgSprite())
.pipe(gulp.dest(options.theme.img_src + 'dict'))
.pipe(filter(options.theme.img_src + 'dict/svg/*.svg'))
.pipe(gulp.dest(options.theme.img_src + 'dict'));
});
Ответы
Ответ 1
Короткий ответ
Удалите атрибут viewBox="0 0 41 2023" из SVG. Впрочем, остальные viewBox тоже можете
удалить. Можно сделать это автоматически с помощью svgo (плагин removeViewBox).
Длинный ответ
Это похоже на баг Chrome, связанный с расчетом background-size, когда background-size
по горизонтали не кратен ширине viewBox в SVG.
Смотрите, у вас background-size задается в em: 4.1em 202.3em (sprite.css:5). А изменение
размеров картинок задается через font-size от 2 до 14 px. Исходное значение font-size
равно 10px, поэтому при открытии страницы размер фона в пикселях получается 41x2023
px, как раз как viewBox в SVG. Можно прописать background-size: 41px 2023px и все останется
по-прежнему.
Но если указать на пиксель меньше: background-size: 40px 2023px, мы увидим смещение
по вертикали. Хотя, казалось бы, картинка должна стать просто немного уже.
Поэтому при изменении шрифта все едет. Если задать размер шрифта 11px, то ширина
фона получится 4.1em * 11px = 45.1px, а это не кратно 41 (ширина исходного viewBox).
Следующее значение шрифта, при котором все показывается нормально - 20px: размер background-size
по горизонтали становится 82px, что кратно 41.
Я точно не берусь описать все особенности этого бага (иногда он проявляется, иногда
нет), но суть в том, что решение простое: удалите атрибут viewBox="0 0 41 2023" из
SVG. Впрочем, остальные viewBox тоже можете удалить.
Можно сделать это автоматически с помощью svgo (плагин removeViewBox). Пример для gulp:
gulp.task('remove-viewbox', function() {
var svgmin = require('gulp-svgmin');
return gulp.src('src/*.svg')
.pipe(svgmin({
plugins: [ {removeViewBox: true} ]
}))
.pipe(gulp.dest('dest/'));
});
Ответ 2
Вы наверное уже догадались, что в Chrome видите вместе с основной иконкой низ предыдущей
иконки.
Причин тут может быть много, но основных две:
У каждого браузера свои стили, поэтому лучше их сбросить отдельным файлом reset.css
от Эрика Майера, либо применить Normalize.css, почитайте перевод статьи здесь.
Вторая, основная причина - подбор иконок с разными пропорциями.
У одних width="7" height="7" viewBox="0 0 7 7, у других viewBox="231 233 38 34 Видите,
тут пришлось двигать иконку с помощью viewBox. И дальше, если посмотреть, запустите
SVG файл спрайта локально, то увидите большие пробелы, это просто иконки не попадают
в зону видимости.
Чтобы избежать таких рисков и непоняток, может быть проще найти SVG иконки с одинаковыми
атрибутами. Таких подборок очень много в сети, где прямо они отсортированы по размерам
32x32; 64x64; 128x128...
Ответ 3
Вариант 1: удаление у исходных файлов ViewBox
Используйте плагины gulp-imagemin и imagemin-svgo для удаление ViewBox:
var
gulp = require('gulp'),
svg-sprites = require('gulp-svg-sprites'),
imagemin = require('gulp-imagemin'),
imageminSvgo = require('imagemin-svgo');
gulp.task('svg-sprites:build', function () {
return gulp.src(options.theme.img_svg_src + '*.svg')
.pipe(imagemin([
imageminSvgo({
plugins: [
{removeViewBox: true}
]
})
]))
.pipe(svgSprite())
.pipe(gulp.dest(options.theme.img_src + 'dict'))
.pipe(filter(options.theme.img_src + 'dict/svg/*.svg'))
.pipe(gulp.dest(options.theme.img_src + 'dict'));
});
Вариант 2: заменить SVG-спрайт на иконочный шрифт
Предпочтительней было бы использование иконичного шрифта вместо спрайтов. И у этого
метода есть ряд преимуществ:
Более меньший вес шрифта, чем спрайта;
Гибкость стилизации через CSS;
Меньший вес CSS.
Для генерации иконочного шрифта я бы посоветовал такую комбинацию:
// Generate icon font
gulp.task('iconfont', function() {
var
fontName = 'icon-font',
cssClass = 'i';
// Исходные SVG-файлы
gulp.src(['./fonts/icon-font/*.svg'])
.pipe(iconfontCss({
fontName: fontName,
cssClass: cssClass,
path: './styl/mixins/icon-font.styl',
targetPath: '../../styl/components/font/icon-font.styl',
fontPath: '../fonts/'
}))
.pipe(iconfont({
fontName: fontName,
prependUnicode: true,
normalize: true,
formats: ['svg','ttf','woff','woff2']
}))
.pipe(gulp.dest('./public/fonts/'));
});
Миски для стилей, который берется из этой строки path: './styl/mixins/icon-font.styl'
будет выглядеть так:
@font-face
font-family "<%= fontName %>"
src: url('<%= fontPath %><%= fontName %>.woff2') format('woff2'),
url('<%= fontPath %><%= fontName %>.woff') format('woff'),
url('<%= fontPath %><%= fontName %>.ttf') format('truetype'),
url('<%= fontPath %><%= fontName %>.svg#<%= fontName %>') format('svg')
[class*="i-"]
position relative
display inline-block
width 1em
height 1em
&:before
font 14px '<%= fontName %>'
font-size inherit
text-rendering auto
speak none
font-variant normal
text-transform none
color inherit
position absolute
top 50%
left 50%
transform translate(-50%, -50%)
<% _.each(glyphs, function(glyph) { %>
.<%= cssClass %>-<%= glyph.fileName %>:before
content "\<%= glyph.codePoint %>"
<% }); %>
После генерации шрифта все, что вам нужно будет сделать, это подключить сгенированный
CSS к вашему сайту или инглудить его к главному CSS-файлу, а затем использовать таким
образом:
Ответ 4
Я взял ваш спрайт и для наглядности немного отформатировал код, не изменяя его сущности.
Обратите внимание, что за вертикальные пробелы между иконками отвечают атрибуты viewport,
которые обычно не указывают, так как по умолчанию они x="0" y="0" - это верхний левый
угол. В вашем варианте для первой иконки y="0", для второй иконки - y="32", далее y="64"
То есть вертикальное позиционирование исключительно зависит от этих параметров.
Первый вариант решения - необходимо увеличить зазоры между иконками, то есть увеличитьY
Внизу пример, как было, видите практически нет зазора между иконками. Во втором примере
зазор увеличен на 8px; y=0;40;80;120
Учитывая, что в вашем варианте вы жестко привязаны к позиционированию иконок внутри
спрайта и как выясняется это может приводить к непредсказуемым эффектам, можно предложить -
Второй вариант
сделать классический спрайт, используя теги и команды вызова
Комментариев нет:
Отправить комментарий