Как я могу масштабировать изображение в спрайте CSS


157

В этой статье http://css-tricks.com/css-sprites/ , рассказывается о том, как я могу обрезать меньшее изображение из одного большего изображения. Можете ли вы сказать мне, если это возможно / как я могу обрезать уменьшенное изображение, а затем масштабировать обрезанную область, прежде чем выложить ее?

Вот пример из этой статьи:

A
{
  background-image: url(http://www.jaredhirsch.com/coolrunnings/public_images/3deb155981/spriteme1.png);
  background-position: -10px -56px;
}

Я хотел бы знать, как я могу масштабировать это изображение после того, как я обрезал его из spriteme1.png

Вот URL примера: http://css-tricks.com/examples/CSS-Sprites/Example1After/

Итак, я хотел бы знать, могу ли я сделать значки рядом с Item1,2,3,4 меньше?


Как спросил Стивен, что-то мешает вам рендерить изображения в нужном вам размере?
Пол Д. Уэйт

4
Я попал на эту страницу, так как я искал ответ на ту же вещь. В современном мире с сетчатыми дисплеями высокой четкости принято создавать изображение в два раза больше его размера, а затем использовать значения высоты / ширины в атрибутах <img> или стилях CSS, чтобы уменьшить его до половины высоты / ширины при отображении. Это обеспечивает четкое отображение на смартфонах и планшетах. Но PNG-спрайты отлично подходят для быстрого кэширования и рендеринга. Было бы лучше не только использовать спрайт 2х изображений, но и затем масштабировать его до размера, который делает его также четким.
Арт Гайгель

Поскольку оригинальный вопрос так и не получил приемлемого ответа, и существует довольно аккуратное и обратно совместимое решение, я сделал новую версию Codepen Stretchy , так как оригинальный сайт больше не в сети, и, возможно, еще есть люди, которым нужна отсталость совместимое решение. Я сделал перо с указанием авторства оригинальной работы / автора.
Все биты равны

Ответы:


131

Вы можете использовать background-size , так как он поддерживается большинством браузеров (но не всеми http://caniuse.com/#search=background-size )

background-size : 150% 150%;

Или

Вы можете использовать комбо масштабирования для webkit / ie и transform: scale для Firefox (-moz-) и Opera (-o-) для кросс-браузерного рабочего стола и мобильного

[class^="icon-"]{
    display: inline-block;
    background: url('../img/icons/icons.png') no-repeat;
    width: 64px;
    height: 51px;
    overflow: hidden;
    zoom:0.5;
    -moz-transform:scale(0.5);
    -moz-transform-origin: 0 0;
}

.icon-huge{
    zoom:1;
    -moz-transform:scale(1);
    -moz-transform-origin: 0 0;
}

.icon-big{
    zoom:0.60;
    -moz-transform:scale(0.60);
    -moz-transform-origin: 0 0;
}

.icon-small{
    zoom:0.29;
    -moz-transform:scale(0.29);
    -moz-transform-origin: 0 0;
}

3
Отлично работает в Chrome, хорошо работает в FF, IE9 / 10. Производит желаемый эффект по большей части.
RCNeil

Используя (пример) background-size: 15%; отлично работает для спрайтов, сохраняя правильное соотношение сторон. Это простое решение для использования с точками останова на адаптивных сайтах.
C13L0

1
Свойство background-size не работает для моего svg-спрайта с фиксированной высотой и шириной, однако масштабирование сработало.
Андре

Чтобы добавить поддержку IE8, используйте атрибут -ms-zoom в качестве синонима увеличения в режиме стандартов IE8. -ms-zoom: 0,7; См. Ссылку ниже для получения более подробной информации: msdn.microsoft.com/en-us/library/ms531189(v=vs.85).aspx
Amr

2
Обновление 2017 года: background-size поддерживается всеми основными браузерами, включая IE9 +. caniuse.com/#search=background-size
Натан

29

Когда вы используете спрайты, вы ограничены размерами изображения в спрайте. Свойство background-sizeCSS, упомянутое Стивеном, пока не получило широкой поддержки и может вызвать проблемы с браузерами, такими как IE8 и ниже, и, учитывая их долю на рынке, это нереальный вариант.

Другой способ решить проблему - использовать два элемента и масштабировать спрайт, используя его с imgтегом, например так:

<div class="sprite-image"
     style="width:20px; height:20px; overflow:hidden; position:relative">
    <!-- set width/height proportionally, to scale the sprite image -->
    <img src="sprite.png" alt="icon"
         width="20" height="80"
         style="position:absolute; top: -20px; left: 0;" />
</div>

Таким образом, внешний элемент ( div.sprite-image) обрезает изображение 20x20px из imgтега, которое действует как масштабированное background-image.


2
Как Клетус и Квентин заявляют здесь , это может быть не лучшим подходом. Для меня это компромисс - мне нужно назначить srcпо css.
Джук

-1: Вы не можете смешивать элементы презентации с контентом / данными. <img>должен использоваться только если он является частью контента. в целях дизайна, фоновые изображения являются обязательными.
Шахрияр Иманов

Лучший ответ (а) работает универсально, (б) понятен людям, (в) кратко, ... (г) отделяет представление от содержания.
Боб Стейн

18

Попробуйте это: Stretchy Sprites - кросс-браузер, адаптивное изменение размера / растяжение изображений спрайтов CSS

Этот метод масштабирует спрайты «быстро» так, чтобы ширина / высота изменялась в соответствии с размером окна вашего браузера. Он не использует, background-size поскольку поддержка этого в старых браузерах отсутствует.

CSS

.stretchy {display:block; float:left; position:relative; overflow:hidden; max-width:160px;}
.stretchy .spacer {width: 100%; height: auto;}
.stretchy .sprite {position:absolute; top:0; left:0; max-width:none; max-height:100%;}
.stretchy .sprite.s2 {left:-100%;}
.stretchy .sprite.s3 {left:-200%;}

HTML

<a class="stretchy" href="#">
  <img class="spacer" alt="" src="spacer.png">
  <img class="sprite" alt="icon" src="sprite_800x160.jpg">
</a>
<a class="stretchy s2" href="#">
  <img class="spacer" alt="" src="spacer.png">
  <img class="sprite" alt="icon" src="sprite_800x160.jpg">
</a>
<a class="stretchy s3" href="#">
  <img class="spacer" alt="" src="spacer.png">
  <img class="sprite" alt="icon" src="sprite_800x160.jpg">
</a>

3
Ссылка на самом деле не объясняет теорию здесь. Вы используете div с переполнением: скрытый как область / окно обрезки поверх масштабированной версии изображения спрайта. Вот почему он вообще не использует фоновое изображение. Просто один слой поверх другого в качестве маски.
Саймон

1
должен ли spacer быть изображением или вместо него можно использовать простой div?
Исапир

4
Вот пример CodePen этого. Кажется, работает только для горизонтальных или вертикальных спрайтов. Не сетки.
Вечерняя ночь

Я сделал новую версию Codepen Stretchy , так как оригинальный веб-сайт больше не находится в сети, и, возможно, есть еще люди, которым нужно решение с обратной совместимостью. Я сделал перо с указанием авторства оригинальной работы / автора
All Bits Equal

10

transform: scale(); заставит оригинальный элемент сохранить его размер.

Я нашел лучший вариант, чтобы использовать vw. Это работает как шарм:

https://jsfiddle.net/tomekmularczyk/6ebv9Lxw/1/

#div1,
#div2,
#div3 {
  background:url('//www.google.pl/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png') no-repeat;
  background-size: 50vw;   
  border: 1px solid black;
  margin-bottom: 40px;
}

#div1 {
  background-position: 0 0;
  width: 12.5vw;
  height: 13vw;
}
#div2 {
  background-position: -13vw -4vw;
  width: 17.5vw;
  height: 9vw;
  transform: scale(1.8);
}
#div3 {
  background-position: -30.5vw 0;
  width: 19.5vw;
  height: 17vw;
}
<div id="div1">
  </div>
  <div id="div2">
  </div>
  <div id="div3">
  </div>


Здравствуйте, это не отвечает на вопрос. Вы должны показать три div с разными масштабами одного и того же изображения. В нескольких словах он должен показывать разные размеры «шрифта». Ты можешь починить это?
Роберт

привет @ Роберт. Как насчет сейчас?
Томаш Муларчик

PS Вы заметили поведение, используя единицу измерения VW?
Роберт

Я не уверен, какое поведение вы имеете в виду?
Томаш Муларчик

VW VH масштабируются пропорционально размеру окна просмотра. Я никогда не использовал их до сих пор. Это просто любопытство по поводу вашего опыта их использования. Являются ли они такими «волшебными» или есть проблемы (неожиданное поведение) в некоторых ситуациях, которые вы, возможно, заметили? спасибо
Роберт

7

Вот что я сделал, чтобы сделать это. Имейте в виду, что он не будет работать на IE8 и ниже.

#element {
  width:100%;
  height:50px;
  background:url(/path/to/image.png);
  background-position:140.112201963534% 973.333333333333%;
}

Ширина фонового изображения будет уменьшаться по мере уменьшения родительского #elementразмера. Вы можете сделать то же самое с его высотой, если вы пересчитаете heightв процентах. Единственный сложный момент - вычислить проценты для background-position.

Первый процент - это ширина целевой области спрайта при нормальной ширине, деленная на общую ширину спрайта и умноженная на 100.

Второй процент - это высота целевой области спрайта перед масштабированием, деленная на общую высоту спрайта и умноженная на 100.

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


6

Кажется, это работает для меня.

Если спрайты находятся в сетке, установите background-sizeзначение 100% для количества спрайтов и на 100% для количества спрайтов. Тогда используйте background-position -<x*100>% -<y*100>%где x и y - спрайт на основе нуля

Другими словами, если вы хотите, чтобы 3-й спрайт слева и 2-й ряд был 2 над и 1 вниз, так

background-position: -200% -100%;

Например вот спрайт лист 4х2 спрайтов

введите описание изображения здесь

И вот пример

div {
  margin: 3px;
  display: inline-block;
}
.sprite {
  background-image: url('https://i.stack.imgur.com/AEYNC.png');
  background-size: 400% 200%;  /* 4x2 sprites so 400% 200% */
}
.s0x0 { background-position:    -0%   -0%; }
.s1x0 { background-position:  -100%   -0%; }
.s2x0 { background-position:  -200%   -0%; }
.s3x0 { background-position:  -300%   -0%; }
.s0x1 { background-position:    -0%  -100%; }
.s1x1 { background-position:  -100%  -100%; }
.s2x1 { background-position:  -200%  -100%; }
.s3x1 { background-position:  -300%  -100%; }
<div class="sprite s3x1" style="width: 45px; height:20px"></div>
<div class="sprite s3x1" style="width: 128px; height:30px"></div>
<div class="sprite s3x1" style="width: 64px; height:56px"></div>
<div class="sprite s2x1" style="width: 57px; height:60px"></div>
<div class="sprite s3x0" style="width: 45px; height:45px"></div>
<div class="sprite s0x1" style="width: 12px; height:100px"></div>

<br/>
<div class="sprite s0x0" style="width: 45px; height:20px"></div>
<div class="sprite s1x0" style="width: 128px; height:45px"></div>
<div class="sprite s2x0" style="width: 64px; height:56px"></div>
<div class="sprite s3x0" style="width: 57px; height:60px"></div>
<br/>
<div class="sprite s0x1" style="width: 45px; height:45px"></div>
<div class="sprite s1x1" style="width: 12px; height:50px"></div>
<div class="sprite s2x1" style="width: 12px; height:50px"></div>
<div class="sprite s3x1" style="width: 12px; height:50px"></div>

Если спрайты имеют разные размеры, вам нужно установить background-sizeдля каждого спрайта значение a, чтобы ширина этого спрайта составляла 100%.

Другими словами, если изображение имеет ширину 640 пикселей и спрайт внутри этого изображения имеет ширину 45 пикселей, то для получения 45 пикселей будет 640 пикселей

xScale = imageWidth / spriteWidth
xScale = 640 / 45
xScale = 14.2222222222
xPercent = xScale * 100
xPercent = 1422.22222222%

Затем вам нужно установить смещение. Сложность смещения заключается в том, что 0% выравнивается по левому краю, а 100% - по правому.

введите описание изображения здесь

Будучи графическим программистом, я ожидал бы, что смещение в 100% переместит фон на 100% по всему элементу, другими словами, полностью с правой стороны, но это не то, что означает 100% при использовании с backgrouhnd-position. background-position: 100%;означает выравнивание по правому краю. Таким образом, форум для принятия этого во внимание после масштабирования

xOffsetScale = 1 + 1 / (xScale - 1)              
xOffset = offsetX * offsetScale / imageWidth

Предположим, что смещение составляет 31 пикселей

xOffsetScale = 1 + 1 / (14.222222222 - 1)
xOffsetScale = 1.0756302521021115
xOffset = offsetX * xOffsetScale / imageWidth
xOffset = 31 * 1.0756302521021115 / 640
xOffset = 0.05210084033619603
xOffsetPercent = 5.210084033619603

Вот изображение 640x480 с 2 спрайтами.

  1. в 31x 27y размер 45w 32h
  2. в 500x 370y размер 105w 65h

введите описание изображения здесь

После математики выше для спрайта 1

xScale = imageWidth / spriteWidth
xScale = 640 / 45
xScale = 14.2222222222
xPercent = xScale * 100
xPercent = 1422.22222222%

xOffsetScale = 1 + 1 / (14.222222222 - 1)
xOffsetScale = 1.0756302521021115
xOffset = offsetX * xOffsetScale / imageWidth
xOffset = 31 * 1.0756302521021115 / 640
xOffset = 0.05210084033619603
xOffsetPercent = 5.210084033619603

yScale = imageHeight / spriteHEight
yScale = 480 / 32
yScale = 15
yPercent = yScale * 100
yPercent = 1500%

yOffsetScale = 1 + 1 / (15 - 1)
yOffsetScale = 1.0714285714285714
yOffset = offsetY * yOffsetScale / imageHeight
yOffset = 27 * 1.0714285714285714 / 480
yOffset = 0.06026785714285714
yOffsetPercent = 6.026785714285714

div {
  margin: 3px;
  display: inline-block;
}
.sprite {
  background-image: url('https://i.stack.imgur.com/mv9lJ.png');
}
.s1 {
  background-size:      1422.2222% 1500%;
  background-position:  5.210084033619603% 6.026785714285714%;
}
.s2 {
  background-size:      609.5238095238095% 738.4615384615385%;
  background-position:  93.45794392523367% 89.1566265060241%;
}
<div class="sprite s1" style="width: 45px; height:20px"></div>
<div class="sprite s1" style="width: 128px; height:30px"></div>
<div class="sprite s1" style="width: 64px; height:56px"></div>
<div class="sprite s1" style="width: 57px; height:60px"></div>
<div class="sprite s1" style="width: 45px; height:45px"></div>
<div class="sprite s1" style="width: 12px; height:50px"></div>
<div class="sprite s1" style="width: 50px; height:40px"></div>
<hr/>
<div class="sprite s2" style="width: 45px; height:20px"></div>
<div class="sprite s2" style="width: 128px; height:30px"></div>
<div class="sprite s2" style="width: 64px; height:56px"></div>
<div class="sprite s2" style="width: 57px; height:60px"></div>
<div class="sprite s2" style="width: 45px; height:45px"></div>
<div class="sprite s2" style="width: 12px; height:50px"></div>
<div class="sprite s2" style="width: 50px; height:40px"></div>


Как вы рассчитали значения для offsetX и offsetY?
TryHarder

5

Старый пост, но вот что я сделал, используя background-size:cover;(подсказка @Ceylan Pamir) ...

ПРИМЕР ИСПОЛЬЗОВАНИЯ
Горизонтальный круговой флиппер (наведите курсор на изображение на лицевой стороне, переворачивает назад с другим изображением).

ПРИМЕР СПРАЙТ
480px x 240px

ПРИМЕР ФИНАЛЬНЫЙ РАЗМЕР
Одиночное изображение @ 120px x 120px

ОБЩИЙ КОД
.front {width:120px; height:120px; background:url(http://www.example.com/images/image_240x240.png); background-size:cover; background-repeat:no-repeat; background-position:0px 0px;}

.back {width:120px; height:120px; background:url(http://www.example.com/images/image_240x240.png); background-size:cover; background-repeat:no-repeat; background-position:-120px 0px;}

СОКРАЩЕННАЯ ДЕЛО FIDDLE
http://jsfiddle.net/zuhloobie/133esq63/2/


4

попробуйте использовать размер фона: http://webdesign.about.com/od/styleproperties/p/blspbgsize.htm

Что-то мешает вам рендерить изображения в нужном вам размере?


Могу ли я использовать JavaScript и CSS в сочетании, чтобы решить эту проблему? Я попробовал размер фона; свойство. Я не могу заставить это работать. По какой-то причине изображение не масштабируется.
Майкл

1
background-sizeэто CSS 3 и еще не поддерживается широко.
Янмезен

4
Это поддерживается большинством версий браузера сейчас. Проверьте это caniuse.com/#search=background-size
kiranvj

4

Мне потребовалось время, чтобы найти решение этой проблемы, которой я был доволен:

Проблема:

  • SVG спрайт иконок - скажем, 80px x 3200px

  • Мы хотим масштабировать каждое их использование в селекторах контента (: before /: after) в разных местах по разным размерам без переопределения ко-ордов каждого спрайта в зависимости от используемого размера.

Таким образом, это решение позволяет вам использовать те же спрайты в <button>качестве<menuitem> то же время масштабируя его.

[data-command]::before {
    content: '';
    position: absolute;
    background-image: url("images/sprite.svgz");
    background-repeat: no-repeat;
    background-size: cover;
}

button[data-command]::before {
  width: 32px;
  height: 32px;
}

menuitem[data-command]::before {
  width: 24px;
  height: 24px;
}

[data-command="cancel"]::before {
  background-position: 0% 35%;
}

[data-command="logoff"]::before {
  background-position: 0% 37.5%;
}

Используя проценты (до 2 десятичных разрядов) в background-position, а не background-size, как предлагают другие здесь, вы можете масштабировать одно и то же объявление значка до любого размера, без необходимости повторно его объявлять.

Процент позиции-y - это исходная высота спрайта / высота иконки в виде% - в нашем случае здесь 80px * 100 / 3200px == каждый спрайт представлен y-позицией 2,5%.

Если у вас есть состояния наведения / наведения мыши, вы можете удвоить ширину спрайта и указать координату position-x.

Недостаток этого подхода состоит в том, что добавление большего количества значков на более позднем этапе изменит высоту спрайта и, следовательно, y-position%, но если вы этого не сделаете, ваши координаты спрайта будут нуждаться в изменении для каждого требуемого масштабированного разрешения.


2

Ну, я думаю, что нашел более простое решение для масштабирования изображений: пример - допустим, есть изображение с 3 одинаковыми по размеру спрайтами, которые вы хотели бы использовать, используйте CSS для масштабирования изображения

background-size : 300% 100%;

а затем укажите настраиваемую высоту и ширину, которые необходимо применить к вашему HTML-элементу, например:

 width :45%;
 height:100px;

Пример кода будет выглядеть примерно так:

.customclass {
    background: url("/sample/whatever.png") 0 0 no-repeat ;
    background-size : 300% 100%;
    width :45%;
    height:100px;
}

я довольно новичок в css, и стилизация - это не моя лучшая область, это может быть неправильный способ сделать это ... но он работал для меня в Firefox / Chrome / Explorer 10, надеюсь, он работает и в более старых версиях ..


2

Используйте transform: scale(...);и добавьте соответствие, margin: -...pxчтобы компенсировать свободное пространство от масштабирования. (вы можете использовать, * {outline: 1px solid}чтобы увидеть границы элементов).


2

2018 здесь. Используйте background-size с процентом.

ПРОСТЫНЬ:

Это предполагает один ряд спрайтов. Ширина вашего листа должна быть числом, которое делится на 100 + ширину одного спрайта . Если у вас есть 30 спрайтов размером 108x108 пикселей, добавьте дополнительное пустое пространство в конец, чтобы получить окончательную ширину 5508 пикселей (50 * 108 + 108).

CSS:

.icon{
    height: 30px;  /* Set this to anything. It will scale. */
    width: 30px; /* Match height. This assumes square sprites. */
    background:url(<mysheeturl>);
    background-size: 5100% 100%; /*  5100% because 51 sprites. */
}

/* Each image increases by 2% because we used 50+1 sprites. 
   If we had used 20+1 sprites then % increase would be 5%. */

.first_image{
    background-position: 0% 0;
}

.ninth_image{
    background-position: 16% 0; /* (9-1) x 2 = 16 */
}

HTML:

<div class ="icon first_image"></div>
<div class ="icon ninth_image"></div>


0

Установите ширину и высоту для элемента-обертки изображения спрайта. Используйте эту CSS.

{
    background-size: cover;
}

1
Я не понимаю, почему за это проголосовали. Работал на меня. Выложу мой метод в ответ.
Крис

Я согласен с Крисом здесь. Это решает проблему и в моем случае. Не уверен, почему это понизили!
ShellZero

3
Он не работает со спрайтом (посмотрите на заголовок вопроса), поэтому это решение было отклонено.
Димко Десу

-8

Легко ... Использование двух копий одного и того же изображения с разным масштабом на листе спрайта. Установите координаты и размер в логике приложения.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.