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


157

У цій статті, http://css-tricks.com/css-sprites/ , мова йде про те, як я можу вирізати менший образ із 1 більшого зображення. Скажіть, будь ласка, чи можливо це / як я можу вирізати менший розмір зображення, а потім масштабувати обрізаний регіон, перш ніж викласти його?

Ось приклад із цієї статті:

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/

Тож я хотів би знати, чи можу я зробити значки поруч із пунктом 1,2,2,4 меншими?


Як запитав Стівен, чи щось перешкоджає вам відтворювати зображення в потрібному розмірі?
Пол Д. Уейт

4
Я опинився на цій сторінці, оскільки шукав відповідь на те саме. У сучасному світі з відображенням сітківки високої чіткості прийнято будувати зображення вдвічі більше, ніж потрібно, а потім використовувати значення висоти / ширини в атрибутах <img> або CSS, щоб зменшити його до половини висоти / ширини під час відображення. Це забезпечує чітке відображення на смартфонах та планшетах. Але спрайти PNG чудово підходять для кешування та швидкого відображення. Найкраще було б не використовувати спрайт з зображеннями в 2 рази, а потім масштабувати його до розміру, завдяки якому він також виглядає чітким.
Art Geigel

Оскільки на оригінальне запитання так і не було прийнято відповіді, і існує досить акуратне та зворотне сумісне рішення, я створив нову версію Codepen Stretchy , оскільки оригінальний веб-сайт більше не в мережі, і там є ще деякі люди, які потребують відсталого сумісне рішення. Я зробив ручку з атрибуцією оригінального твору / автора.
Усі біти рівні

Відповіді:


131

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

background-size : 150% 150%;

Або

Ви можете використовувати комбінацію масштабування для веб-програми / тобто і трансформації: масштаб для 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

Використання (приклад) фонового розміру: 15%; працює ідеально для спрайтів, зберігаючи правильне співвідношення сторін. Це просте рішення для використання з точками розриву на чуйних сайтах.
C13L0

1
властивість фонового розміру не працювала для мого спрайгу svg з фіксованою висотою та шириною, проте масштаб зробив трюк.
Андре

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

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

29

Під час використання спрайтів ви обмежуєтесь розмірами зображення в спрайті. background-sizeВластивість CSS, згаданий Стівен, що не дуже широко підтримується і може викликати проблеми з браузерами , як 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) обрізає з imgтегу зображення 20x20px , яке діє як масштабоване background-image.


2
Як і Клетус і Квентін, тут це може бути не найкращим підходом. Для мене це угодник - мені потрібно призначити srccss.
Джок

-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
чи повинен спейсер бути зображенням чи може бути використаний простий дів?
isapir

4
Ось приклад CodePen цього. Здається, він працює лише для горизонтальних або вертикальних спрайтів. Не сітки.
Wernight

Я створив нову версію 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>


Привіт, це не відповідає на запитання. Ви повинні показати три диви з різними масштабами одного зображення. У кількох словах він повинен показувати різні розміри «шрифту». Ви можете це виправити?
Роберт

привіт @ Роберт. Як щодо тепер?
Томаш Муларчик

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-size100% кількість спрайтів і 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 для кожного спрайту відсоток таким чином, щоб ширина цього спрайта становила 100%

Іншими словами, якщо зображення шириною 640 пікселів, а спрайт всередині цього зображення - шириною 45 пікселів, то щоб отримати 4540 пікселів на 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;}

СКОРОЧЕНИЙ ПІДТРИМУВАННЯ СПРАВИ
http://jsfiddle.net/zuhloobie/133esq63/2/


4

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

чи щось перешкоджає вам відтворювати зображення в потрібному розмірі в першу чергу?


Чи можна використовувати JavaScript та CSS у поєднанні для вирішення цього питання? Я спробував фоновий розмір; майно. Я не можу змусити його працювати. Він чомусь не масштабує зображення.
Майкл

1
background-sizeє CSS 3 та ще не широко підтримується.
janmoesen

4
Зараз його підтримує більшість версій браузера. Перевірте caniuse.com/#search=background-size
kiranvj

4

Щоб вирішити цю проблему, я був задоволений: мені знадобився певний час:

Проблема:

  • Спрайт SVG з іконок - скажімо, 80px x 3200px

  • Ми хочемо масштабувати кожне їх використання у селекторах вмісту (: до /: після) у різних місцях за різними розмірами без повторного визначення порядок кожного спрайту виходячи з використовуваного розміру.

Таким чином, це рішення дозволяє використовувати ті самі спірити спрайту в а, <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%;
}

Використовуючи відсотки (до двох знаків після коми) у фоновому положенні, а не розмірі фону, як запропоновано іншими тут, ви можете масштабувати те саме оголошення значка до будь-якого розміру, не потребуючи його повторного декларування.

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

Якщо у вас є стан наведення курсора / миші, ви можете подвоїти ширину спрайта і вказати в координаті позиція-x.

Недоліком такого підходу є те, що додавання більшої кількості піктограм згодом змінить висоту спрайта і так y-позицію%, але якщо цього не зробити, то ваші координати спрайтів потребують змін для кожного масштабованого дозволу, яке вам потрібно.


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 рік тут. Використовуйте розмір фону з відсотком.

ЛИСТ:

Це передбачає один ряд спрайтів. Ширина аркуша повинна бути числом, яке рівномірно ділиться на 100 + шириною одного спрайта . Якщо у вас є 30 спрайтів розміром 108x108 px, то додайте до кінця зайвий пробіл, щоб зробити остаточну ширину 5508px (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
Я не розумію, чому це голосування. Працювали для мене. Опублікував мій метод як відповідь.
chris

Я згоден з Крисом тут. Це вирішує проблему і в моєму випадку. Не впевнений, чому це знищено!
ShellZero

3
Він не працює з спрайтом (дивіться назву питання), тому це рішення не використовується.
Дімко Десу

-8

Легко ... Використовуючи дві копії одного зображення з різною шкалою на аркуші спрайта. Встановіть Коорди та розмір за логікою програми.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.