¿Cómo puedo escalar una imagen en un sprite CSS?

157

En este artículo, http://css-tricks.com/css-sprites/ , habla sobre cómo puedo recortar una imagen más pequeña de una imagen más grande. ¿Puede decirme si es posible / cómo puedo recortar una imagen más pequeña y luego escalar la región recortada antes de diseñarla?

Aquí hay un ejemplo de ese artículo:

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

Me gustaría saber cómo puedo escalar esa imagen después de recortarla desde spriteme1.png

Aquí está la URL del ejemplo: http://css-tricks.com/examples/CSS-Sprites/Example1After/

Entonces, ¿me gustaría saber si puedo hacer que los íconos al lado de Item1,2,3,4 sean más pequeños?

Miguel
fuente
Como Stephen preguntó, ¿hay algo que le impida renderizar las imágenes en el tamaño que desea en primer lugar?
Paul D. Waite
44
Terminé en esta página porque estaba buscando una respuesta para lo mismo. En el mundo de hoy con pantallas de retina de alta definición, es costumbre construir una imagen dos veces el tamaño que necesita y luego usar valores de alto / ancho en atributos <img> o estilos CSS para reducirlo a la mitad del alto / ancho cuando se muestra. Esto garantiza una visualización nítida en teléfonos inteligentes y tabletas. Pero los sprites PNG son excelentes para almacenar en caché y renderizar rápidamente. Sería mejor no solo usar un sprite de imágenes 2x, sino también escalarlo a un tamaño que también lo haga ver nítido.
Art Geigel
Como la pregunta original nunca recibió una respuesta aceptada y hay una solución bastante ordenada y compatible con versiones anteriores, creé una nueva versión de Codepen Stretchy , ya que el sitio web original ya no está en línea y quizás todavía hay algunas personas que necesitan una versión anterior solución compatible He hecho la Pluma con la atribución de la obra / autor original.
Todos los bits son iguales el

Respuestas:

131

Puede usar background-size , ya que es compatible con la mayoría de los navegadores (pero no todos http://caniuse.com/#search=background-size )

background-size : 150% 150%;

O

Puede usar un combo de zoom para webkit / ie y transform: scale para Firefox (-moz-) y Opera (-o-) para dispositivos de escritorio y dispositivos móviles 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;
}
aWebDeveloper
fuente
3
Funciona muy bien en Chrome, funciona bien en FF, IE9 / 10. Produce el efecto deseado en su mayor parte.
RCNeil
Usando (ejemplo) tamaño de fondo: 15%; funciona perfecto para sprites manteniendo la relación de aspecto correcta. Es una solución simple de usar con puntos de interrupción en sitios receptivos.
C13L0
1
la propiedad de tamaño de fondo no funcionó para mi sprite svg con una altura y ancho fijos, sin embargo, la escala funcionó.
Andre
Para agregar soporte a IE8, use el atributo -ms-zoom como sinónimo de zoom en el modo de estándares IE8. -ms-zoom: 0.7; Consulte el siguiente enlace para obtener más detalles: msdn.microsoft.com/en-us/library/ms531189(v=vs.85).aspx
Amr
2
Actualización de 2017: el tamaño de fondo es compatible con todos los principales navegadores, incluido IE9 +. caniuse.com/#search=background-size
Nathan Hinchey
29

Cuando usa sprites, está limitado a las dimensiones de la imagen en el sprite. La background-sizepropiedad CSS, mencionada por Stephen, aún no es ampliamente compatible y puede causar problemas con los navegadores como IE8 y versiones anteriores, y dada su participación en el mercado, esta no es una opción viable.

Otra forma de resolver el problema es usar dos elementos y escalar el sprite usándolo con una imgetiqueta, como esta:

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

De esta manera, el elemento externo ( div.sprite-image) está recortando una imagen de 20x20px de la imgetiqueta, que actúa como una escala background-image.

Alex Gyoshev
fuente
2
Como cletus y Quentin afirman aquí , este podría no ser el mejor enfoque. Para mí es un factor decisivo: necesito asignar srcpor CSS.
Jook
-1: No puedes mezclar elementos de presentación con contenido / datos. <img>solo debe usarse si es parte del contenido. Para fines de diseño, las imágenes de fondo son imprescindibles.
Shahriyar Imanov
La mejor respuesta (a) funciona universalmente, (b) es comprensible para los humanos, (c) es breve, ... (z) separa la presentación del contenido.
Bob Stein
18

Pruebe esto: Sprites elásticos : cross-browser, cambio de tamaño receptivo / estiramiento de imágenes de sprites CSS

Este método escala los sprites 'de manera receptiva' para que el ancho / alto se ajuste de acuerdo con el tamaño de la ventana de su navegador. No se utiliza, background-size ya que no existe soporte para esto en navegadores antiguos.

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>
tobyj
fuente
3
El enlace realmente no explica la teoría aquí. Está utilizando un div con desbordamiento: oculto como un área / ventana de recorte sobre la parte superior del uso de una versión a escala de la imagen del sprite. Es por eso que no usa una imagen de fondo en absoluto. Solo una capa sobre la otra como máscara.
Simon
1
¿El espaciador debe ser una imagen o se puede usar un simple div en su lugar?
isapir
44
Aquí hay un ejemplo de CodePen de esto. Parece funcionar solo para sprites horizontales o verticales. No rejillas.
Wernight
Hice una nueva versión de Codepen Stretchy , ya que el sitio web original ya no está en línea y puede que todavía haya algunas personas que necesitan una solución compatible con versiones anteriores. Hice el bolígrafo con la atribución de la obra / autor original
All Bits Equal
10

transform: scale(); hará que el elemento original conserve su tamaño.

Encontré que la mejor opción es usar vw. Funciona a las mil maravillas:

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>

Tomasz Mularczyk
fuente
Hola, esto no responde la pregunta. Debes mostrar los tres divs con diferentes escalas de la misma imagen. En pocas palabras, debe mostrar diferentes tamaños de la "fuente". ¿Puedes arreglarlo?
Robert
hola @Robert. ¿Que tal ahora?
Tomasz Mularczyk
PD: ¿has notado comportamientos usando la unidad de medida VW?
Robert
No estoy seguro, ¿qué comportamientos quieres decir?
Tomasz Mularczyk
VW VH están escalando proporcionalmente con el tamaño de la ventana gráfica. Nunca los he usado hasta ahora. Es solo una curiosidad acerca de su experiencia al usarlos. ¿Son tan "mágicos" o hay problemas a considerar (comportamientos inesperados) en algunas situaciones que puede haber notado? gracias
Robert
7

Esto es lo que hice para hacer esto. Tenga en cuenta que no funcionará en IE8 y versiones inferiores.

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

El ancho de la imagen de fondo se reducirá a medida que el padre de la #elementescala se reduzca. También puede hacer lo mismo con su altura, si convierte heighta un porcentaje. Lo único complicado es calcular los porcentajes background-position.

El primer porcentaje es el ancho del área objetivo del sprite cuando está en el ancho normal dividido por el ancho total del sprite, y multiplicado por 100.

El segundo porcentaje es la altura del área objetivo del sprite antes de ser escalado dividido por la altura total del sprite, y multiplicado por 100.

La redacción de esas dos ecuaciones es un poco descuidada, así que avíseme si necesita que se lo explique mejor.


fuente
6

Esto parece funcionar para mí.

Si los sprites están en la cuadrícula, establezca el background-size100% del número de sprites y 100% del número de sprites hacia abajo. Luego usa background-position -<x*100>% -<y*100>%donde x e y son el sprite basado en cero

En otras palabras, si quieres el tercer sprite de la izquierda y la segunda fila, eso es 2 arriba y 1 abajo, así que

background-position: -200% -100%;

Por ejemplo, aquí hay una hoja de sprites 4x2 sprites

ingrese la descripción de la imagen aquí

Y aquí hay un ejemplo

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>

Si los sprites son de diferentes tamaños, deberá establecer el background-sizeporcentaje de cada sprite en un porcentaje tal que el ancho de ese sprite sea del 100%

En otras palabras, si la imagen tiene 640px de ancho y el sprite dentro de esa imagen tiene 45px de ancho, entonces para que ese 45px tenga 640px

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

Entonces necesita establecer el desplazamiento. La complicación del desplazamiento es que el 0% está alineado a la izquierda y el 100% está alineado a la derecha.

ingrese la descripción de la imagen aquí

Como programador de gráficos, esperaría un desplazamiento del 100% para mover el fondo 100% a través del elemento, en otras palabras, completamente fuera del lado derecho, pero eso no es lo que significa 100% cuando se usa backgrouhnd-position. background-position: 100%;significa alineado a la derecha. Entonces, el foro para tomar eso en cuenta después de escalar es

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

Suponga que el desplazamiento es 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

Aquí hay una imagen de 640x480 con 2 sprites.

  1. a 31x 27y tamaño 45w 32h
  2. a 500x 370y tamaño 105w 65h

ingrese la descripción de la imagen aquí

Siguiendo las matemáticas anteriores 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>

gman
fuente
¿Cómo calculó los valores para offsetX y offsetY?
TryHarder
5

background-size:cover;Publicación anterior , pero esto es lo que hice usando (punta de sombrero para @Ceylan Pamir) ...

EJEMPLO DE USO
Volteador de círculo horizontal (desplace el cursor sobre la imagen frontal, voltea hacia atrás con una imagen diferente).

EJEMPLO SPRITE
480px x 240px

EJEMPLO TAMAÑO FINAL
Imagen ú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;}

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

Chris
fuente
4

intente usar el tamaño de fondo: http://webdesign.about.com/od/styleproperties/p/blspbgsize.htm

¿hay algo que te impide renderizar las imágenes en el tamaño que deseas en primer lugar?

stephenmurdoch
fuente
¿Puedo usar JavaScript y CSS en combinación para resolver esto? Probé el tamaño de fondo; propiedad. No puedo hacer que funcione. No escala la imagen por alguna razón.
michael
1
background-sizees CSS 3 y aún no es ampliamente compatible.
Janmoesen
44
Es compatible con la mayoría de las versiones de navegador ahora. Mira esto caniuse.com/#search=background-size
kiranvj
4

Me llevó un tiempo crear una solución a este problema con el que estaba contento:

Problema:

  • Un sprite de iconos SVG: digamos 80 px x 3200 px

  • Queremos escalar cada uso de ellos en selectores de contenido (: before /: after) en varios lugares en varios tamaños sin redefinir los codigos de cada sprite en función del tamaño utilizado.

Por lo que esta solución le permite utilizar los mismos sprites compañeros de ords en una <button>como <menuitem>mientras sigue su reducción.

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

Al usar porcentajes (hasta 2 decimales) en la posición del fondo en lugar del tamaño del fondo como lo sugieren otros aquí, puede escalar la misma declaración de icono a cualquier tamaño, sin necesidad de volver a declararla.

El porcentaje de posición y es la altura original del sprite / altura del icono como%; en nuestro caso, aquí 80px * 100 / 3200px == cada sprite está representado por una posición y del 2.5%.

Si tiene estados de desplazamiento / mouseover, puede duplicar el ancho del sprite y especificarlo en la coordenada posición-x.

La desventaja de este enfoque es que agregar más íconos en una fecha posterior cambiará la altura del sprite y, por lo tanto, la posición y%, pero si no lo hace, entonces sus coordenadas de sprite necesitarán un cambio para cada resolución escalada que necesite.

Neil
fuente
2

Bueno, creo que encontré una solución más simple para escalar imágenes: ejemplo: digamos que hay una imagen con 3 sprites del mismo tamaño que te gustaría usar, usa CSS para escalar la imagen

background-size : 300% 100%;

y luego especifique la altura y el ancho personalizados que deben aplicarse a su elemento html, por ejemplo:

 width :45%;
 height:100px;

Un código de muestra se vería así:

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

soy bastante nuevo en css, y el estilo no es mi mejor área, esta podría ser una forma incorrecta de hacerlo ... pero funcionó para mí en Firefox / Chrome / Explorer 10, espero que también funcione en versiones anteriores ...

Dasith
fuente
2

Use transform: scale(...);y agregue coincidencias margin: -...pxpara compensar el espacio libre de la escala. (puede usar * {outline: 1px solid}para ver los límites de los elementos).

adyry
fuente
2

2018 aquí. Utilice el tamaño de fondo con porcentaje.

SÁBANA:

Esto supone una sola fila de sprites. El ancho de su hoja debe ser un número que sea divisible por 100 + ancho de un sprite . Si tiene 30 sprites que son 108x108 px, agregue espacio en blanco adicional al final para hacer el ancho final 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>
usuario984003
fuente
1

Use transform: scale(0.8);con el valor que necesita en lugar de 0.8

Miguel Ballén
fuente
0

Establezca el ancho y la altura para envolver el elemento de la imagen del sprite. Usa este CSS.

{
    background-size: cover;
}
Ceylan Pamir
fuente
1
No entiendo por qué esto es rechazado. Trabajó para mi. Publicaré mi método como respuesta.
Chris
Estoy de acuerdo con Chris aquí. Esto resuelve el problema en mi caso también. ¡No estoy seguro de por qué es rechazado!
ShellZero
3
No funciona con sprite (mira el título de la pregunta), es por eso que esta solución es rechazada.
Dimko Desu
-8

Fácil ... Usando dos copias de la misma imagen con diferente escala en la hoja del sprite. Establezca los Coords y el tamaño en la lógica de la aplicación.

makubex
fuente