Como posso dimensionar uma imagem em um sprite CSS


157

Neste artigo, http://css-tricks.com/css-sprites/ , ele fala sobre como cortar uma imagem menor de uma imagem maior. Você pode me dizer se é possível / como posso cortar uma imagem menor e depois escalar a região cortada antes de colocá-la em destaque?

Aqui está um exemplo desse artigo:

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

Gostaria de saber como posso dimensionar essa imagem depois de cortá-la do spriteme1.png

Aqui está o URL do exemplo: http://css-tricks.com/examples/CSS-Sprites/Example1After/

Então, eu gostaria de saber se posso diminuir os ícones ao lado do Item1,2,3,4?


Como Stephen perguntou, há algo que o impede de renderizar as imagens no tamanho que você deseja em primeiro lugar?
Paul D. Waite

4
Acabei nesta página porque estava procurando uma resposta para a mesma coisa. No mundo de hoje, com telas de retina de alta definição, é habitual criar uma imagem com o dobro do tamanho necessário e, em seguida, usar valores de altura / largura em atributos <img> ou estilos CSS para reduzi-la à metade da altura / largura ao exibir. Isso garante uma exibição nítida em smartphones e tablets. Mas os sprites PNG são ótimos para armazenar em cache e renderizar rapidamente. Seria melhor não apenas usar um sprite de imagens 2x, mas também escalá-lo para um tamanho que a tornasse nítida também.
Art Geigel # 19/16

Como a pergunta original nunca recebeu uma resposta aceita e há uma solução bastante elegante e compatível com versões anteriores, criei uma nova versão do Codepen Stretchy , pois o site original não está mais online e talvez ainda exista algumas pessoas por aí que precisam de um retrocesso solução compatível. Eu fiz a caneta com a atribuição do trabalho / autor original.
Todos os bits são iguais a

Respostas:


131

Você pode usar o tamanho do plano de fundo , como suportado pela maioria dos navegadores (mas nem todos http://caniuse.com/#search=background-size )

background-size : 150% 150%;

Ou

Você pode usar uma combinação de zoom para webkit / ie transform: scale para Firefox (-moz-) e Opera (-o-) para desktop e celular entre navegadores

[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
Funciona muito bem no Chrome, funciona bem no FF, IE9 / 10. Produz o efeito desejado para a maior parte.
precisa saber é o seguinte

Usando (exemplo) tamanho do plano de fundo: 15%; funciona perfeito para sprites, mantendo a proporção correta. É uma solução simples para usar com pontos de interrupção em sites responsivos.
C13L0:

1
a propriedade tamanho do plano de fundo não funcionou para o meu sprite svg com altura e largura fixas; no entanto, a escala funcionou.
9555 Andre Andre

Para adicionar suporte ao IE8, use o atributo -ms-zoom como sinônimo de zoom no modo Padrões do IE8. -ms-zoom: 0,7; Consulte o link abaixo para obter mais detalhes: msdn.microsoft.com/en-us/library/ms531189(v=vs.85).aspx
Amr

2
Atualização de 2017: o tamanho do plano de fundo é suportado por todos os principais navegadores, incluindo o IE9 +. caniuse.com/#search=background-size
Nathan Hinchey

29

Ao usar sprites, você fica limitado às dimensões da imagem no sprite. A background-sizepropriedade CSS, mencionada por Stephen, ainda não é amplamente suportada e pode causar problemas em navegadores como o IE8 e abaixo - e, dada a sua participação no mercado, essa não é uma opção viável.

Outra maneira de resolver o problema é usar dois elementos e escalar o sprite usando-o com uma imgtag, assim:

<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>

Dessa forma, o elemento externo ( div.sprite-image) está cortando uma imagem de 20x20px da imgtag, que age como uma escala background-image.


2
Como o cletus e o estatuto de Quentin aqui , essa pode não ser a melhor abordagem. Para mim, é uma quebra de negócio - preciso atribuir srcpor css.
Jook

-1: você não pode misturar elementos de apresentação com conteúdo / dados. <img>só deve ser usado se fizer parte do conteúdo. para fins de design, as imagens de plano de fundo são uma obrigação.
Shahriyar Imanov

A melhor resposta (a) funciona universalmente, (b) é compreensível pelo homem, (c) é breve, ... (z) separa a apresentação do conteúdo.
Bob Stein

18

Experimente: Stretchy Sprites - Redimensionamento / alongamento responsivo em vários navegadores de imagens de sprites CSS

Esse método dimensiona os sprites 'responsivamente' para que a largura / altura se ajuste de acordo com o tamanho da janela do navegador. Ele não usa, background-size pois o suporte a isso em navegadores antigos é inexistente.

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
O link realmente não explica a teoria aqui. Você está usando uma div com estouro: oculto como uma área / janela de corte por cima da utilização de uma versão em escala da imagem do sprite. É por isso que ele não usa uma imagem de plano de fundo. Apenas uma camada acima da outra como uma máscara.
Simon

1
O espaçador deve ser uma imagem ou uma div simples pode ser usada?
Isapir

4
Aqui está um exemplo do CodePen disso. Parece funcionar apenas para sprites horizontais ou verticais. Não grades.
Wernight 20/09/13

Eu criei uma nova versão do Codepen Stretchy , pois o site original não está mais online e talvez ainda existam pessoas por aí que precisam de uma solução compatível com versões anteriores. Eu fiz a caneta com a atribuição do original trabalho / autor
todos os bits Equal

10

transform: scale(); fará com que o elemento original preserve seu tamanho.

Eu achei a melhor opção é usar vw. Está funcionando como um encanto:

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>


Olá, isso não responde à pergunta. Você deve mostrar os três divs com escalas diferentes da mesma imagem. Em poucas palavras, ele deve mostrar tamanhos diferentes da "fonte". Consegues consertar isso?
Robert

oi @Robert. Que tal agora?
Tomasz Mularczyk

PS você notou comportamentos usando a unidade de medida VW?
Robert

Não tenho certeza, que comportamentos você quer dizer?
Tomasz Mularczyk 23/08

Os VW VH estão escalando proporcionalmente com o tamanho da janela de exibição. Eu nunca os usei até agora. É apenas uma curiosidade sobre sua experiência em usá-los. Eles são tão "mágicos" ou existem problemas a serem considerados (comportamentos inesperados) em algumas situações que você pode ter notado? obrigado
Robert

7

Aqui está o que eu fiz para fazer isso. Lembre-se de que não funcionará no IE8 e abaixo.

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

A largura da imagem de fundo será reduzida conforme o pai das #elementescalas. Você também pode fazer o mesmo com sua altura, se converter heightpara uma porcentagem. A única parte complicada é descobrir as porcentagens para background-position.

A primeira porcentagem é a largura da área de destino do sprite quando na largura normal dividida pela largura total do sprite e multiplicada por 100.

A segunda porcentagem é a altura da área de destino do sprite antes de ser escalada, dividida pela altura total do sprite e multiplicada por 100.

A redação dessas duas equações é um pouco superficial, então, deixe-me saber se você precisa de uma explicação melhor.


6

Isso parece funcionar para mim.

Se os sprites estiverem na grade, defina o background-sizenúmero de 100% de sprites e o número de 100% de sprites para baixo. Em seguida, use background-position -<x*100>% -<y*100>%onde x e y são o sprite baseado em zero

Em outras palavras, se você quiser o terceiro sprite da esquerda e da segunda linha, são 2 sobre e 1 para baixo,

background-position: -200% -100%;

Por exemplo, aqui está uma folha de sprite 4x2 sprites

insira a descrição da imagem aqui

E aqui está um exemplo

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>

Se os sprites tiverem tamanhos diferentes, você precisará definir o valor background-sizede cada sprite em um percentual, de modo que a largura desse sprite se torne 100%

Em outras palavras, se a imagem tiver 640px de largura e o sprite dentro dessa imagem tiver 45px de largura, para obter 45px com 640px

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

Então você precisa definir o deslocamento. A complicação do deslocamento é que 0% está alinhado à esquerda e 100% está alinhado à direita.

insira a descrição da imagem aqui

Como programador gráfico, eu esperaria que um deslocamento de 100% movesse o plano de fundo 100% pelo elemento, em outras palavras, totalmente do lado direito, mas não é isso que 100% significa quando usado backgrouhnd-position. background-position: 100%;significa alinhado à direita. Portanto, o fórum para levar isso em consideração após o dimensionamento é

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

Suponha que o deslocamento seja 31px

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

Aqui está uma imagem de 640 x 480 com 2 sprites.

  1. em 31x 27y tamanho 45w 32h
  2. em 500x 370y tamanho 105w 65h

insira a descrição da imagem aqui

Seguindo a matemática acima para sprite 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>


Como você calculou os valores para offsetX e offsetY?
TryHarder 9/10/19

5

Post antigo, mas aqui está o que eu fiz usando background-size:cover;(dica de chapéu para @Ceylan Pamir) ...

EXEMPLO DE USO
Alavanca de círculo horizontal (passe o cursor na imagem da frente, vira para trás com imagem diferente).

EXEMPLO SPRITE
480px x 240px

EXEMPLO TAMANHO FINAL
Imagem única @ 120px x 120px

CÓDIGO GENÉRICO
.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;}

CASO ABREVIADO FIDDLE
http://jsfiddle.net/zuhloobie/133esq63/2/


4

tente usar o tamanho do plano de fundo: http://webdesign.about.com/od/styleproperties/p/blspbgsize.htm

existe algo que o impede de renderizar as imagens no tamanho que você deseja em primeiro lugar?


Posso usar JavaScript e CSS em conjunto para resolver isso? Eu tentei o tamanho do plano de fundo; propriedade. Não consigo fazer funcionar. Não dimensiona a imagem por algum motivo.
22610 Michael

1
background-sizeé CSS 3 e ainda não é amplamente suportado.
janmoesen

4
É suportado pela maioria das versões do navegador agora. Marque esta caniuse.com/#search=background-size
kiranvj

4

Demorei um pouco para criar uma solução para esse problema que me agradou:

Problema:

  • Um sprite de ícones SVG - digamos 80px x 3200px

  • Queremos escalar cada uso deles em seletores de conteúdo (: antes /: depois) em vários lugares, em vários tamanhos, sem redefinir as coordenadas de cada sprite com base no tamanho usado.

Portanto, esta solução permite que você use os mesmos Sprite co-ords em um <button>como um <menuitem>enquanto ainda dimensioná-lo.

[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%;
}

Usando porcentagens (com 2 casas decimais) na posição do plano de fundo em vez do tamanho do plano de fundo, conforme sugerido por outras pessoas aqui, você pode dimensionar a mesma declaração de ícone para qualquer tamanho, sem precisar redeclará-la.

A porcentagem da posição y é a altura original do sprite / altura do ícone como% - no nosso caso aqui 80px * 100 / 3200px == cada sprite é representado por uma posição y de 2,5%.

Se você tiver estados de pairar / passar o mouse, poderá dobrar a largura do sprite e especificar na coordenada posição x.

A desvantagem dessa abordagem é que a adição de mais ícones em uma data posterior alterará a altura do sprite e, portanto, a posição y, mas se você não fizer isso, suas coordenadas do sprite precisarão de alterações para cada resolução em escala necessária.


2

Bem, acho que encontrei uma solução mais simples para dimensionar imagens: exemplo - digamos que exista uma imagem com três sprites de tamanho igual que você queira usar, use CSS para dimensionar a imagem

background-size : 300% 100%;

e especifique a altura e a largura personalizadas que precisam ser aplicadas ao seu elemento html, por exemplo:

 width :45%;
 height:100px;

Um código de exemplo ficaria assim:

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

sou bastante novo em css, e o estilo não é minha melhor área, isso pode ser uma maneira errada de fazê-lo .. mas funcionou para mim no Firefox / Chrome / Explorer 10, espero que funcione em versões mais antigas ..


2

Use transform: scale(...);e adicione correspondência margin: -...pxpara compensar o espaço livre da escala. (você pode usar * {outline: 1px solid}para ver os limites do elemento).


2

2018 aqui.Use o tamanho do plano de fundo com porcentagem.

FOLHA:

Isso pressupõe uma única linha de sprites. A largura da sua planilha deve ser um número que é divisível igualmente por 100 + largura de um sprite . Se você tiver 30 sprites de 108 x 108 px, adicione espaço em branco extra ao final para criar a largura final de 5508 px (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

Defina a largura e a altura para o elemento de invólucro da imagem do sprite. Use este css.

{
    background-size: cover;
}

1
Não entendo por que isso é rejeitado. Trabalhou para mim. Vou postar meu método como resposta.
Chris #

Eu concordo com o Chris aqui. Isso resolve o problema também no meu caso. Não tenho certeza por que é votado!
ShellZero 12/09

3
Ele não funciona com o sprite (veja o título da pergunta), é por isso que esta solução foi rebaixada.
Dimko Desu

-8

Fácil ... Usando duas cópias da mesma imagem em diferentes escalas na folha do sprite. Defina as cordas e o tamanho na lógica do aplicativo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.