Статьи

Использование современного CSS для создания адаптивной сетки изображений

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

Подробнее о адаптивных макетах. Посмотрите наш скринкаст Создание макетов с несколькими столбцами во Flexbox .

Построение адаптивного макета

Для начала предположим, что на больших экранах наша галерея должна выглядеть примерно так:

Требуется макет для больших экранов

На экранах меньшего размера (т. Е. <50em) он должен выглядеть следующим образом:

Требуется макет для маленьких экранов

Разметка проста:

<div>
  <a href="path-to-the-image">
    <figure>
      <img src="path-to-the-image" alt="">
    </figure>
  </a>

  <!-- other anchors here ... -->

</div>

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

  • Я хочу макет с 2 колонками на средних экранах и меньше (то есть <50em), и макет с 4 колонками на больших экранах (50em или выше).
  • Расстояние между столбцами должно быть 8 пикселей.

Использование inline-блока

Сначала я буду использовать метод display:inline-block Рассмотрим следующий CSS:

 div {
  font-size: 0;
}

a {
  font-size: 16px; 
  display: inline-block;
  margin-bottom: 8px;
  width: calc(50% - 4px);
  margin-right: 8px;
}

a:nth-of-type(2n) {
  margin-right: 0;
}

@media screen and (min-width: 50em) {
  a {
    width: calc(25% - 6px);
  }

  a:nth-of-type(2n) {
    margin-right: 8px;
  }

  a:nth-of-type(4n) {
    margin-right: 0;
  }
}

Вот объяснение того, что я сделал:

По умолчанию между элементами inline-block . Один из способов переопределить это — установить размер шрифта родительского элемента на ноль. Для этого также может потребоваться сброс размера шрифта любых дочерних элементов (в нашем случае это не обязательно).

На маленьких экранах у меня есть макет с двумя столбцами, и я указываю 8px пространства между столбцами.

Ширина наших столбцов рассчитывается следующим образом:

  • Общее пространство между столбцами в строке = 1 * 8px => 8px. Производное значение составляет 8px, а не 16px, потому что я удаляю правое поле для каждого второго столбца на маленьких экранах.
  • Ширина каждого столбца = calc (50% — 4px). Значение 4px, полученное путем вычисления: общее пространство между столбцами в строке / количество столбцов в строке (8px / 2 => 4px).

2 колонки

На больших экранах у меня есть макет с 4 колонками, и я указываю пространство 8px между колонками Итак, ширина наших столбцов рассчитывается следующим образом:

  • Общее пространство между столбцами в строке = 3 * 8px => 24px. Опять же, производное значение составляет 24px, а не 32px, потому что я удаляю правое поле для каждого четвертого столбца.
  • Для ширины столбца я использую calc (25% — 6px). Значение 6px получено путем простого вычисления: общее пространство между столбцами в строке / количество столбцов в строке (24px / 4 => 6px).

4 колонки

Посмотрите демонстрацию CodePen для метода встроенного блока здесь

Использование Flexbox

Решение выше работает довольно хорошо, но есть некоторые недостатки. Чтобы продемонстрировать один недостаток, давайте предположим, что каждое изображение также содержит подпись.

Рассмотрим эту слегка обновленную разметку:

 <div>
  <a href="path-to-the-image">
    <figure>
      <img src="path-to-the-image" alt="">
      <figcaption>Some text here</figcaption>
    </figure>
  </a>

  <!-- other anchors here ... -->

</div>

Вот новая версия нашей галереи на больших экранах:

Большой экран с надписями

Просмотрите демонстрацию CodePen, используя встроенный блок с подписями

Результат не так привлекателен, потому что элементы сетки имеют разную высоту. Мы можем исправить это с помощью flexbox, современного метода компоновки, который позволит нам преодолеть многие распространенные проблемы компоновки (например, разрыв по умолчанию между элементами inline-block Чтобы активировать этот метод, мне просто нужно обновить CSS родительского элемента (гибкий контейнер):

 div {
  display: flex;
  flex-wrap: wrap;
}

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

Большой экран с надписями, улучшено

Просмотрите демонстрацию CodePen, используя flexbox с улучшенными заголовками

На данный момент, есть еще одна вещь, которую я должен уточнить. Flexbox предоставляет свойство justify-content которое выравнивает элементы flex вдоль главной оси текущей строки контейнера flex. Однако обратите внимание, что это свойство не определяет значение, которое позволит нам построить желаемый макет галереи. Например, значение space-between

Сетка с пробелом между значением

В то время как свойство space-around

Сетка с пространственным значением

В обоих случаях последние два элемента неловко распределяются по последнему ряду. CSS для этого метода будет выглядеть так:

 div {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between; /* or space-around */
} 

a {
  display: inline-block;
  margin-bottom: 8px;
  width: calc(50% - 4px);
}

@media screen and (min-width: 50em) {
  a {
    width: calc(25% - 6px);
  }
}

В этом случае я не назначал свойство margin-right Это происходит потому, что в зависимости от значения свойства justify-content

Просмотрите демонстрацию CodePen, используя свойство justify-content

Вывод

В этом посте было рассмотрено несколько методов управления расстоянием между столбцами сетки в адаптивной сетке изображений. Хотя метод inline-block является достаточным, flexbox делает его намного проще и удобнее, особенно в сочетании с функцией calc()

Получите максимум от макетов Flexbox и посмотрите наш скринкаст по созданию макетов с несколькими столбцами во Flexbox .

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