133 votes

Mettre l'image à l'échelle pour qu'elle s'adapte à une boîte de délimitation

Existe-t-il une solution uniquement en css pour mettre une image à l'échelle dans une boîte de délimitation (en conservant le rapport d'aspect) ? Cela fonctionne si l'image est plus grande que le conteneur :

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

Exemple :

Mais je veux mettre l'image à l'échelle jusqu'à ce qu'une dimension soit égale à 100 % du conteneur.

0 votes

Vous voulez dire par exemple height : 100% et width : 100% ? Avez-vous une dimension souhaitée que vous voulez atteindre ? Sinon, vous pouvez aussi étirer l'image et la forcer à atteindre ces dimensions.

0 votes

@mikevoermans Regardez mes deux premiers exemples : Je veux étirer l'image jusqu'à ce que l'une des dimensions soit de 100% et l'autre de <=100%.

0 votes

@jacktheripper En conservant l'aspect-ratio bien sûr...

185voto

Thomas Guillory Points 2701

Grâce à CSS3, il existe une solution !

La solution est de mettre l'image comme background-image et ensuite définir le background-size à contain .

HTML

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

CSS

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

Testez-le ici : http://www.w3schools.com/cssref/playit.asp?filename=playcss_background-size&preval=contain

Compatibilité totale avec les derniers navigateurs : http://caniuse.com/background-img-opts

Pour aligner le div au centre, vous pouvez utiliser cette variante :

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

1 votes

Bien joué, même si ma réponse n'est pas incorrecte (vous demandiez spécifiquement l'img), c'est une excellente solution et j'aurais dû y penser. Le seul problème est qu'IE 8 est encore si largement utilisé que je ne voudrais pas m'y fier pour l'instant, mais c'est quand même une bonne idée.

0 votes

Oui, vous avez raison, votre réponse n'est pas incorrecte : je vais la marquer comme acceptée et intégrer cette solution spécifique dans la question pour ceux qui googlent cela.

6 votes

Définissez-le sur "cover" si vous ne voulez pas de letterboxing : background-size : contain ;

107voto

Stephan Muller Points 8432

Note : Même si c'est la réponse acceptée, la réponse ci-dessous est plus précis et est actuellement pris en charge par tous les navigateurs si vous avez la possibilité d'utiliser une image de fond.

Edit 2 : Dans l'ère moderne, utiliser object-fit pourrait être une solution encore meilleure : https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit

Non, il n'existe pas de méthode CSS permettant de faire cela dans les deux sens. Vous pourriez ajouter

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

Pour qu'un élément ait toujours une largeur de 100 % et que sa hauteur soit automatiquement adaptée au rapport d'aspect, ou l'inverse :

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

pour que la hauteur maximale et la largeur relative soient toujours respectées. Pour faire les deux, vous devez déterminer si le rapport hauteur/largeur est supérieur ou inférieur à celui de son conteneur, ce que les CSS ne peuvent pas faire.

La raison en est que CSS ne sait pas à quoi ressemble la page. Il définit des règles au préalable, mais ce n'est qu'ensuite que les éléments sont rendus et que vous savez exactement à quelles tailles et à quels rapports vous avez affaire. Le seul moyen de détecter cela est le JavaScript.


Bien que vous ne recherchiez pas une solution JS, je vais quand même en ajouter une si quelqu'un en a besoin. La façon la plus simple de gérer cela avec JavaScript est d'ajouter une classe basée sur la différence de ratio. Si le rapport largeur/hauteur du cadre est supérieur à celui de l'image, ajoutez la classe "fillwidth", sinon ajoutez la classe "fillheight".

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

.fillwidth { 
  width: 100%; 
  height: auto; 
}
.fillheight { 
  height: 100%; 
  width: auto; 
}

div {
  border: 1px solid black;
  overflow: hidden;
}

.tower {
  width: 100px;
  height: 200px;
}

.trailer {
  width: 200px;
  height: 100px;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="tower">
  <img src="http://placekitten.com/150/150" />
</div>
<div class="trailer">
  <img src="http://placekitten.com/150/150" />
</div>

8 votes

En fait, il existe une solution : définir la taille d'arrière-plan CSS3 sur contain. Voir ma réponse.

0 votes

Tu as tout à fait raison. Même si c'est un an et demi plus tard maintenant, j'ai édité mon message.

4 votes

Je dirais que c'est la bonne réponse à la question posée, à savoir quelle est la CSS pour la balise img. Cette question est pertinente car, sémantiquement, la balise img est un contenu, alors que l'image en arrière-plan d'un div ne l'est pas. Si certaines circonstances rendent cette solution peu pratique (si vous ne connaissez pas le rapport entre l'image et le conteneur), pour d'autres, elle est tout à fait appropriée. Merci.

41voto

CyberShadow Points 13244

Voici une solution que j'ai découverte :

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

Cela décuplera l'image, mais la limitera à 10 % de sa taille finale, ce qui la confinera au conteneur.

Contrairement à la background-image cette solution fonctionnera également avec <video> éléments.

Exemple interactif :

 function step(timestamp) {
     var container = document.getElementById('container');
     timestamp /= 1000;
     container.style.left   = (200 + 100 * Math.sin(timestamp * 1.0)) + 'px';
     container.style.top    = (200 + 100 * Math.sin(timestamp * 1.1)) + 'px';
     container.style.width  = (500 + 500 * Math.sin(timestamp * 1.2)) + 'px';
     container.style.height = (500 + 500 * Math.sin(timestamp * 1.3)) + 'px';
     window.requestAnimationFrame(step);
 }

 window.requestAnimationFrame(step);

 #container {
     outline: 1px solid black;
     position: relative;
     background-color: red;
 }
 #image {
     display: block;
     max-width: 10%;
     max-height: 10%;
     transform-origin: 0 0;
     transform: scale(10);
 }

<div id="container">
    <img id="image" src="https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png">
</div>

1 votes

J'adore cette solution. Non seulement elle répond réellement à la question (je sais, quelle idée), mais elle fonctionne parfaitement dans tous les navigateurs modernes sans devoir recourir à Javascript !

2 votes

J'adorerais voir un violon de ça. Dans mon test de placement d'une image dans un conteneur 400x400, l'image est simplement coupée dans le coin.

3 votes

Belle réponse ! @Yashua Vous devez ajouter transform-origin: top left pour arrêter le recadrage. /Zombie

0voto

ericosg Points 2158

Cherchez-vous à vous développer vers le haut mais pas vers le bas ?

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

Cependant, cela ne verrouille pas le rapport d'aspect.

5 votes

Essayez d'être un peu plus clair dans vos attentes avant de déclasser la réponse de quelqu'un. Surtout lorsqu'il a répondu à votre question avant que vous ne l'ayez clarifiée par des modifications.

2 votes

Essayez aussi d'être plus poli. Personne ne va vous aider si vous parlez de cette façon.

0 votes

@Artimuz Mes excuses si je vous ai mal guidé, mais il ne me semblait pas clair que vous souhaitiez conserver l'aspect-ratio, c'est pourquoi j'ai fait un commentaire spécifique à ce sujet. Vous remarquerez également que j'ai collé un extrait de votre code dans les exemples. Je pense que conserver height : auto ; fera l'affaire si vous spécifiez une largeur.

0voto

Antti Points 81

J'ai utilisé un tableau pour centrer l'image à l'intérieur de la boîte. Il conserve le rapport d'aspect et met à l'échelle l'image de manière à ce qu'elle soit totalement à l'intérieur de la boîte. Si l'image est plus petite que la boîte, elle est affichée comme elle est au centre. Le code ci-dessous utilise un cadre de 40px de largeur et 40px de hauteur. (Je ne suis pas sûr qu'il fonctionne bien car je l'ai retiré d'un autre code plus complexe et l'ai un peu simplifié).

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

<table class="SmallThumbnailContainer" cellpadding="0" cellspacing="0">
  <tr>
    <td>
      <img src="https://www.gravatar.com/avatar/bf7d39f4ed9c289feca7de38a0093250?s=32&d=identicon&r=PG" width="32" height="32" alt="OP's SO avatar image used as a sample jpg because it is hosted on SO, thus always available" />
    </td>
  </tr>
</table>

Remarque : la taille native de la vignette dans cet extrait est de 32px x 32px, ce qui est inférieur à son conteneur de 40px x 40px. Si le conteneur est plus petit que la vignette dans n'importe quelle dimension, par exemple 40px x 20px, l'image circule à l'extérieur du conteneur dans les dimensions qui sont plus petites que la dimension de l'image correspondante. Le conteneur est marqué par une bordure grise de 1px.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X