html - Как сделать так, чтобы изображения оставались в строках контейнера css?




image css3 (2)

Приведенный ниже код демонстрирует предполагаемое поведение при изменении размера окна в Chrome 60 и Firefox 55 (но не в iOS Safari 10.3; это, скорее всего, еще один вопрос, почему он ведет себя неправильно в Safari).

html, body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  border: 0;
  background-color: lightgrey;
}

.container {
  box-sizing: border-box;
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: repeat(3, calc((60vh - 12px)/3));
  /*grid-template-rows: 1fr 1fr 1fr;*/
  /*grid-template-rows: auto auto auto;*/
  height: 60vh;
  border: 3px solid yellow;
  padding: 3px;
  /*grid-gap: 20px;*/ /* <-- would also mess things up */
}

.tile {
}

img {
  box-sizing: border-box;
  display: block;
  object-fit: contain;
  width: 100%;
  height: 100%;
  margin: 0;
  border: 0;
  padding: 3px;
}
 <!-- The image is 200 x 100 px: a green and a blue square next to each other. -->
 <div class="container">
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
 </div>

Важно, что соотношение сторон изображения (2: 1)

сохраняется Я бы ожидал либо:

grid-template-rows: 1fr 1fr 1fr;

или же:

grid-template-rows: auto auto auto;

делает изображения вписанными в ряды сетки, но ни один из них не делает. С:

grid-template-rows: repeat(3, calc((60vh - 12px)/3));

Я получаю желаемое поведение. Как я могу избежать математики самостоятельно? Другими словами, что мне делать, чтобы grid-template-rows: 1fr 1fr 1fr; (или что-то подобное) работает?

Уже трудно определить высоту элемента контейнера в CSS на реальной странице. Цель состоит в том, чтобы решить это с помощью CSS сетки. нет JavaScript, и нет взлома фонового изображения.

Обновление: я первоначально исключил взлом фонового изображения по двум причинам.

  1. Я подумал (из-за некоторых недоразумений), что URL фонового изображения должен быть в файле CSS, но это не так: я могу использовать встроенные стили и использовать его в HTML.

  2. Это было грубо. После того, как я увидел, насколько сложным и запутанным он становится с вложенными flex-контейнерами, вложенными в контейнер grid, чтобы заставить его работать в Safari, я просто прибегнул к взлому фонового изображения, поскольку он значительно чище и работает во всех протестированных браузерах (Chrome, Firefox, Сафари).

В конце концов, это не принятый ответ, который помог решить мою проблему.


Вы можете использовать grid-template-rows: 1fr 1fr 1fr и, что более важно, вы должны сбросить значения min-width и min-height элементов сетки, которые по умолчанию установлены на auto (столько же, сколько содержимое).

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

Источник: W3C

Это похоже на правило auto flex item для flexbox . Смотрите демо ниже, где я обнуляю их:

html, body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  border: 0;
  background-color: lightgrey;
}

.container {
  box-sizing: border-box;
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  height: 60vh;
  border: 3px solid yellow;
  padding: 3px;
  /*grid-gap: 20px;*/ /* <-- would also mess things up */
}

.tile {
  min-width: 0;
  min-height: 0;
}

img {
  box-sizing: border-box;
  display: block;
  object-fit: contain;
  width: 100%;
  height: 100%;
  margin: 0;
  border: 0;
  padding: 3px;
}
<!-- The image is 200 x 100 px: a green and a blue square next to each other. -->
 <div class="container">
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
 </div>


У вас есть изображения, установленные на height: 100% . Но 100% чего? 100% контейнера? 100% области просмотра? 100% подряд? Если да, то какова высота ряда?

Chrome и Firefox делают обоснованное предположение о ваших намерениях. Они внедрили алгоритмы, разработанные для того, чтобы выйти за рамки спецификаций и улучшить пользовательский опыт. Они называют эти модификации "interventions" .

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

Эти различия в браузере объясняются более подробно здесь:

  • CSS Grid Row Высота Safari Ошибка
  • Chrome / Safari не заполняет 100% высоты родительского элемента flex

Тогда вы должны учитывать, что элементы сетки по умолчанию не могут быть меньше их содержимого. Если для ваших строк установлено значение 1fr , но изображения превышают выделенное пространство, строки должны расширяться. Вы можете переопределить это поведение с помощью min-height: 0 / min-width: 0 или overflow любым значением, отличным от visible .

Это поведение объясняется более подробно здесь:

  • Предотвращение растяжения элементов сетки в CSS Grid Layout
  • Почему гибкий элемент не уходит от размера контента?

Тем не менее, если вы учтете приведенные выше рекомендации, вы, вероятно, сможете заставить свой макет работать в Safari с комбинацией свойств grid и flex:

* {
  box-sizing: border-box;
}

body {
  display: flex;
  flex-direction: column;
  height: 100vh;
  margin: 0;
  background-color: lightgrey;
}

header,
footer {
  flex: 0 0 100px;
  background-color: tomato;
  display: flex;
  align-items: center;
  justify-content: center;
}

.container {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: auto;
  padding: 3px;
}

.tile {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 0;
}

img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  padding: 3px;
}
<header>HEADER</header>
<!-- The image is 200 x 100 px: a green and a blue square next to each other. -->
<div class="container">
  <div class="tile">
    <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
  </div>
  <div class="tile">
    <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
  </div>
  <div class="tile">
    <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
  </div>
  <div class="tile">
    <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
  </div>
  <div class="tile">
    <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
  </div>
  <div class="tile">
    <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
  </div>
</div>
<footer>FOOTER</footer>

jsFiddle





css-grid