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




image css3 (3)

Приведенный ниже код демонстрирует предполагаемое поведение при изменении размера окна в 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, Сафари).

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


Я не знаю, насколько аккуратно вы хотите, чтобы изображения подходили, но вы могли бы использовать minmax() . minmax() позволяет установить минимальное и максимальное значение для размера строки сетки. Установка auto для минимума и 33% для максимума позволит им получить столько, сколько нужно для контента, и до 33% высоты контейнера сетки, но не больше . Это сохранит все ваши элементы сетки вместе на максимальной высоте 99% от 60vh, что занимает контейнер сетки.

Это не совсем автоматический способ, которым вы надеялись получить ... вы все равно объявляете размер, даже если он относительный. Он избегает неуклюжего вида calc((60vh - 12px) / 3) , хотя в этом методе нет ничего плохого, если только в вашем посте нет других ограничений.

Тем не менее, kukkuz 'ответ и сброс min-height - лучшее решение, и это то, чего мне не хватало.

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, minmax(auto, 33%));
  height: 60vh;
  border: 3px solid yellow;
  padding: 3px;
}
.tile {
    display: grid;
}
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>


Вы можете использовать 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