Scala l'immagine per adattarla a un riquadro di delimitazione


117

Esiste una soluzione solo CSS per ridimensionare un'immagine in un riquadro di delimitazione (mantenendo le proporzioni)? Funziona se l'immagine è più grande del contenitore:

img {
  max-width: 100%;
  max-height: 100%;
}

Esempio:

Ma voglio aumentare l'immagine fino a quando una dimensione è il 100% del contenitore.


Intendi altezza: 100% e larghezza: 100%? hai una dimensione desiderata che vuoi raggiungere? altrimenti potresti anche allungare l'immagine e costringerla a raggiungere anche quelle dimensioni.
mikevoermans

@mikevoermans Guarda i miei due primi esempi: Voglio allungare l'immagine fino a quando una delle dimensioni è al 100% e l'altra è <= 100%
Thomas Guillory

@jacktheripper Conservando le proporzioni ovviamente ...
Thomas Guillory

@gryzzly Gli esempi parlano da soli! Se avevano guardato agli esempi, era ovvio.
Thomas Guillory

@Artimuz Sono completamente in disaccordo. Tre delle risposte alle tue domande (compresa la mia) suggeriscono che NON era ovvio.
Khan

Risposte:


94

Nota: anche se questa è la risposta accettata, la risposta di seguito è più accurata ed è attualmente supportata in tutti i browser se hai la possibilità di utilizzare un'immagine di sfondo.

No, non esiste un unico modo CSS per farlo in entrambe le direzioni. Potresti aggiungere

.fillwidth {
    min-width: 100%;
    height: auto;
}

All'elemento an per avere sempre una larghezza del 100% e ridimensionare automaticamente l'altezza in base alle proporzioni, o al contrario:

.fillheight {
    min-height: 100%; 
    width: auto;
}

per scalare sempre all'altezza massima e alla larghezza relativa. Per fare entrambe le cose, dovrai determinare se le proporzioni sono superiori o inferiori al suo contenitore e CSS non può farlo.

Il motivo è che CSS non sa come appare la pagina. Stabilisce le regole in anticipo, ma solo dopo è che gli elementi vengono renderizzati e sai esattamente con quali dimensioni e rapporti hai a che fare. L'unico modo per rilevarlo è con JavaScript.


Anche se non stai cercando una soluzione JS, ne aggiungerò comunque una se qualcuno potrebbe averne bisogno. Il modo più semplice per gestirlo con JavaScript è aggiungere una classe basata sulla differenza di rapporto. Se il rapporto larghezza-altezza del riquadro è maggiore di quello dell'immagine, aggiungi la classe "fillwidth", altrimenti aggiungi la classe "fillheight".


7
In realtà c'è una soluzione: impostare la dimensione dello sfondo CSS3 per contenere. Vedi la mia risposta.
Thomas Guillory

Hai assolutamente ragione. Anche se è passato un anno e mezzo, ho modificato il mio post.
Stephan Muller

4
Suppongo che questa sia la risposta corretta alla domanda posta, che è qual è il CSS per il tag img. Ciò è rilevante perché semanticamente il tag img è contenuto, l'immagine come sfondo di un div non lo è. Mentre alcune circostanze lo rendono poco pratico (se non conosci il rapporto tra immagine e contenitore), per altri è giusto. Grazie.
duncanwilcox

173

Grazie a CSS3 c'è una soluzione!

La soluzione è di mettere l'immagine come background-imagee quindi impostare il background-sizeverso contain.

HTML

<div class='bounding-box'>
</div>

CSS

.bounding-box {
  background-image: url(...);
  background-repeat: no-repeat;
  background-size: contain;
}

Provalo qui: http://www.w3schools.com/cssref/playit.asp?filename=playcss_background-size&preval=contain

Piena compatibilità con i browser più recenti: http://caniuse.com/background-img-opts

Per allineare il div al centro, puoi utilizzare questa variazione:

.bounding-box {
  background-image: url(...);
  background-size: contain;
  position: absolute;
  background-position: center;
  background-repeat: no-repeat;
  height: 100%;
  width: 100%;
}

1
Bella, anche se la mia risposta non è sbagliata (stavi chiedendo dell'IMG in particolare) questa è un'ottima soluzione e avrei dovuto pensarci. L'unico problema è che IE 8 è ancora così ampiamente utilizzato che non vorrei ancora fare affidamento su questo, ma comunque un bel trucco.
Stephan Muller

6
Impostalo su "cover" se non vuoi il letterbox: background-size: contenere;
arxpoetica

3
Va notato che si può iniettare gli URL di immagine con HTML: <div class=image style="background-image: url('/images/foo.jpg');"></div>. Tutti gli altri stili dovrebbero essere applicati con CSS.
Andrey Mikhaylov - lolmaus

14
Direi che questo è un approccio terribile. Modificandolo in un'immagine di sfondo, stai rimuovendo il significato semantico dell'immagine nell'HTML.
animuson

14
@animuson: Mi ha comunque aiutato poiché utilizzo HTML / CSS per i report stampati e non potevo fare un ciarlatano sulla semantica :)
Christian Wattengård

37

Ecco una soluzione hacker che ho scoperto:

#image {
    max-width: 10%;
    max-height: 10%;
    transform: scale(10);
}

Questo ingrandirà l'immagine di dieci volte, ma la restringerà al 10% della sua dimensione finale, legandola così al contenitore.

A differenza della background-imagesoluzione, funzionerà anche con gli <video>elementi.

Esempio interattivo:


1
Amo questa soluzione. Non solo risponde effettivamente alla domanda (lo so, che pensiero), funziona magnificamente in tutti i browser moderni senza dover ricorrere a Javascript!
ndm13

2
Mi piacerebbe vederne un violino. Nel mio test di inserire un img in un contenitore 400x400, l'img viene ritagliato nell'angolo
cyberwombat

3
Bella risposta! @Yashua Devi aggiungere transform-origin: top leftper interrompere il ritaglio. / Zombie
XwipeoutX

Brillante. La mia unica preoccupazione sarebbe una possibile perdita di qualità dell'immagine in un browser mal codificato, ma in teoria dovrebbe funzionare bene!
Codemonkey

Interessante, ma non funziona su Chrome. Risultati in una riga ritagliata dell'immagine.
MattK

23

Oggi dì solo adattamento all'oggetto: contiene. Il supporto è tutto tranne IE: http://caniuse.com/#feat=object-fit


3
IE ha solo una quota di mercato di circa il 16% al momento in cui scrivo questo (09/12/2016 10:56) e continua a diminuire, quindi questa è la risposta migliore per me: D
Zhang

8
Non modificare le risposte di altre persone per correggere cose diverse da errori di battitura o collegamenti interrotti. Non direi qualcosa di infantile come "C'è un polyfill per browser di merda" in una risposta SO, e non apprezzo che la mia risposta sia stata modificata per far sembrare che l'abbia detto. se vuoi usare le tue parole, inseriscile nella tua risposta.
Glenn Maynard

Direi che non è IE il problema, ma Edge. Secondo caniuse object-fitè ancora in fase di sviluppo per questo.
BairDev

Questa dovrebbe essere una delle risposte più votate dal 2017 in poi ... Secondo il link caniuse sopra, il 90% di tutti gli utenti a livello globale ora utilizza un browser che lo supporta
fgblomqvist

Ho appena pubblicato una risposta che funziona con e senza object-fit: stackoverflow.com/a/46456673/474031
gabrielmaldi

8

html:

    <div class="container">
      <img class="flowerImg" src="flower.jpg">
    </div>

css:

.container{
  width: 100px;
  height: 100px;
}


.flowerImg{
  width: 100px;
  height: 100px;
  object-fit: cover;
  /*object-fit: contain;
  object-fit: scale-down;
  object-position: -10% 0;
  object-fit: none;
  object-fit: fill;*/
}

5

Puoi farlo con CSS puro e supporto browser completo, sia per immagini lunghe verticalmente che orizzontalmente allo stesso tempo.

Ecco uno snippet che funziona in Chrome, Firefox e Safari (sia usando object-fit: scale-downche senza usarlo):

figure {
  margin: 0;
}

.container {
  display: table-cell;
  vertical-align: middle;
  width: 80px;
  height: 80px;
  border: 1px solid #aaa;
}

.container_image {
  display: block;
  max-width: 100%;
  max-height: 100%;
  margin-left: auto;
  margin-right: auto;
}

.container2_image2 {
  width: 80px;
  height: 80px;
  object-fit: scale-down;
  border: 1px solid #aaa;
}
Without `object-fit: scale-down`:

<br>
<br>

<figure class="container">
  <img class="container_image" src="https://i.imgur.com/EQgexUd.jpg">
</figure>

<br>

<figure class="container">
  <img class="container_image" src="https://i.imgur.com/ptO8pGi.jpg">
</figure>

<br> Using `object-fit: scale-down`:

<br>
<br>

<figure>
  <img class="container2_image2" src="https://i.imgur.com/EQgexUd.jpg">
</figure>

<br>

<figure>
  <img class="container2_image2" src="https://i.imgur.com/ptO8pGi.jpg">
</figure>


2

Un'altra soluzione senza immagine di sfondo e senza la necessità di un contenitore (anche se le dimensioni massime del riquadro di delimitazione devono essere note):

img{
  max-height: 100px;
  max-width: 100px;
  width: auto;    /* These two are added only for clarity, */
  height: auto;   /* as the default is auto anyway */
}


Se è richiesto l'uso di un contenitore, la larghezza massima e l'altezza massima possono essere impostate al 100%:

img {
    max-height: 100%;
    max-width: 100%;
    width: auto; /* These two are added only for clarity, */
    height: auto; /* as the default is auto anyway */
}

div.container {
    width: 100px;
    height: 100px;
}

Per questo avresti qualcosa come:

<table>
    <tr>
        <td>Lorem</td>
        <td>Ipsum<br />dolor</td>
        <td>
            <div class="container"><img src="image5.png" /></div>
        </td>
    </tr>
</table>

1

Questo esempio per allungare l'immagine proporzionalmente per adattarla all'intera finestra. Aggiungere un'improvvisazione al codice corretto sopra$( window ).resize(function(){});

function stretchImg(){
    $('div').each(function() {
      ($(this).height() > $(this).find('img').height()) 
        ? $(this).find('img').removeClass('fillwidth').addClass('fillheight')
        : '';
      ($(this).width() > $(this).find('img').width()) 
        ? $(this).find('img').removeClass('fillheight').addClass('fillwidth')
        : '';
    });
}
stretchImg();

$( window ).resize(function() {
    strechImg();
});

Ci sono due condizioni if. Il primo continua a controllare se l'altezza dell'immagine è inferiore al div e applica la .fillheightclasse mentre il successivo controlla la larghezza e applica la .fillwidthclasse. In entrambi i casi l'altra classe viene rimossa utilizzando.removeClass()

Ecco il CSS

.fillwidth { 
   width: 100%;
   max-width: none;
   height: auto; 
}
.fillheight { 
   height: 100vh;
   max-width: none;
   width: auto; 
}

Puoi sostituire 100vhcon 100%se vuoi allungare l'immagine con in un div. Questo esempio per allungare l'immagine proporzionalmente per adattarla all'intera finestra.


OP ha chiesto specificamente un approccio solo css.
Colt McCormack

0

Stai cercando di scalare verso l'alto ma non verso il basso?

div {
    border: solid 1px green;
    width: 60px;
    height: 70px;
}

div img {
    width: 100%;
    height: 100%;
    min-height: 500px;
    min-width: 500px;
    outline: solid 1px red;
}

Tuttavia, questo non blocca le proporzioni.


5
Cerca di essere un po 'più chiaro con le tue aspettative prima di votare per difetto la risposta di qualcuno. Soprattutto quando hanno risposto alla tua domanda prima che tu abbia chiarito la tua domanda con le modifiche.
Khan

2
Inoltre, cerca di essere più educato. Nessuno ti aiuterà se parli in quel modo.
Misha Reyzlin

@Artimuz Mi scuso se ti ho guidato per errore, ma non mi è sembrato chiaro che volessi mantenere le proporzioni, motivo per cui ho commentato specificamente. Inoltre, noterai che ho incollato uno snippet del tuo codice dagli esempi. Credo mantenere l'altezza: auto; lo farà per te se specifichi una larghezza.
ericosg

0

Ho usato la tabella per centrare l'immagine all'interno della scatola. Mantiene le proporzioni e ridimensiona l'immagine in un modo che è totalmente all'interno della scatola. Se l'immagine è più piccola del riquadro, viene visualizzata così com'è al centro. Il codice sottostante utilizza una casella di 40 px di larghezza e 40 px di altezza. (Non sono sicuro di quanto bene funzioni perché l'ho rimosso da un altro codice più complesso e l'ho semplificato un po ')

CSS:

.SmallThumbnailContainer
{
    display: inline-block; position: relative;
    float: left;    
    width: 40px;
    height: 40px;
    border: 1px solid #ccc;
    margin: 0px; padding: 0px;
}
.SmallThumbnailContainer { width: 40px; margin: 0px 10px 0px 0px; } 
.SmallThumbnailContainer tr { height: 40px; text-align: center; }
.SmallThumbnailContainer tr td { vertical-align: middle; position: relative; width: 40px;  }
.SmallThumbnailContainer tr td img { overflow: hidden; max-height: 40px; max-width: 40px; vertical-align: middle; margin: -1px -1px 1px -1px; }

HTML:

<table class="SmallThumbnailContainer" cellpadding="0" cellspacing="0">
    <tr><td>
        <img src="thumbnail.jpg" alt="alternative text"/>
    </td></tr>
    </table>

0

Il modo più pulito e semplice per farlo:

Prima un po 'di CSS:

div.image-wrapper {
    height: 230px; /* Suggestive number; pick your own height as desired */
    position: relative;
    overflow: hidden; /* This will do the magic */
    width: 300px; /* Pick an appropriate width as desired, unless you already use a grid, in that case use 100% */
}
img {
    width: 100%;
    position: absolute;
    left: 0;
    top: 0;
    height: auto;
}

L'HTML:

<div class="image-wrapper">
  <img src="yourSource.jpg">
</div>

Questo dovrebbe fare il trucco!


0

Questo mi ha aiutato:

.img-class {
  width: <img width>;
  height: <img height>;
  content: url('/path/to/img.png');
}

Quindi sull'elemento (puoi usare javascript o media query per aggiungere reattività):

<div class='img-class' style='transform: scale(X);'></div>

Spero che questo ti aiuti!


-3
.boundingbox {
    width: 400px;
    height: 500px;
    border: 2px solid #F63;
}
img{
    width:400px;
    max-height: 500px;
    height:auto;
}

Sto modificando la mia risposta per spiegare ulteriormente la mia soluzione poiché ho un voto negativo.

Con gli stili impostati come mostrato sopra in css, ora il seguente div html mostrerà che l'immagine si adatta sempre alla larghezza e regolerà le proporzioni alte in larghezza. Pertanto l'immagine verrà ridimensionata per adattarsi a un riquadro di delimitazione come richiesto nella domanda.

<div class="boundingbox"><img src="image.jpg"/></div>

Questa risposta funziona solo quando la scatola è più alta che larga.
XwipeoutX
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.