CSS3 Flexbox поддерживает соотношение сторон изображения

С помощью гибкой блочной модели CSS, как заставить изображение сохранить его пропорции?

JS Fiddle http://jsfiddle.net/xLc2Le0k/2/

Обратите внимание, что изображения растягиваются или сжимаются, чтобы заполнить ширину контейнера. Это нормально, но можем ли мы также растянуть или уменьшить высоту, чтобы сохранить пропорции изображения?

HTML

<div class="slider">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
</div>

CSS

.slider {
    display: flex;
}
.slider img {
    margin: 0 5px;
}

9 ответов

Решение

Для тегов img, если вы определяете одну сторону, размер другой стороны изменяется, чтобы сохранить соотношение сторон, и по умолчанию изображения расширяются до своего исходного размера.

Используя этот факт, если вы поместите каждый тег img в тег div и установите его ширину равной 100% родительского тега div, высота будет соответствовать желаемому соотношению сторон.

http://jsfiddle.net/xLc2Le0k/15/

* {
    margin: 0;
    padding: 0;
}
.slider {
    display: flex;
}
.slider .slide img {
    width: 100%;
}

Чтобы предотвратить растягивание изображений по любой оси внутри гибкого родителя, я нашел несколько решений.

Вы можете попробовать использовать объектную посадку на изображении, которая, например,

object-fit: contain;

http://jsfiddle.net/ykw3sfjd/

Или вы можете добавить гибкие специальные правила, которые в некоторых случаях могут работать лучше.

align-self: center;
flex: 0 0 auto;

Не нужно добавлять содержащий div.

По умолчанию для свойства css "align-items" установлено значение "stretch", из-за которого ваши изображения растягиваются до полной первоначальной высоты. Установка свойства css "align-items" в значение "flex-start" решает вашу проблему.

.slider {
    display: flex;
    align-items: flex-start;  /* ADD THIS! */
}

Большинство изображений с собственными размерами, то есть натурального размера, как jpeg образ. Если указанный размер определяет как ширину, так и высоту, пропущенное значение определяется с использованием внутреннего отношения... - см. MDN.

Но это работает не так, как ожидалось, если изображения, которые задаются как прямые изгибаемые элементы с текущим модулем раскладки гибких блоков уровня 1, насколько я знаю.

Смотрите эти обсуждения и сообщения об ошибках могут быть связаны:

  • Flexbugs # 14 - Внутренние размеры Chrome/Flexbox не реализованы правильно.
  • Firefox Bug 972595 - Flex-контейнеры должны использовать "flex- based " вместо "width" для вычисления собственной ширины flex-элементов
  • Chromium Issue 249112 - В Flexbox разрешите собственные пропорции для расчета расчета основного размера.

В качестве обходного пути вы можете обернуть каждый <img> с <div> или <span>, или так.

jsFiddle

.slider {
  display: flex;
}

.slider>div {
  min-width: 0; /* why? see below. */
}

.slider>div>img {
  max-width: 100%;
  height: auto;
}
<div class="slider">
  <div><img src="https://picsum.photos/400/300?image=0" /></div>
  <div><img src="https://picsum.photos/400/300?image=1" /></div>
  <div><img src="https://picsum.photos/400/300?image=2" /></div>
  <div><img src="https://picsum.photos/400/300?image=3" /></div>
</div>

4.5 Предполагаемый минимальный размер гибких элементов

Чтобы обеспечить более разумный минимальный размер по умолчанию для гибких элементов, эта спецификация вводит новое автоматическое значение в качестве начального значения свойств min-width и min-height, определенных в CSS 2.1.


Кроме того, вы можете использовать CSS table вместо макета, который вы получите аналогичные результаты, как flexbox, он будет работать на большем количестве браузеров, даже для IE8.

jsFiddle

.slider {
  display: table;
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

.slider>div {
  display: table-cell;
  vertical-align: top;
}

.slider>div>img {
  max-width: 100%;
  height: auto;
}
<div class="slider">
  <div><img src="https://picsum.photos/400/300?image=0" /></div>
  <div><img src="https://picsum.photos/400/300?image=1" /></div>
  <div><img src="https://picsum.photos/400/300?image=2" /></div>
  <div><img src="https://picsum.photos/400/300?image=3" /></div>
</div>

В последнее время я играл в flexbox, и я нашел решение для этого путем экспериментов и следующих рассуждений. Однако на самом деле я не уверен, что именно так и происходит.

Если реальная ширина зависит от гибкой системы. Поэтому после того, как ширина элементов достигает максимальной ширины родительского элемента, дополнительная ширина, заданная в css, игнорируется. Тогда можно безопасно установить ширину на 100%.

Так как высота тега img является производной от самого изображения, то установка высоты в 0% может что-то сделать. (это то, где мне неясно, что... но для меня имело смысл это исправить)

DEMO

(помните, сначала увидел это здесь!)

.slider {
    display: flex;
}
.slider img {
    height: 0%;
    width: 100%;
    margin: 0 5px;
}

Пока работает только в хроме

This behavior is expected. flex container will stretch all its children by default. Image have no exception. (ie, parent will have align-items: stretch property)

To keep the aspect ratio we've two solutions:

  1. Either replace default align-items: stretch property to align-items: flex-start or align-self: center etc,http://jsfiddle.net/e394Lqnt/3/

or

  1. Set align property exclusively to the child itself: like, align-self: center or align-self: flex-start etc.http://jsfiddle.net/e394Lqnt/2/

Объявите, где display: flex;был дан Элемент.
align-items: center;

На самом деле я обнаружил, что контейнер тега изображения должен иметь высоту, чтобы сохранить соотношение изображения. например>

.container{display:flex; height:100%;} img{width:100%;height:auto;}

тогда в вашем HTML ваш контейнер обернет изображение тега

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

эта работа для IE и других браузеров

У меня просто была такая же проблема. Используйте гибкое выравнивание, чтобы центрировать ваши элементы. Вам нужно использовать align-items: center вместо align-content: center, Это будет поддерживать соотношение сторон, в то время как align-content не будет сохранять соотношение сторон.

Другие вопросы по тегам