Почему ширина и высота гибкого элемента влияют на визуализацию гибкого элемента?

Изображение в flexbox, которое имеет max-height стиль отображается по-разному в зависимости от того, имеет ли он height а также width атрибуты установлены.

Тот, с атрибутами, установленными на истинную ширину / высоту изображения, рендерится с сохраненным соотношением сторон, но те, у которых нет атрибутов, учитывают max-height и кажется раздавленным.

.flex-parent {
  display: flex;
  max-height: 10vh;
}
<div class="flex-parent">
  <img                          src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  <img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>

Вот как это выглядит в Chrome 58 (и аналогично в Firefox 54).

Различный рендеринг img во flexbox. Без атрибутов ширины и высоты, а также с

Почему они делают по-разному? Какие правила определяют это поведение?

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

Контекст делает страницу с адаптивными изображениями, где каждое изображение

  • может иметь уникальные оригинальные размеры
  • не вызывает перекомпоновку при загрузке, т. е. при первоначальном рендере зарезервировано правильное пространство (следовательно, используются атрибуты высоты и ширины)
  • может вместить все на экран сразу (отсюда и я балуюсь vh в CSS)

Изображение лягушки от https://en.wikipedia.org/wiki/File:Red_eyed_tree_frog_edit2.jpg

4 ответа

Решение

Начальная настройка гибкого контейнера align-items: stretch,

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

В контейнере в направлении строки, как в вопросе, поперечная ось является вертикальной.

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

Однако, когда гибкий элемент имеет определенный размер креста, он переопределяет stretch дефолт.

Из спецификации:

8.3. Выравнивание по оси align-items а также align-self свойства

Элементы Flex могут быть выровнены по поперечной оси текущей строки контейнера Flex, аналогично justify-content но в перпендикулярном направлении.

stretch

Если свойство размера креста элемента flex вычисляется как auto и ни один из полей поперечной оси не auto, гибкий элемент растягивается.

Это ключевой язык:

Если свойство размера креста элемента flex вычисляется как auto

И вот как спецификация определяет "свойство поперечного размера":

Ширина или высота гибкого элемента, который находится в поперечном измерении, является поперечным размером элемента. Свойство размера креста зависит от того, width или же height это в поперечном измерении.

https://www.w3.org/TR/css-flexbox-1/


Таким образом, ваш код воспроизводится так, как определено в спецификации.

Это то, что у вас есть:

.flex-parent {
  display: flex;
  max-height: 10vh;
}
<div class="flex-parent">
  <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  <img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>

Первое изображение не имеет определенной ширины (основной размер) или высоты (поперечный размер) ни в CSS, ни в HTML. Его поперечный размер, следовательно, вычисляет auto,

Это утверждение:

Если свойство размера креста элемента flex вычисляется как auto

... это правда, и align-items: stretch вступает в силу.

Изображение расширяется по высоте контейнера, которая составляет 10 пикселей.

Второе изображение, однако, имеет явный размер. Размер креста определяется в HTML (height="240").

Теперь это утверждение:

Если свойство размера креста элемента flex вычисляется как auto

... ложно, и align-items: stretch отменяется HTML height Атрибут преобладает.

Две заметки о втором изображении:

  1. Изображение игнорирует max-height ограничение на контейнер, потому что начальная настройка в CSS overflow: visible,
  2. HTML width а также height атрибуты сопоставляются с их соответствующими свойствами CSS. Следовательно, height="240" переопределяет height: auto дефолт. Ниже приведены ссылки на спецификации.*

При рендеринге изображений во флекс-контейнере необходимо учитывать еще две проблемы.

  1. Минимальный размер по умолчанию для гибких элементов. Этот параметр предотвращает сжатие элементов Flex ниже размера их содержимого. Прочтите этот пост для полной информации:

  2. Различное поведение среди основных браузеров. Firefox, Chrome, Safari, Edge и IE11 не всегда отображают изображения как гибкие элементы одинаково. Прочтите этот пост для более подробной информации:


Учитывая все вышеперечисленные факторы, вот мое предлагаемое решение:

.flex-parent {
  display: flex;
  max-height: 50vh; /* adjusted for demo */
}

.flex-parent {
  min-width: 0;
}

img {
  width: 100%;
  height: auto;
}
<div class="flex-parent">
  <div>
    <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  </div>
  <div>
    <img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  </div>
</div>


* HTML width а также height атрибуты сопоставляются с их соответствующими свойствами CSS. Следовательно, если указано, они переопределяют значения по умолчанию CSS. Из спецификации HTML5:

10.4.3 Атрибуты для встроенного контента и изображений

width а также height атрибуты на applet, embed, iframe, object или же video элементы и input элементы с type атрибут в состоянии кнопки изображения, который либо представляет изображение, либо, как ожидает пользователь, в конечном итоге будет представлять изображение, сопоставляя его со свойствами измерения. width а также height на элементе соответственно.

10.2 Таблица стилей агента пользователя CSS и подсказки для презентации

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

Пробовал читать спецификации flexbox w3c и наткнулся на это. Это говорит о том, что

Для каждого измерения, если это измерение поля содержимого гибкого контейнера имеет определенный размер, используйте его; если этот размер гибкого контейнера измеряется с ограничением min или max-content, доступное пространство в этом измерении является этим ограничением.

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

Надеюсь это поможет.

Здесь вы написали max-height:10vh, vh не поддерживает ни в одном браузере, кроме самой последней iOS 6. Это относится ко всем единицам длины, относящимся к области просмотра. используйте другие значения вместо Vh, это будет работать нормально. Пожалуйста, прочтите этот блог https://css-tricks.com/the-lengths-of-css/.

.flex-parent {
  display: flex;
  max-height:  max-content;
}
<div class="flex-parent">
  <img                          src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  <img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>

Проблема в том, где вы устанавливаете максимальную высоту. Свойство css max-height по умолчанию не наследуется. Ваше объявление CSS создает div, который составляет 10% от высоты области просмотра. Изображение без размеров устанавливается сжатым в зависимости от его родительских размеров. Изображение, на которое вы устанавливаете неявные размеры, всегда будет этими размерами. В зависимости от размера div, он может переполниться. Если вы поместите свойство max-height на первое изображение, оно должно изменить размер, сохранив соотношение сторон.

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