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.