Флекс-элемент изображения не уменьшает высоту во флексбоксе

У меня есть гибкий контейнер, который содержит гибкий элемент img.

Я хочу, чтобы этот img игнорировал его внутреннюю высоту (90 пикселей), чтобы высота могла уменьшаться, чтобы соответствовать высоте гибкого элемента родственного элемента (согласно стилю по умолчанию align-items: stretch).

.container {
    border: 1px solid;
    display: flex;
}

.item {
    border: 1px solid;
}

.content {
    width: 200px;
    height: 50px;
    background-color: hotPink;
}
<div class = "container">
    <img class = "item" src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ">
    <div class = "item">
        <div class = "content"></div>
    </div>
</div>

Мы можем увидеть желаемое поведение, если поменяем img на div:

.container {
    border: 1px solid;
    display: flex;
}

.item {
    border: 1px solid;
}

.dynamicHeightContent {
    width: 120px;
    height: 100%;
    background-color: green;
}

.content {
    width: 200px;
    height: 50px;
    background-color: hotPink;
}
<div class = "container">
    <div class = "item">
        <div class = "dynamicHeightContent"></div>
    </div>
    <div class = "item">
        <div class = "content"></div>
    </div>
</div>

Пробовал min-height: 0 на img, безрезультатно.

  • Какое особое поведение относится к img, но не к div?
  • Как мы можем отказаться от особого поведения img, чтобы он вел себя как другие гибкие элементы (например, div)? Если нет способа отказаться, есть ли рекомендуемый обходной путь?

Обратите внимание, что хотя высота img не уменьшается, она выглядит как расти:

.container {
    border: 1px solid;
    display: flex;
}

.item {
    border: 1px solid;
}

.content {
    width: 200px;
    height: 300px;
    background-color: hotPink;
}
<div class = "container">
    <img class = "item" src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ">
    <div class = "item">
        <div class = "content"></div>
    </div>
</div>

Примечание: я рад игнорировать соотношение сторон img. Я планирую избегать перекоса img через object-fit: cover.

заверните изображение в div и увидите разницу...

kukkuz 11.04.2019 12:24

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

Huangism 11.04.2019 16:53
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
7
2
3 078
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

хотя это не тот ответ, который вы спрашиваете, но div и img на самом деле ведут себя одинаково, то есть, если есть контент выше высоты, он увеличивает высоту

пример:

.container {
    border: 1px solid;
    display: flex;
}

.item {
    border: 1px solid;
}

.dynamicHeightContent {
    width: 120px;
    height: 100%;
    background-color: green;
}

.content {
    width: 200px;
    height: 50px;
    background-color: hotPink;
}
<div class = "container">
    <div class = "item">
        <div class = "dynamicHeightContent">
        akhsdjahskd<br>
        ajkhsdkjhasd<br>
        ajshdkahsd<br>
        ajsgdjgad<br>
        ajshdasjdh<br>
        </div>
    </div>
    <div class = "item">
        <div class = "content"></div>
    </div>
</div>

так как вы настаиваете на том, что object-fit должен решить эту проблему, вы можете попробовать это, как видите, object-fit работает, только если мы установим высоту и ширину, иначе браузер попытается заставить его «сохранить соотношение сторон», просто попробуйте удалить высоту или ширина из css (по одному), вы увидите этот эффект

.container {
    border: 1px solid;
    display: flex;
}

.item {
    border: 1px solid;
}

img.item {
    height: 50px;
    width: 200px;
    object-fit: cover;
}

.content {
    width: 200px;
    height: 50px;
    background-color: hotPink;
}
<div class = "container">
    <img class = "item" src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ">
    <div class = "item">
        <div class = "content"></div>
    </div>
</div>

Я думаю, вы смотрите на это неправильно.

Само изображение имеет высоту 90 пикселей, что означает, что содержимое гибкого элемента имеет высоту 90 пикселей (поскольку ваше изображение является гибким элементом). Таким образом, ваш div с правой стороны соответствует высоте изображения, потому что он выше высоты div, а не наоборот.

Подумайте об этом, как если бы вы установили высоту гибкого элемента (изображения) на 90 пикселей. Таким образом, он не уменьшится, если вы не установите меньшую высоту. Несмотря на то, что вы явно не установили высоту изображения на 90 пикселей, но она составляет 90 пикселей, поэтому она устанавливается неявно, что вызывает путаницу. Таким образом, хотя он будет превышать 90 пикселей в высоту, он не уйдет под него, потому что это высота содержимого гибкого элемента.

В случае, когда вы поменяли его на div, и он работает так, как вы себе представляли, это связано с тем, что для .item div, который является гибким элементом, не задана высота.

Это имеет смысл, но я бы ожидал, что будет способ игнорировать внутренний размер/высоту изображения, например. min-height: 0. Отдельно, каков рекомендуемый обходной путь? Это очень распространенный вариант использования.

Oliver Joseph Ash 11.04.2019 19:46

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

Huangism 11.04.2019 19:52

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

Huangism 11.04.2019 20:00

Это хороший способ увидеть это. Но когда вы используете object-fit, изображение может работать на любой высоте. По этой причине для CSS может иметь смысл иметь какой-то механизм для игнорирования внутренней высоты.

Oliver Joseph Ash 11.04.2019 20:07

Я надеюсь, что объяснение имеет смысл, это единственный способ, которым я могу логически объяснить это

Huangism 11.04.2019 20:09
Ответ принят как подходящий

Обратите внимание, что в вашем примере item — это гибкий элемент, а не content — вы должны проверить поведение растяжениеitem здесь.


How can we opt out of img's special behaviour so that it behaves like other flex items (such as div)?

Он ведет себя как другие гибкие элементы<img> может быть не очень полезен в качестве гибкий элемент, но поведение растяжения работает нормально:

  • если изображение имеет высоту больше, чем item, itemрастягивается соответствует высоте изображения
  • если высота изображения меньше item, изображение растягивается соответствует высоте content, нарушая соотношение сторон.

См. демо ниже:

.container {
  border: 1px solid;
  display: flex;
}

.item {
  background: cadetblue;
}

.content {
  width: 200px;
  background-color: hotPink;
}

img {
  display: block;
}
<h2>Small content</h2>
<div class = "container">
  <img src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ">
  <div class = "item">
    <div class = "content">some text here some text here some text here </div>
  </div>
</div>
<br/>
<h2>Large Content</h2>
<div class = "container">
  <img src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ">
  <div class = "item">
    <div class = "content">some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here </div>
  </div>
</div>

I have tried min-height: 0 on the img, to no avail.

min-height: 0 присваивается флексбокс столбца вдоль направление изгиба, чтобы переопределить поведение авто по умолчанию (для направление строки свойство равно min-width) — это не работает в поперечная ось.

Вы можете увидеть подробности и некоторые примеры ниже:


Оборачиваем изображение в контейнер

Теперь оберните <img> в div и увидите ту же ситуацию — поведение протяжение снова хорошее:

.container {
  border: 1px solid;
  display: flex;
}

.item {
  background: cadetblue;
}

.content {
  width: 200px;
  background-color: hotPink;
}

img {
  display: block;
}
<h2>Small content</h2>
<div class = "container">
  <div class = "item">
    <img src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ"></div>
  <div class = "item">
    <div class = "content">some text here some text here some text here </div>
  </div>
</div>
<br/>
<h2>Large Content</h2>
<div class = "container">
  <div class = "item">
    <img src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ"></div>
  <div class = "item">
    <div class = "content">some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here </div>
  </div>
</div>

Разница в том, что теперь вы можете успешно использовать object-fit на изображении (это не работает должным образом, если это гибкий элемент):

.container {
  border: 1px solid;
  display: flex;
}

.item {
  background: cadetblue;
}

.content {
  width: 200px;
  background-color: hotPink;
}

img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<h2>Small content</h2>
<div class = "container">
  <div class = "item">
    <img src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ"></div>
  <div class = "item">
    <div class = "content">some text here some text here some text here </div>
  </div>
</div>
<br/>
<h2>Large Content</h2>
<div class = "container">
  <div class = "item">
    <img src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ"></div>
  <div class = "item">
    <div class = "content">some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here </div>
  </div>
</div>

I want this img to disregard its intrinsic height (90px) so that the height may shrink to match the sibling's flex item height

Единственный способ игнорировать высоту изображения — использовать позиционирование в оболочке изображения:

  • расположите изображение абсолютно относительно его оболочки,
  • вы можете указать ширину обертке изображения или указать flex: 1 на item, чтобы получить половину доступной ширины по горизонтали.

См. демо ниже:

.container {
  border: 1px solid;
  display: flex;
}

.item {
  background: cadetblue;
  flex: 1; /* equal width for items */
}

.content {
  width: 200px;
  background-color: hotPink;
}

.item:first-child { /* image container */
  position: relative;
}

img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  position: absolute; /* position absolutely */
  top: 0;
  left: 0;
}
<h2>Small content</h2>
<div class = "container">
  <div class = "item">
    <img src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ"></div>
  <div class = "item">
    <div class = "content">some text here some text here some text here </div>
  </div>
</div>
<br/>
<h2>Large Content</h2>
<div class = "container">
  <div class = "item">
    <img src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRu-3yBSd2b6JCOMcGVSOFf8X49QB3Ik-OI87gKEMwWLrdJxP5qOErmZQ"></div>
  <div class = "item">
    <div class = "content">some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here </div>
  </div>
</div>

Это имеет смысл, спасибо. Жаль, что трюк position: absolute необходим. Я подозреваю, что это будет распространенная проблема, с которой сталкиваются разработчики. Похоже, нам нужен декларативный способ сделать это, добавленный в CSS, поэтому нам не нужно прибегать к этим хакам. Я буду наблюдать, чтобы увидеть, сколько внимания получит этот вопрос :-)

Oliver Joseph Ash 17.04.2019 12:29

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