Aligner verticalement une image à l'intérieur d'un div avec une hauteur réactive

135

J'ai le code suivant qui configure un conteneur dont la hauteur change avec la largeur lorsque le navigateur est redimensionné (pour maintenir un rapport hauteur / largeur carré).

HTML

<div class="responsive-container">
    <div class="dummy"></div>
    <div class="img-container">
        <IMG HERE>
    </div>
</div>

CSS

.responsive-container {
    position: relative;
    width: 100%;
    border: 1px solid black;
}

.dummy {
    padding-top: 100%; /* forces 1:1 aspect ratio */
}

.img-container {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

Comment puis-je aligner verticalement l'IMG à l'intérieur du conteneur? Toutes mes images ont des hauteurs variables et le conteneur ne peut pas avoir une hauteur / hauteur de ligne fixe car il est réactif ... S'il vous plaît aider!

user1794295
la source
1
Voici une solution flexbox simple: stackoverflow.com/a/31977476/3597276
Michael Benjamin

Réponses:

381

Voici une technique pour aligner des éléments en ligne à l'intérieur d'un parent , horizontalement et verticalement en même temps:

Alignement vertical

1) Dans cette approche, nous créons un inline-block(pseudo-) élément comme premier (ou dernier) enfant du parent , et définissons sa heightpropriété sur 100%pour prendre toute la hauteur de son parent .

2) De plus, l'ajout vertical-align: middlegarde les éléments en ligne (-block) au milieu de l'interligne. Donc, nous ajoutons cette déclaration CSS au premier enfant et à notre élément (l' image ) à la fois.

3) Enfin, afin de supprimer le caractère d'espace blanc entre les éléments en ligne (-bloc) , nous pourrions définir la taille de la police du parent à zéro par font-size: 0;.

Remarque: j'ai utilisé la technique de remplacement d'image de Nicolas Gallagher dans ce qui suit.

Quels sont les bénéfices?

  • Le conteneur ( parent ) peut avoir des dimensions dynamiques.
  • Il n'est pas nécessaire de spécifier explicitement les dimensions de l'élément d'image.

  • Nous pouvons facilement utiliser cette approche pour aligner un <div>élément verticalement également; qui peut avoir un contenu dynamique (hauteur et / ou largeur). Mais notez que vous devez redéfinir la font-sizepropriété de divpour afficher le texte intérieur. Démo en ligne .

<div class="container">
    <div id="element"> ... </div>
</div>
.container {
    height: 300px;
    text-align: center;  /* align the inline(-block) elements horizontally */
    font: 0/0 a;         /* remove the gap between inline(-block) elements */
}

.container:before {    /* create a full-height inline block pseudo=element */
    content: ' ';
    display: inline-block;
    vertical-align: middle;  /* vertical alignment of the inline element */
    height: 100%;
}

#element {
    display: inline-block;
    vertical-align: middle;  /* vertical alignment of the inline element */
    font: 16px/1 Arial sans-serif;        /* <-- reset the font property */
}

Le résultat

Aligner verticalement un élément dans son conteneur

Conteneur réactif

Cette section ne répondra pas à la question car l'OP sait déjà comment créer un conteneur réactif. Cependant, je vais vous expliquer comment cela fonctionne.

Afin de faire changer la hauteur d'un élément de conteneur avec sa largeur (en respectant les proportions), nous pourrions utiliser une valeur de pourcentage pour la paddingpropriété haut / bas .

Une valeur de pourcentage sur le remplissage ou les marges haut / bas est relative à la largeur du bloc conteneur.

Par exemple:

.responsive-container {
  width: 60%;

  padding-top: 60%;    /* 1:1 Height is the same as the width */
  padding-top: 100%;   /* width:height = 60:100 or 3:5        */
  padding-top: 45%;    /* = 60% * 3/4 , width:height =  4:3   */
  padding-top: 33.75%; /* = 60% * 9/16, width:height = 16:9   */
}

Voici la démo en ligne . Commentez les lignes du bas et redimensionnez le panneau pour voir l'effet.

De plus, nous pourrions appliquer la paddingpropriété à un mannequin enfant ou :before/ :afterpseudo-élément pour obtenir le même résultat. Mais notez que dans ce cas, la valeur en pourcentage sur paddingest relative à la largeur de .responsive-containerlui - même.

<div class="responsive-container">
  <div class="dummy"></div>
</div>
.responsive-container { width: 60%; }

.responsive-container .dummy {
  padding-top: 100%;    /*  1:1 square */
  padding-top: 75%;     /*  w:h =  4:3 */
  padding-top: 56.25%;  /*  w:h = 16:9 */
}

Démo n ° 1 .
Démo # 2 (Utilisation d'un :afterpseudo-élément)

Ajout du contenu

L'utilisation de la padding-toppropriété crée un espace énorme en haut ou en bas du contenu, à l'intérieur du conteneur .

Pour résoudre ce problème, nous avons envelopper le contenu par un élément d'emballage, retirer cet élément du document flux normal en utilisant le positionnement absolu , et enfin développer l'emballage (bu en utilisant top, right, bottomet leftpropriétés) pour remplir tout l'espace de son parent, le conteneur .

Et c'est parti:

.responsive-container {
  width: 60%;
  position: relative;
}

.responsive-container .wrapper {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
}

Voici la démo en ligne .


Se rassembler tous

<div class="responsive-container">
  <div class="dummy"></div>

  <div class="img-container">
    <img src="http://placehold.it/150x150" alt="">
  </div>
</div>
.img-container {
  text-align:center; /* Align center inline elements */
  font: 0/0 a;       /* Hide the characters like spaces */
}

.img-container:before {
  content: ' ';
  display: inline-block;
  vertical-align: middle;
  height: 100%;
}

.img-container img {
  vertical-align: middle;
  display: inline-block;
}

Voici la DEMO DE TRAVAIL .

Évidemment, vous pouvez éviter d'utiliser un ::beforepseudo-élément pour la compatibilité du navigateur et créer un élément en tant que premier enfant de .img-container:

<div class="img-container">
    <div class="centerer"></div>
    <img src="http://placehold.it/150x150" alt="">
</div>
.img-container .centerer {
  display: inline-block;
  vertical-align: middle;
  height: 100%;
}

DÉMO MISE À JOUR .

Utilisation des max-*propriétés

Afin de garder l'image à l'intérieur de la boîte dans une largeur inférieure, vous pouvez définir max-heightet max-widthpropriété sur l'image:

.img-container img {
    vertical-align: middle;
    display: inline-block;
    max-height: 100%;  /* <-- Set maximum height to 100% of its parent */
    max-width: 100%;   /* <-- Set maximum width to 100% of its parent */
}

Voici la DÉMO MISE À JOUR .

Hashem Qolami
la source
1
Salut Hashem, merci beaucoup pour votre réponse - cela a fonctionné comme par magie pour les navigateurs de bureau, même lors du redimensionnement vers des largeurs plus petites. Mais malheureusement, les images apparaissent hors de leur position, sous la division du conteneur, sur mobile (Android v2.3.5). Une idée sur un correctif pour cela?
user1794295
3
@ user1794295 J'ai testé ce violon sur trois appareils Android avec Android v2.3 (Galaxy S II, Galaxy Note, Motorola Droid 4) via browsererstack.com, tout fonctionne comme prévu.Vous pouvez trouver le résultat ici: browsererstack.com/screenshots /… . Veuillez fournir une capture d'écran ou un test spécifique de votre problème. J'aiderai autant que possible.
Hashem Qolami
1
Bonjour, voici quelques captures d'écran: Browserstack.com/screenshots/… - comme vous pouvez le voir avec des appareils plus petits (par exemple Xperia, LG Nexus 4), les images apparaissent sous les conteneurs ... que se passe-t-il?!
user1794295
3
@HashemQolami C'est la chose CSS la plus étonnante, depuis que j'ai commencé à créer des sites Web :).
Alexander Solonik
1
Merci pour font-size: 0;!
Johannes Liebermann
47

Avec flexbox, c'est facile:

VIOLON

Ajoutez simplement ce qui suit au conteneur d'image:

.img-container {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    display: flex; /* add */
    justify-content: center; /* add to align horizontal */
    align-items: center; /* add to align vertical */
}
Danield
la source
2
Cette solution fonctionne et est beaucoup plus élégante dans mon cas. CSS3 Flex est génial!
Daniel Bonnell
2
Cela ne fonctionne pas dans Safari: (Je suppose que le problème est flex
yennefer
1
@yennefer pour safari utilisez le -webkit-préfixe, ou essayez une bibliothèque comme prefixfree.js :)
QUB3X
Cela ne fonctionne pas lorsque la hauteur du conteneur est réactive (en pourcentage).
jenlampton
1
Solution parfaite!
Nirus
16

Utilisez ce css, car vous en avez déjà le balisage:

.img-container {
    position: absolute;
    top: 50%;
    left: 50%;
}

.img-container > img {
  margin-top:-50%;
  margin-left:-50%;  
}

Voici un JsBin fonctionnel: http://jsbin.com/ihilUnI/1/edit

Cette solution ne fonctionne que pour les images carrées (car une valeur en pourcentage de la marge supérieure dépend de la largeur du conteneur, pas de la hauteur). Pour les images de taille aléatoire, vous pouvez effectuer les opérations suivantes:

.img-container {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%); /* add browser-prefixes */
}

Solution de travail JsBin: http://jsbin.com/ihilUnI/2/edit

Tibos
la source
Désolé, cela ne fonctionne pas pour moi - cela réduit simplement la taille des images à la moitié de la largeur du conteneur.
user1794295
2
Je ne vois pas comment cela peut arriver à partir du CSS que j'ai mentionné. Veuillez fournir un échantillon fonctionnel que je peux voir afin que je puisse améliorer ma réponse. PS: j'ai aussi fourni une autre solution :)
Tibos
11

Vous pouvez centrer une image, à la fois horizontalement et verticalement, en utilisant margin: autoun positionnement absolu. Aussi:

  1. Il est possible d'abandonner le balisage supplémentaire en utilisant des pseudo éléments.
  2. Il est possible d'afficher la partie centrale des images GRANDES en utilisant des valeurs négatives à gauche, en haut, à droite et en bas.

.responsive-container {
  margin: 1em auto;
  min-width: 200px;       /* cap container min width */
  max-width: 500px;       /* cap container max width */
  position: relative;     
  overflow: hidden;       /* crop if image is larger than container */
  background-color: #CCC; 
}
.responsive-container:before {
  content: "";            /* using pseudo element for 1:1 ratio */
  display: block;
  padding-top: 100%;
}
.responsive-container img {
  position: absolute;
  top: -999px;            /* use sufficiently large number */
  bottom: -999px;
  left: -999px;
  right: -999px;
  margin: auto;           /* center horizontally and vertically */
}
<p>Note: images are center-cropped on &lt;400px screen width.
  <br>Open full page demo and resize browser.</p>
<div class="responsive-container">
  <img src="http://lorempixel.com/400/400/sports/9/">
</div>
<div class="responsive-container">
  <img src="http://lorempixel.com/400/200/sports/8/">
</div>
<div class="responsive-container">
  <img src="http://lorempixel.com/200/400/sports/7/">
</div>
<div class="responsive-container">
  <img src="http://lorempixel.com/200/200/sports/6/">
</div>

Salman A
la source
Merci! votre .responsive-container img css était le seul qui fonctionnait pour moi.
Diogo Garcia
4

Essaye celui-là

  .responsive-container{
          display:table;
  }
  .img-container{
          display:table-cell;
          vertical-align: middle;
   }

la source
Désolé cela ne fonctionne pas, je pense que parce que mon .img-containerest absolument positionné - cela est nécessaire pour garder le rapport hauteur / largeur carré / hauteur dynamique.
user1794295
2

Voici une technique qui vous permet de centrer TOUT contenu à la fois verticalement et horizontalement!

Fondamentalement, vous avez juste besoin de deux conteneurs et assurez-vous que vos éléments répondent aux critères suivants.

Le conteneur extérieur:

  • avoir dû display: table;

Le conteneur intérieur:

  • avoir dû display: table-cell;
  • avoir dû vertical-align: middle;
  • avoir dû text-align: center;

La boîte de contenu:

  • avoir dû display: inline-block;

Si vous utilisez cette technique, ajoutez simplement votre image (avec tout autre contenu que vous souhaitez accompagner) dans la zone de contenu.

Démo:

body {
    margin : 0;
}

.outer-container {
    position : absolute;
    display: table;
    width: 100%;
    height: 100%;
    background: #ccc;
}

.inner-container {
    display: table-cell;
    vertical-align: middle;
    text-align: center;
}

.centered-content {
    display: inline-block;
    background: #fff;
    padding : 12px;
    border : 1px solid #000;
}

img {
   max-width : 120px;
}
<div class="outer-container">
   <div class="inner-container">
     <div class="centered-content">
        <img src="https://i.stack.imgur.com/mRsBv.png" />
     </div>
   </div>
</div>

Voir aussi ce violon !

John Slegers
la source
2

Je suis tombé sur ce fil à la recherche d'une solution qui:

  • utilise 100% de la largeur de l'image donnée
  • conserve le rapport hauteur / largeur de l'image
  • garde l'image alignée verticalement au milieu
  • fonctionne dans les navigateurs qui ne prennent pas entièrement en charge flex

En testant certaines des solutions publiées ci-dessus, je n'en ai pas trouvé une répondant à tous ces critères, j'ai donc rassemblé cette solution simple qui pourrait être utile pour d'autres personnes qui doivent faire de même:

.container {
  width: 30%;
  float: left;
  border: 1px solid turquoise;
  margin-right: 3px;
  margin-top: 3px;
}

.container:last-of-kind {
  margin-right: 0px;
}

.image-container {
  position: relative;
  overflow: hidden;
  padding-bottom: 70%;
  /* this is the desired aspect ratio */
  width: 100%;
}

.image-container img {
  position: absolute;
  /* the following 3 properties center the image on the vertical axis */
  top: 0;
  bottom: 0;
  margin: auto;
  /* uses image at 100% width (also meaning it's horizontally center) */
  width: 100%;
}
<div class="container">
  <div class="image-container">
    <img src="http://placehold.it/800x800" class="img-responsive">
  </div>
</div>

<div class="container">
  <div class="image-container">
    <img src="http://placehold.it/800x800" class="img-responsive">
  </div>
</div>

<div class="container">
  <div class="image-container">
    <img src="http://placehold.it/800x800" class="img-responsive">
  </div>
</div>

Exemple de travail sur JSFiddle

Alexandra
la source
0

Essayer

HTML

<div class="responsive-container">
     <div class="img-container">
         <IMG HERE>
     </div>
</div>

CSS

.img-container {
    position: absolute;
    top: 0;
    left: 0;
height:0;
padding-bottom:100%;
}
.img-container img {
width:100%;
}
Paramasivan
la source
0

Code HTML

<div class="image-container"> <img src=""/> </div>

code css

img
{
  position: relative;
  top: 50%;
  transform: translateY(-50%);
 }
William
la source
Bien que cet extrait de code soit le bienvenu et puisse fournir une aide, il serait grandement amélioré s'il incluait une explication de la façon dont il répond à la question. Sans cela, votre réponse a beaucoup moins de valeur éducative - rappelez-vous que vous répondez à la question pour les lecteurs à l'avenir, pas seulement pour la personne qui la pose maintenant! Veuillez modifier votre réponse pour ajouter une explication et donner une indication des limites et des hypothèses applicables.
Toby Speight
0

Créez un autre div et ajoutez à la fois 'dummy' et 'img-container' à l'intérieur du div

Faites du HTML et du CSS comme suit

html , body {height:100%;}
.responsive-container { height:100%; display:table; text-align:center; width:100%;}
.inner-container {display:table-cell; vertical-align:middle;}
<div class="responsive-container">
    <div class="inner-container">
		<div class="dummy">Sample</div>
		<div class="img-container">
			Image tag
		</div>
	</div>	
</div>

Au lieu de 100% pour le `` conteneur réactif '', vous pouvez donner la hauteur que vous voulez.,

Découvrir
la source