Плавное масштабирование элементов в макете CSS Grid

Я создал макет ниже, используя display: grid, я использовал старый трюк padding-top, чтобы иметь плавные квадратные элементы div, но мне интересно, есть ли лучший способ сделать это с помощью CSS Grid или Flexbox. Макет должен выглядеть как есть, а не использовать JS.

https://codepen.io/anon/pen/GWzavX

.o-container {
  margin: 0 auto;
  max-width: 1280px;
}

.o-grid {
  box-sizing: border-box;
  display: grid;
  grid-gap: 1rem;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, 1fr);
  max-width: 100%;
  padding: 0 1rem;
  width: 100%;
}

.o-grid__content {
  box-sizing: border-box;
  height: 100%;
  padding: 1rem;
  position: absolute;
  top: 0;
  width: 100%;
}

.o-grid__item {
  box-shadow: inset 0 0 0 1px red;
  position: relative;
}

.o-grid__item--tall {
  grid-row: span 2;
}

.o-grid__item--wide {
  grid-column: span 2;
  padding-top: 50%;
}
<div class="o-container">
  <div class="o-grid">
    <div class="o-grid__item o-grid__item--wide">
      <div class="o-grid__content">
        1. 2x1
      </div>
    </div>
    <div class="o-grid__item">
      <div class="o-grid__content">
        2. 1x1
      </div>
    </div>
    <div class="o-grid__item o-grid__item--tall">
      <div class="o-grid__content">
        3. 1x2
      </div>
    </div>
    <div class="o-grid__item">
      <div class="o-grid__content">
        4. 1x1
      </div>
    </div>
    <div class="o-grid__item">
      <div class="o-grid__content">
        5. 1x1
      </div>
    </div>
    <div class="o-grid__item">
      <div class="o-grid__content">
        6. 1x1
      </div>
    </div>
  </div>
</div>


person iamdarrenhall    schedule 03.04.2017    source источник


Ответы (3)


Я создал макет ниже, используя display: grid, я использовал старый трюк padding-top, чтобы иметь плавные квадратные элементы div, но мне интересно, есть ли лучший способ сделать это с помощью CSS Grid или Flexbox.

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

В CSS Grid трюк padding-top не работает в Firefox. Спецификация указывает причину:

6.4. Поля и отступы элемента сетки

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

Процентные поля и отступы в элементах сетки могут быть разрешены:

  • их собственная ось (левый/правый процент разрешается по ширине, верхний/нижний разрешается по высоте), или,
  • встроенная ось (левый/правый/верхний/нижний процент разрешается в зависимости от ширины).

Пользовательский агент должен выбрать одно из этих двух действий.

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

Эта проблема существует и во Flexbox: Почему процентное заполнение не работает для flex-элементов в Firefox?

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

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

5.1.2. Длина области просмотра в процентах: vw, vh, vmin, vmax единиц

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

  • vw unit — равен 1% ширины исходного содержащего блока.
  • vh unit — равен 1% высоты исходного содержащего блока.
  • vmin unit — равно меньшему из vw или vh.
  • vmax unit — равно большему из vw или vh.

Вот приблизительный набросок: пересмотренный код

person Michael Benjamin    schedule 16.04.2017

Попробуйте заменить прокладку на

height: calc(25vw - 1.5rem);

Или еще лучше, примените его ко всем элементам сетки, а не только к первому:

.o-grid__item {
  box-shadow: inset 0 0 0 1px red;
  position: relative;
  height: calc(25vw - 1.5rem); /* allow for the spacing between squares */
}

.o-grid__item--tall {
  grid-row: span 2;
  height: calc(50vw - 1rem); 
}

.o-grid__item--wide {
  grid-column: span 2;
}
person Blazemonger    schedule 03.04.2017
comment
Проблема в том, что он работает только до тех пор, пока не будет достигнута ширина контейнера. - person iamdarrenhall; 03.04.2017
comment
Я не уверен, что ты имеешь в виду...? - person Blazemonger; 03.04.2017
comment
Сравните первое перо с эту ветку с вашими предложениями. Первая проблема заключается в том, что элементы div не являются квадратными, а во-вторых, они продолжают расти после того, как ширина области просмотра превышает ширину контейнера (1280 пикселей). - person iamdarrenhall; 04.04.2017
comment
Просто (1) отрегулируйте высоту с помощью calc(), чтобы отразить фактическую ширину, и (2) используйте @media screen, чтобы добавить max-height, когда вы достигнете 1280 пикселей. - person Blazemonger; 04.04.2017

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

Недостатком этого является блокировка высоты элемента, поэтому, если элемент слишком мал, его содержимое будет переполнено.

Мне нравится немного другой подход, который использует плавающий псевдоэлемент для достижения тот же результат, но также позволяет элементу увеличиваться, чтобы содержать переполнение, если это необходимо:

.o-grid__item--wide::before {
  content: "";
  float: left;
  padding-bottom: 50%;
}
.o-grid__item--wide::after {
  clear: left;
  content: " ";
  display: table;
}

Используя это внутри сетки, вы можете избавиться от объявления grid-template-rows. В противном случае, если один элемент вырастет и будет содержать переполнение, он также изменит высоту всех остальных строк сетки.

person keithjgrant    schedule 04.04.2017