Вертикально выровнять изображение внутри div с отзывчивой высотой

135

У меня есть следующий код, который устанавливает контейнер, высота которого изменяется в зависимости от ширины при изменении размера браузера (для сохранения квадратного соотношения сторон).

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

Как я могу вертикально выровнять IMG внутри контейнера? Все мои изображения имеют переменную высоту, и контейнер не может иметь фиксированную высоту / высоту строки, потому что он отзывчивый ... Пожалуйста, помогите!

user1794295
источник
1
Вот простое решение flexbox: stackoverflow.com/a/31977476/3597276
Майкл Бенджамин

Ответы:

381

Вот методика выравнивания встроенных элементов внутри родителя , по горизонтали и вертикали одновременно:

Вертикальное выравнивание

1) В этом подходе мы создаем inline-block(псевдо) элемент в качестве первого (или последнего) дочернего элемента родителя и устанавливаем его heightсвойство, 100%чтобы принимать всю высоту его родителя .

2) Кроме того, добавление vertical-align: middleсохраняет встроенные элементы (-block) в середине строки. Итак, мы добавляем эту декларацию CSS к первому дочернему элементу и нашему элементу ( изображению ).

3) Наконец, чтобы удалить пробел между символами inline (-block) , мы можем установить нулевой размер шрифта родительского элемента font-size: 0;.

Примечание: я использовал технику замены изображения Николаса Галлахера в следующем.

Каковы преимущества?

  • Контейнер ( родитель ) может иметь динамические размеры.
  • Нет необходимости явно указывать размеры элемента изображения.

  • Мы можем легко использовать этот подход для выравнивания <div>элемента по вертикали ; который может иметь динамическое содержимое (высота и / или ширина). Но обратите внимание, что вы должны повторно установить font-sizeсвойство divдля отображения внутреннего текста. Демо онлайн .

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

Выход

Вертикально выровнять элемент в его контейнере

Отзывчивый Контейнер

Этот раздел не собирается отвечать на вопрос, так как ОП уже знает, как создать адаптивный контейнер. Однако я объясню, как это работает.

Чтобы высота элемента контейнера изменялась в зависимости от его ширины (с учетом соотношения сторон), мы могли бы использовать процентное значение для paddingсвойства top / bottom .

Процентное значение на верхней / нижней прокладкой или краями является относительно ширины содержащего блока.

Например:

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

Вот онлайн демо . Закомментируйте линии снизу и измените размер панели, чтобы увидеть эффект.

Кроме того, мы можем применить paddingсвойство к фиктивному дочернему элементу или :before/ :afterпсевдоэлементу для достижения того же результата. Но к сведению , что в этом случае процентное значение на paddingэто по отношению к ширине от .responsive-containerсебя.

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

Демо № 1 .
Демонстрация № 2 (Использование :afterпсевдоэлемента)

Добавление контента

Использование padding-topсвойства приводит к появлению огромного пространства в верхней или нижней части содержимого внутри контейнера .

Для того , чтобы исправить это, мы должны обернуть содержимое с помощью элемента - оболочки, удалите этот элемент из документа нормального потока, используя абсолютное позиционирование , и , наконец , развернуть обертку (бушель , используя top, right, bottomи leftсвойство) , чтобы заполнить все пространство своего родителя, контейнер .

Вот так:

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

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

Вот онлайн демо .


Собираем все вместе

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

Вот РАБОЧАЯ ДЕМО .

Очевидно, что вы можете избежать использования ::beforeпсевдоэлемента для совместимости с браузером и создать элемент в качестве первого потомка .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%;
}

ОБНОВЛЕНО ДЕМО .

Использование max-*свойств

Чтобы сохранить изображение внутри рамки на более низкой ширине, вы можете установить max-heightи max-widthсвойство на изображении:

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

Вот ОБНОВЛЕНИЕ ДЕМО .

Хашем Колами
источник
1
Привет, Хашем, большое спасибо за твой ответ - это сработало как волшебство для настольных браузеров, даже при изменении размера на меньшую ширину. Но, к сожалению, изображения появляются не на своем месте, под контейнером div, на мобильном устройстве (Android v2.3.5). Любая идея исправить это?
user1794295
3
@ user1794295 Я тестировал эту скрипку на трех устройствах Android с Android v2.3 (Galaxy S II, Galaxy Note, Motorola Droid 4) через browserstack.com, Все работает, как я ожидал. Результат можно найти здесь: browserstack.com/screenshots / ... . Пожалуйста, предоставьте скриншот или сделайте конкретный тест вашей проблемы. Я помогу, насколько смогу.
Всевышний Колами
1
Привет, вот несколько скриншотов: browserstack.com/screenshots/… - как вы можете видеть на небольших устройствах (например, Xperia, LG Nexus 4), изображения появляются под контейнерами ... что происходит ?!
user1794295
3
@HashemQolami Это самая удивительная вещь CSS, так как я начал создавать сайты :).
Александр Солоник
1
Спасибо за font-size: 0;!
Йоханнес Либерманн
47

С flexbox это легко:

FIDDLE

Просто добавьте следующее в контейнер изображений:

.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
источник
2
Это решение работает и гораздо более элегантно в моем случае. CSS3 Flex - это круто!
Даниэль Боннелл
2
Это не работает в Safari :( Я думаю, что проблема заключается в гибкости
yennefer
1
@yennefer для сафари используйте -webkit-префикс или попробуйте такую ​​библиотеку, как prefixfree.js :)
QUB3X
Это не работает, когда высота контейнера реагирует (в процентах).
Дженламптон
1
Идеальное решение!
Вирус
16

Используйте этот CSS, так как у вас уже есть разметка для него:

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

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

Вот рабочий JsBin: http://jsbin.com/ihilUnI/1/edit

Это решение работает только для квадратных изображений (так как процентное значение на полях зависит от ширины контейнера, а не от высоты). Для изображений произвольного размера вы можете сделать следующее:

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

Рабочее решение JsBin: http://jsbin.com/ihilUnI/2/edit

Tibos
источник
Извините, у меня не работает - это просто уменьшение размера изображений до половины ширины контейнера.
user1794295
2
Я не понимаю, как это может произойти из упомянутого мной CSS. Пожалуйста, предоставьте рабочий образец, который я смогу увидеть, чтобы я мог улучшить свой ответ. PS: я также предоставил другое решение :)
Tibos
11

Вы можете центрировать изображение как по горизонтали, так и по вертикали, используя margin: autoи абсолютное позиционирование. Также:

  1. Можно исключить дополнительную разметку, используя псевдоэлементы.
  2. Можно отобразить среднюю часть БОЛЬШИХ изображений, используя отрицательные значения слева, сверху, справа и снизу.

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

Салман А
источник
Спасибо! ваш .responsive-container img css был единственным, который работал на меня.
Диого Гарсия
4

Попробуй это

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

источник
Извините, это не работает, я думаю, потому что мой .img-containerабсолютно позиционирован - это необходимо для сохранения квадратного соотношения сторон / динамической высоты.
user1794295
2

Вот техника, которая позволяет вам центрировать ЛЮБОЙ контент как по вертикали, так и по горизонтали!

По сути, вам просто нужны два контейнера и убедитесь, что ваши элементы соответствуют следующим критериям.

Внешний контейнер:

  • должен иметь display: table;

Внутренний контейнер:

  • должен иметь display: table-cell;
  • должен иметь vertical-align: middle;
  • должен иметь text-align: center;

Контент окно:

  • должен иметь display: inline-block;

Если вы используете эту технику, просто добавьте свое изображение (вместе с любым другим контентом, который вы хотите использовать с ним) в поле контента.

Демо:

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>

Смотрите также эту скрипку !

Джон Слегерс
источник
2

Я наткнулся на эту тему в поисках решения, которое:

  • использует 100% ширины данного изображения
  • сохраняет соотношение сторон изображения
  • держит изображение вертикально выровненным по центру
  • работает в браузерах, которые не полностью поддерживают flex

Тестируя некоторые решения, опубликованные выше, я не нашел ни одного, который соответствовал бы всем этим критериям, поэтому я собрал этот простой, который может быть полезен для других людей, которым необходимо сделать то же самое:

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

Рабочий пример на JSFiddle

Александра
источник
0

Пытаться

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
источник
0

HTML-код

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

код CSS

img
{
  position: relative;
  top: 50%;
  transform: translateY(-50%);
 }
Уильям
источник
Хотя этот фрагмент кода приветствуется и может оказать некоторую помощь, он будет значительно улучшен, если в него будет включено объяснение того, как он решает этот вопрос. Без этого ваш ответ имеет гораздо меньшую образовательную ценность - помните, что в будущем вы отвечаете на вопрос читателей, а не просто того, кто спрашивает сейчас! Пожалуйста, отредактируйте свой ответ, чтобы добавить объяснение и указать, какие ограничения и предположения применяются.
Тоби Спейт
0

Создайте еще один div и добавьте в него и «dummy», и «img-container»

Делайте HTML и CSS как следует

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>

Вместо 100% для «отзывчивого контейнера» вы можете указать желаемую высоту.

Обнаружить
источник