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



На данный момент, по данным 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 было найдено решение, которое является более элегантным. О его выгодах Вы можете прочитать в комментариях к данной публикации.
Share post

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 6

    0

    Вместо классов photo1, photo2 и т.д. можно использовать CSS-селекторы .photo:nth-child(1), .photo:nth-child(2) и т.д… Так HTML-код будет проще.

      0
      Действительно, мне даже не пришло это в голову. Спасибо за замечание!
      +1
      А grid-template-areas был бы не удобнее в этом случае? Вместо того чтобы писать 20 правил, сделали бы одно, да еще и наглядное. Или он так не сможет?
        0
        Он так может. Но пришлось бы создать 52 (13 х 4) именованных области, а потом каждый элемент все равно бы пришлось помещать в выдленную для него область. grid-template-areas очень полезное свойство, но в данном случае (при большом количестве грид-элементов и их несиммитричного расположени) он бесполезен.
          +1
          Зачем 52? У вас же всего 19 изображений.
          grid-template-areas:
          "g01 g01 g02 g03 g04 g05 g05 g05 g05 g06 g06 g07 g08"
          "g01 g01 g09 g10 g10 g05 g05 g05 g05 g06 g06 g11 g12"
          "g13 g15 g15 g10 g10 g05 g05 g05 g05 g18 g18 g19 g19"
          "g14 g15 g15 g16 g17 g05 g05 g05 g05 g18 g18 g19 g19";
          

          Вот вся ваша сетка — сразу можно посмотреть где что расположено.

          PS. более того, если выделить в редакторе один из элементов, редактор тут же подсветит какие еще области этот элемент занимает. А в ваш вариант даже соваться страшно.
            +1
            Я это и имел ввиду. Вы создали 52 зоны, 19 из них являются уникальными.

            Но вы оказались правы. Ваш вариант намного лучше. Особенно при переопределении сетки в разных брейкпоинтах и, уже упомянутой выше, подстветки в редакторе.

            Большое спасибо за совет!

      Only users with full accounts can post comments. Log in, please.