Alinee verticalmente una imagen dentro de un div con altura receptiva

135

Tengo el siguiente código que configura un contenedor que tiene una altura que cambia con el ancho cuando se redimensiona el navegador (para mantener una relación de aspecto cuadrado).

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

¿Cómo puedo alinear verticalmente el IMG dentro del contenedor? Todas mis imágenes tienen alturas variables y el contenedor no puede tener una altura fija / altura de línea porque responde ... ¡Por favor, ayuda!

usuario1794295
fuente
1
Aquí hay una solución simple de flexbox: stackoverflow.com/a/31977476/3597276
Michael Benjamin

Respuestas:

381

Aquí hay una técnica para alinear elementos en línea dentro de un padre , horizontal y verticalmente al mismo tiempo:

Alineamiento vertical

1) En este enfoque, creamos un inline-block(pseudo-) elemento como el primer (o último) hijo del padre , y configuramos su heightpropiedad 100%para tomar toda la altura de su padre .

2) Además, la suma vertical-align: middlemantiene los elementos en línea (bloque) en el medio del espacio de línea. Entonces, agregamos esa declaración CSS al primer hijo y a nuestro elemento (la imagen ) ambos.

3) Finalmente, para eliminar el carácter de espacio en blanco entre los elementos en línea (-block) , podríamos establecer el tamaño de fuente del padre en cero por font-size: 0;.

Nota: Utilicé la técnica de reemplazo de imagen de Nicolas Gallagher a continuación.

¿Cuales son los beneficios?

  • El contenedor ( padre ) puede tener dimensiones dinámicas.
  • No es necesario especificar las dimensiones del elemento de imagen explícitamente.

  • Podemos usar fácilmente este enfoque para alinear un <div>elemento verticalmente también; que puede tener un contenido dinámico (alto y / o ancho). Pero tenga en cuenta que debe volver a configurar la font-sizepropiedad de divpara mostrar el texto interior. Demo en línea .

<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 */
}

La salida

Alinear verticalmente un elemento en su contenedor

Contenedor receptivo

Esta sección no responderá la pregunta ya que el OP ya sabe cómo crear un contenedor receptivo. Sin embargo, explicaré cómo funciona.

Para hacer que la altura de un elemento contenedor cambie con su ancho (respetando la relación de aspecto), podríamos usar un valor porcentual para la paddingpropiedad superior / inferior .

Un valor porcentual en el margen superior / inferior o en los márgenes es relativo al ancho del bloque contenedor.

Por ejemplo:

.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   */
}

Aquí está la demostración en línea . Comente las líneas desde la parte inferior y cambie el tamaño del panel para ver el efecto.

Además, podríamos aplicar la paddingpropiedad a un hijo ficticio o :before/ :afterpseudo-elemento para lograr el mismo resultado. Pero tenga en cuenta que en este caso, el valor de porcentaje en paddinges relativo al ancho de .responsive-containersí mismo.

<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 */
}

Demo # 1 .
Demo # 2 (Usando :afterpseudo-elemento)

Agregar el contenido

El uso de la padding-toppropiedad provoca un gran espacio en la parte superior o inferior del contenido, dentro del contenedor .

Con el fin de fijar de eso, tenemos envolver el contenido por un elemento de envoltura, eliminar ese elemento de flujo normal de documentos mediante el posicionamiento absoluto , y, finalmente, expandir la envoltura (bu usando top, right, bottomy leftpropiedades) para llenar todo el espacio de su matriz, El contenedor .

Aquí vamos:

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

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

Aquí está la demostración en línea .


Todos juntos

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

Aquí está la demostración de trabajo .

Obviamente, podría evitar el uso de ::beforepseudoelementos para la compatibilidad del navegador y crear un elemento como primer hijo 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%;
}

DEMO ACTUALIZADA .

Usando max-*propiedades

Con el fin de mantener el interior la imagen de la caja de ancho menor, podría configurar max-heighty max-widthpropiedad en la imagen:

.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 */
}

Aquí está la DEMO ACTUALIZADA .

Hashem Qolami
fuente
1
Hola Hashem, muchas gracias por tu respuesta: esto funcionó como magia para los navegadores de escritorio, incluso cuando cambiaste el tamaño a anchos más pequeños. Pero desafortunadamente, las imágenes aparecen fuera de posición, debajo del contenedor div, en dispositivos móviles (Android v2.3.5). ¿Alguna idea sobre una solución para esto?
user1794295
3
@ user1794295 Probé este violín en tres dispositivos Android con Android v2.3 (Galaxy S II, Galaxy Note, Motorola Droid 4) a través de browserstack.com, todo funciona como esperaba. Puede encontrar el resultado aquí: browserstack.com/screenshots / ... . Proporcione una captura de pantalla o una prueba específica de su problema. Ayudaré lo más que pueda.
Hashem Qolami
1
Hola, aquí hay algunas capturas de pantalla: browserstack.com/screenshots/… , como puede ver con dispositivos más pequeños (por ejemplo, Xperia, LG Nexus 4), las imágenes aparecen debajo de los contenedores ... ¿qué está pasando?
user1794295
3
@HashemQolami Esto es lo más sorprendente de CSS, desde que comencé a construir sitios web :).
Alexander Solonik
1
Gracias por font-size: 0;!
Johannes Liebermann
47

Con flexbox esto es fácil:

VIOLÍN

Simplemente agregue lo siguiente al contenedor de imágenes:

.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
fuente
2
Esta solución funciona y es mucho más elegante en mi caso. ¡CSS3 Flex es increíble!
Daniel Bonnell
2
No funciona en Safari :( Creo que el problema es flexible
yennefer
1
@yennefer para el -webkit-prefijo de uso de safari , o pruebe una biblioteca como prefixfree.js :)
QUB3X
Esto no funciona cuando la altura del contenedor responde (en porcentaje).
jenlampton
1
¡Solución perfecta!
Nirus
16

Use este CSS, ya que tiene el marcado para ello:

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

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

Aquí hay un JsBin en funcionamiento: http://jsbin.com/ihilUnI/1/edit

Esta solución solo funciona para imágenes cuadradas (porque un valor de margen superior de porcentaje depende del ancho del contenedor, no de la altura). Para imágenes de tamaño aleatorio, puede hacer lo siguiente:

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

Solución de trabajo de JsBin: http://jsbin.com/ihilUnI/2/edit

Tibos
fuente
Lo siento, no funciona para mí, esto es solo reducir el tamaño de las imágenes a la mitad del ancho del contenedor.
user1794295
2
No veo cómo puede suceder eso del CSS que mencioné. Proporcione una muestra de trabajo que pueda ver para que pueda mejorar mi respuesta. PD: También proporcioné otra solución :)
Tibos
11

Puede centrar una imagen, tanto horizontal como verticalmente, utilizando margin: autoun posicionamiento absoluto. También:

  1. Es posible deshacerse del marcado adicional utilizando pseudo elementos.
  2. Es posible visualizar la porción media de imágenes GRANDES usando valores negativos izquierdo, superior, derecho e inferior.

.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
fuente
¡Gracias! tu .responsive-container img css fue el único que funcionó para mí.
Diogo García
4

Prueba este

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

fuente
Lo siento, esto no funciona, creo que porque my .img-containerestá absolutamente posicionado, esto es necesario para mantener la relación de aspecto cuadrado / altura dinámica.
user1794295
2

¡Aquí hay una técnica que le permite centrar CUALQUIER contenido tanto vertical como horizontalmente!

Básicamente, solo necesita dos contenedores y asegúrese de que sus elementos cumplan con los siguientes criterios.

El otro contenedor:

  • debería tener display: table;

El contenedor interior:

  • debería tener display: table-cell;
  • debería tener vertical-align: middle;
  • debería tener text-align: center;

El cuadro de contenido:

  • debería tener display: inline-block;

Si utiliza esta técnica, simplemente agregue su imagen (junto con cualquier otro contenido que desee utilizar) al cuadro de contenido.

Demo:

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>

Ver también este violín !

John Slegers
fuente
2

Encontré este hilo en busca de una solución que:

  • usa el 100% del ancho de la imagen dada
  • mantiene la relación de aspecto de la imagen
  • mantiene la imagen alineada verticalmente al medio
  • funciona en navegadores que no son totalmente compatibles con flex

Al probar algunas de las soluciones publicadas anteriormente, no encontré una que cumpla con todos estos criterios, por lo que armé esta simple que podría ser útil para otras personas que necesitan hacer lo mismo:

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

Ejemplo de trabajo en JSFiddle

Alexandra
fuente
0

Tratar

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

código HTML

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

código css

img
{
  position: relative;
  top: 50%;
  transform: translateY(-50%);
 }
Guillermo
fuente
Si bien este fragmento de código es bienvenido y puede proporcionar algo de ayuda, mejoraría enormemente si incluyera una explicación de cómo aborda la pregunta. Sin eso, su respuesta tiene mucho menos valor educativo: recuerde que está respondiendo la pregunta para los lectores en el futuro, ¡no solo la persona que pregunta ahora! Por favor, editar su respuesta para agregar explicación y dar una indicación de lo que se aplican limitaciones y supuestos.
Toby Speight
0

Haga otro div y agregue 'dummy' y 'img-container' dentro del div

Hacer HTML y CSS como sigue

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>

En lugar del 100% para el 'contenedor receptivo', puede dar la altura que desee.

Descubrir
fuente