it-swarm.com.ru

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

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

 dummy image

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

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, и нет фоновых изображений взломов.


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

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

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

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

8
Ali

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

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

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

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

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

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

Тем не менее, если вы учтете приведенные выше рекомендации, вы, вероятно, сможете заставить свой макет работать в 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

2
Michael_B

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

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

Источник: W3C

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

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>

3
kukkuz

Я не знаю, насколько точно вы хотите, чтобы изображения подходили, но вы можете использовать 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>

1
TylerH