Come posso ridimensionare un'immagine in uno sprite CSS


157

In questo articolo, http://css-tricks.com/css-sprites/ , viene spiegato come posso ritagliare un'immagine più piccola da un'immagine più grande. Puoi dirmi se è possibile / come posso ritagliare un'immagine più piccola e quindi ridimensionare la regione ritagliata prima di disporla?

Ecco un esempio di quell'articolo:

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

Vorrei sapere come posso ridimensionare quell'immagine dopo averla ritagliata da spriteme1.png

Ecco l'URL dell'esempio: http://css-tricks.com/examples/CSS-Sprites/Example1After/

Quindi vorrei sapere se posso ridurre le icone accanto a Item1,2,3,4?


Come ha chiesto Stephen, c'è qualcosa che ti impedisce di rendere le immagini nella dimensione che desideri in primo luogo?
Paul D. Waite,

4
Sono finito su questa pagina poiché stavo cercando una risposta per la stessa cosa. Nel mondo di oggi con display a retina ad alta definizione è consuetudine costruire un'immagine due volte più grande di quanto deve essere e quindi utilizzare i valori di altezza / larghezza negli attributi <img> o stili CSS per ridurla a metà dell'altezza / larghezza durante la visualizzazione. Ciò garantisce una visualizzazione nitida su smartphone e tablet. Ma gli sprite PNG sono perfetti per la memorizzazione nella cache e il rendering rapido. Sarebbe meglio non solo utilizzare uno sprite di immagini 2x, ma per ridimensionarlo a una dimensione che lo faccia sembrare anche nitido.
Art Geigel,

Poiché la domanda originale non ha mai ricevuto una risposta accettata e esiste una soluzione abbastanza ordinata e compatibile con le versioni precedenti, ho realizzato una nuova versione di Codepen Stretchy , poiché il sito Web originale non è più online e forse ci sono ancora alcune persone là fuori che hanno bisogno di una versione arretrata soluzione compatibile. Ho realizzato la penna con attribuzione dell'opera / autore originale.
Tutti i bit sono uguali al

Risposte:


131

È possibile utilizzare la dimensione dello sfondo , poiché supportata dalla maggior parte dei browser (ma non tutti http://caniuse.com/#search=background-size )

background-size : 150% 150%;

O

Puoi usare una combinazione di zoom per webkit / ie e trasformare: ridimensiona per Firefox (-moz-) e Opera (-o-) per desktop e dispositivi mobili su più browser

[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
Funziona alla grande in Chrome, funziona bene in FF, IE9 / 10. Produce l'effetto desiderato per la maggior parte.
RCNeil,

Utilizzando (esempio) le dimensioni dello sfondo: 15%; funziona perfettamente per gli sprite mantenendo le proporzioni corrette. È una soluzione semplice da utilizzare con i punti di interruzione su siti reattivi.
C13L0

1
la proprietà size-background non ha funzionato per il mio svg sprite con altezza e larghezza fisse, tuttavia la scala ha funzionato.
Andre

Per aggiungere supporto a IE8, utilizzare l'attributo -ms-zoom come sinonimo di zoom in modalità Standard IE8. -ms-zoom: 0,7; Per ulteriori dettagli, consultare il collegamento seguente: msdn.microsoft.com/en-us/library/ms531189(v=vs.85).aspx
Amr

2
Aggiornamento 2017: la dimensione dello sfondo è supportata da tutti i principali browser, incluso IE9 +. caniuse.com/#search=background-size
Nathan Hinchey

29

Quando usi gli sprite, sei limitato alle dimensioni dell'immagine nello sprite. La background-sizeproprietà CSS, menzionata da Stephen, non è ancora ampiamente supportata e potrebbe causare problemi con browser come IE8 e inferiori - e data la loro quota di mercato, questa non è un'opzione praticabile.

Un altro modo per risolvere il problema è utilizzare due elementi e ridimensionare lo sprite utilizzandolo con un imgtag, in questo modo:

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

In questo modo, l'elemento esterno ( div.sprite-image) sta ritagliando un'immagine 20x20px dal imgtag, che si comporta come una scala background-image.


2
Come cletus e Quentin statet qui , questo potrebbe non essere l'approccio migliore. Per me è un rompicapo: devo assegnarlo srctramite CSS.
Jook,

-1: non è possibile mescolare elementi di presentazione con contenuto / dati. <img>dovrebbe essere usato solo se fa parte del contenuto. a fini di progettazione, le immagini di sfondo sono un must.
Shahriyar Imanov,

La migliore risposta (a) funziona universalmente, (b) è comprensibile per l'uomo, (c) è breve, ... (z) separa la presentazione dal contenuto.
Bob Stein,

18

Prova questo: Stretchy Sprites - Cross-browser, ridimensionamento / stiramento reattivo delle immagini sprite CSS

Questo metodo ridimensiona gli sprite "in modo reattivo" in modo che la larghezza / altezza si adattino in base alle dimensioni della finestra del browser. Non utilizza background-size come supporto per questo nei browser meno recenti è inesistente.

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
Il link non spiega davvero la teoria qui. Stai utilizzando un div con overflow: nascosto come area / finestra di ritaglio sopra l'utilizzo di una versione ridimensionata dell'immagine sprite. Ecco perché non utilizza affatto un'immagine di sfondo. Solo uno strato sopra l'altro come maschera.
Simon,

1
il distanziatore deve essere un'immagine o può essere utilizzato un semplice div?
Isapir,

4
Ecco un esempio di CodePen . Sembra funzionare solo per sprite orizzontali o verticali. Non griglie.
Wernight,

Ho realizzato una nuova versione di Codepen Stretchy , in quanto il sito Web originale non è più online e, per quanto ci siano ancora persone là fuori che hanno bisogno di una soluzione compatibile con le versioni precedenti. Ho realizzato la penna con attribuzione dell'opera / autore originale
All Bits uguale al

10

transform: scale(); farà in modo che l'elemento originale mantenga le sue dimensioni.

Ho trovato che l'opzione migliore è usare vw. Funziona come un fascino:

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>


Ciao, questo non risponde alla domanda. Dovresti mostrare le tre div con scale diverse della stessa immagine. In poche parole, dovrebbe mostrare dimensioni diverse del "carattere". Puoi aggiustarlo?
Robert,

ciao @Robert. Che ne dici adesso?
Tomasz Mularczyk,

PS hai notato comportamenti che utilizzano l'unità di misura VW?
Robert,

Non sono sicuro, quali comportamenti intendi?
Tomasz Mularczyk,

VW VH si ridimensiona proporzionalmente alla dimensione della finestra. Non li ho mai usati fino ad ora. È solo una curiosità sulla tua esperienza nell'usarli. Sono così "magici" o ci sono problemi da considerare (comportamenti inaspettati) in alcune situazioni che potresti aver notato? grazie
Robert

7

Ecco cosa ho fatto per fare questo. Tieni presente che non funzionerà su IE8 e versioni successive.

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

La larghezza dell'immagine di sfondo si ridimensionerà come padre della #elementscala in basso. Puoi fare lo stesso anche con la sua altezza, se converti heightin percentuale. L'unica cosa difficile è capire le percentuali per background-position.

La prima percentuale è la larghezza dell'area target dello sprite quando a larghezza normale divisa per la larghezza totale dello sprite e moltiplicata per 100.

La seconda percentuale è l'altezza dell'area target dello sprite prima di essere ridimensionata divisa per l'altezza totale dello sprite e moltiplicata per 100.

La formulazione su queste due equazioni è un po 'sciatta, quindi fatemi sapere se avete bisogno di me per spiegarlo meglio.


6

Questo sembra funzionare per me.

Se gli sprite sono nella griglia, imposta il background-sizenumero di sprite al 100% e il numero di sprite al 100% verso il basso. Quindi usa background-position -<x*100>% -<y*100>%dove xey sono gli sprite basati su zero

In altre parole, se vuoi il 3 ° sprite dalla sinistra e la 2a fila che è 2 sopra e 1 giù così

background-position: -200% -100%;

Ad esempio, ecco un foglio sprite 4x2 sprite

inserisci qui la descrizione dell'immagine

Ed ecco un esempio

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 gli sprite sono di dimensioni diverse, dovrai impostare il valore background-sizedi ogni sprite su una percentuale tale che la larghezza dello sprite diventi 100%

In altre parole, se l'immagine ha una larghezza di 640 px e lo sprite all'interno di quell'immagine è largo 45 px, allora per ottenere quel 45 px sia 640 px

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

Quindi è necessario impostare l'offset. La complicazione dell'offset è che lo 0% è allineato a sinistra e il 100% è allineato a destra.

inserisci qui la descrizione dell'immagine

Come programmatore grafico, mi aspetto che un offset del 100% sposti lo sfondo del 100% attraverso l'elemento, in altre parole completamente dalla parte di destra, ma non è ciò che significa al 100% quando utilizzato con backgrouhnd-position. background-position: 100%;significa allineato a destra. Quindi, il forumla per tenerne conto dopo il ridimensionamento è

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

Supponiamo che l'offset sia di 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

Ecco un'immagine 640x480 con 2 sprite.

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

inserisci qui la descrizione dell'immagine

Seguendo la matematica sopra per 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>


Come hai calcolato i valori di offsetX e offsetY?
TryHarder

5

Vecchio post, ma ecco cosa ho fatto usando background-size:cover;(punta del cappello a @Ceylan Pamir) ...

ESEMPIO UTILIZZO
Aletta a cerchio orizzontale (passa con il mouse sull'immagine del lato anteriore, capovolge all'indietro con un'immagine diversa).

ESEMPIO SPRITE
480px x 240px

ESEMPIO DIMENSIONE FINALE
Immagine singola @ 120px x 120px

CODICE GENERICO
.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;}

ABBREVIATED CASE FIDDLE
http://jsfiddle.net/zuhloobie/133esq63/2/


4

prova a utilizzare la dimensione dello sfondo: http://webdesign.about.com/od/styleproperties/p/blspbgsize.htm

c'è qualcosa che ti impedisce di rendere le immagini con le dimensioni che desideri in primo luogo?


Posso usare JavaScript e CSS in combinazione per risolvere questo problema? Ho provato le dimensioni dello sfondo; proprietà. Non riesco a farlo funzionare. Non ridimensiona l'immagine per qualche motivo.
michael

1
background-sizeè CSS 3 e non è ancora ampiamente supportato.
Janmoesen,

4
Ora è supportato dalla maggior parte delle versioni del browser. Controlla questo caniuse.com/#search=background-size
kiranvj

4

Mi ci è voluto un po 'di tempo per creare una soluzione a questo problema di cui ero felice:

Problema:

  • Uno sprite SVG di icone - diciamo 80px x 3200px

  • Vogliamo ridimensionare ogni loro utilizzo nei selettori di contenuto (: before /: after) in vari punti su varie dimensioni senza ridefinire le coordinate di ogni sprite in base alla dimensione utilizzata.

Quindi questa soluzione ti consente di usare le stesse coordinate dello sprite in <button>un <menuitem>mentre ancora ridimensionandolo.

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

Utilizzando le percentuali (fino a 2 decimali) in posizione di sfondo anziché in dimensioni di sfondo come suggerito da altri qui, è possibile ridimensionare la stessa dichiarazione icona a qualsiasi dimensione, senza bisogno di ridistribuirla.

La percentuale posizione-y è l'altezza dello sprite originale / altezza dell'icona in% - nel nostro caso qui 80px * 100 / 3200px == ogni sprite è rappresentato da una posizione y del 2,5%.

Se hai gli stati di passaggio del mouse / passaggio del mouse puoi raddoppiare la larghezza dello sprite e specificare nella coordinata posizione-x.

Lo svantaggio di questo approccio è che l'aggiunta di più icone in un secondo momento cambierà l'altezza dello sprite e quindi la posizione y%, ma se non lo fai, le tue coordinate di sprite dovranno cambiare per ogni risoluzione in scala richiesta.


2

Beh, penso che abbia trovato una soluzione più semplice per ridimensionare le immagini: esempio: supponiamo che ci sia un'immagine con 3 sprite di uguali dimensioni che vorresti usare, usa CSS per ridimensionare l'immagine

background-size : 300% 100%;

e quindi specifica l'altezza e la larghezza personalizzate che devono essere applicate al tuo elemento HTML, ad esempio:

 width :45%;
 height:100px;

Un codice di esempio sarebbe simile al seguente:

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

Sono abbastanza nuovo per CSS, e lo styling non è la mia area migliore, questo potrebbe essere un modo sbagliato di farlo .. ma ha funzionato per me in Firefox / Chrome / Explorer 10, spero che funzioni anche nelle versioni precedenti ..


2

Utilizzare transform: scale(...);e aggiungere la corrispondenza margin: -...pxper compensare lo spazio libero dal ridimensionamento. (puoi usare * {outline: 1px solid}per vedere i confini degli elementi).


2

2018 qui. Usa le dimensioni dello sfondo con percentuale.

FOGLIO:

Questo presuppone una singola fila di sprite. La larghezza del foglio dovrebbe essere un numero che è uniformemente divisibile per 100 + larghezza di uno sprite . Se hai 30 sprite di 108x108 px, aggiungi uno spazio extra alla fine per rendere la larghezza finale 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

Imposta la larghezza e l'altezza sull'elemento wrapper dell'immagine sprite. Usa questo css.

{
    background-size: cover;
}

1
Non capisco perché questo sia sotto votato. Ha funzionato per me. Invierò il mio metodo come risposta.
chris,

Sono d'accordo con chris qui. Questo risolve il problema anche nel mio caso. Non sono sicuro del perché sia ​​stato sottoposto a downgrade
ShellZero,

3
Non funziona con sprite (guarda il titolo della domanda), ecco perché questa soluzione è sottoposta a downgrade.
Dimko Desu,

-8

Facile ... Usare due copie della stessa immagine con scala diversa sul foglio dello sprite. Imposta le coordinate e le dimensioni sulla logica dell'app.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.