Pull to refresh

Создание несимметричной сетки с помощью Grid Layout

Reading time 3 min
Views 16K


На данный момент, по данным Can I Use, 84% браузеров поддерживает Grid Layout. С каждым месяцем это число растет. А ведь буквально недавно этот модуль находился за флагом. Поэтому если Вы еще не знакомы с теми возможностями, которые он предоставляет, то самое время это исправить.

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

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

<div class="container">
  <div class="photo photo1"></div>
  <!-- Остальные элементы -->
  <div class="photo photo20"></div>
</div>

Наш родительский элемент попросим вести себя как джентльмен грид-контейнер с сеткой 13 на 4, где каждая клетка является квадратом со стороной 75 и отступами по 5 пикселей. Для наглядности я добавил фоновый цвет каждому блоку, чтобы Вы видели распределения блоков в контейнере. Наши двадцать элементов расположились в ячейки слева направо. Если вы откроете инструмент разработчика, то увидите остальные пустующие клетки. Дальше Вы поймете, для чего мы их создали.

Распределение элементов в грид-контейнере



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

.photo1 {
  /* от какой строки */
  grid-row-start: 1;
  /* до какой строки */
  grid-row-end: 3;
  /* от какого столбца */
  grid-column-start: 1;
  /* до какого столбца */
  grid-column-end: 3;
}

Выглядит громоздко. Вам не кажется?

.photo1 {
  grid-row: 1 / 3;
  grid-column: 1 / 3;
}

Уже лучше, но можно еще короче.

.photo1 {
  grid-area: 1 / 1 / span 2 / span 2;
}

Вы разумеется заметили, что мы еще заменили тройки на span 2. Это сделано для того, чтобы не считать треки. Мы просто говорим браузеру — через какое количество клеток элемент будет протянут. А теперь нам нужно сделать это для каждого блока. Кстати, если не указывать конечную позицию, то элемент будет занимать ровно одну клетку.

После этого добавим элементам фоновое изображение, которое будет масштабироваться с сохранением пропорций.

.photo {
  background-size: cover;
}

.photo1 {
  background-image: url(...);
}



Наглядная нумерация треков. Ах да, вы можете считать их с конца, только перед значением нужно не забыть указать минус.
Такую же операцию мы проведем для следующего брейкпоинта, где наша галерея будет иметь размеры 10 на 5. Все, что мы сделали это — поменяли значение свойства grid-area у элементов и добавили одно изображение из-за то, что при переопределении сетки у нас образовалась пустая область. К сожалению, при создании media-выражения нельзя воспользоваться функцией calc (на момент написания статьи эта возможность реализована только в Chrome 66, Firefox 59 и Opera 53), поэтому расчеты приведены в комментариях к коду. Считается это так: сумма ширины элемента и его отступа умноженное на количество колонок в предыдущем брейкпоинте.

/* (75px + 5px) * 13 columns = 1040px */
@media (max-width: 1040px) {
  .container {
    grid: repeat(5, 75px) / repeat(10, 75px);
  }

  /* Здесь будет новое определение позиций для остальных элементов */
  
  .photo20 {
    grid-area: 4 / 9 / span 2 / span 2;
  }
}


На самом последнем брейкпоинте все наши изображения будут одного размера, а, значит будут занимать ровно одну клетку. Для реализации такого поведения мы переопределим количество элементов в контейнере на 20 и установим классу photo (данный класс имеется у каждого изображения) свойство grid-area на значение по умолчанию — auto. Тем самым, мы сбросили параметры, заданные в предыдущем брейкпоинте. Теперь наши блоки автоматически распределяются по клеткам слева направо.

/* (75px + 5px) * 10 columns = 800px */
@media (max-width: 800px) {
  .container {
    grid: repeat(4, 75px) / repeat(5, 75px);
  }

  .photo {
    grid-area: auto / auto;
  }
}


Заключение


Как видите, новый модуль CSS довольно гибок и прост в обучении. Разумеется, я не воспользовался в этой статье всеми возможностями, которые он предоставляет. Но уже на данном примере наглядно продемонстрирована мощь этого инструмента. Надеюсь, что для Вас это станет отрывной точкой в изучении Grid Layout, и Вы будете готовы к его использованию, как только ваш блог/сайт сможет себе позволить прекратить поддержку старых браузеров.

UPD: Благодаря пользователю Loki3000 было найдено решение, которое является более элегантным. О его выгодах Вы можете прочитать в комментариях к данной публикации.
Tags:
Hubs:
+6
Comments 6
Comments Comments 6

Articles