DevGang
Авторизоваться

Создание сетки с помощью CSS Grid 

В недавнем проекте я наткнулся на изящный способ создания макета сетки, используя CSS Grid и немного javascript. Сначала я думал об использовании чего-то вроде Masonry.js или Isotope, но это было немного излишне. Что хорошего в этом подходе, он очень гибкий и не опирается ни на какие фреймворки! Я постараюсь сделать этот пост коротким и приятным, чтобы вы могли сами приступить к работе и насладиться этим трюком.

Давайте начнем с добавления HTML в файл index.html.

Здесь мы создали простую сетку с некоторыми элементами. Примечание: padding-top и lazyloaded предназначены для предотвращения скачка контента при загрузке ваших изображений.

Теперь давайте добавим немного CSS

.grid {
   display: grid;
   grid-row-gap: 0px;
   grid-column-gap: 40px;
   grid-template-columns: repeat(
       auto-fit,
       minmax(300px, var(--template-columns, 1fr))
   );
   grid-auto-rows: 5px;
   width: 80%;
   max-width: 1080px;
   margin: 0 auto;
   padding-bottom: 40px;
}

.grid-item {
   grid-row-end: var(--row-span, span 40)
   padding-bottom: 40px
}

img {
   width: 100%;
   height: auto
}

@media (max-width:800px) {
   .grid {
       width: 90%;
       grid-template-columns: 1fr;
       grid-auto-rows: auto
   }

   .grid-item {
       grid-row-end: auto
   }
}

По сути, то, что мы здесь делаем с .grid, говорит о том, что мы хотим отобразить адаптивную сетку элементов. minmax(300px, var(-template-columns, 1fr)) делает для нас большую работу, создавая повторяющиеся столбцы с минимальной шириной 300px и максимальной шириной 1fr (fr - дробная единица), когда ширина столбца падает ниже минимального значения, макет перетасовывается, а количество столбцов уменьшается.

Здесь следует отметить некоторые вещи, grid-auto-rows: 5px которые позволят нам создать макет каменной кладки. Некоторые стилистические предпочтения, которые у меня есть, это использовать grid-gap-columns и padding-bottom чтобы создавать промежутки между элементами. Причина этого в том, что я обнаружил, что интервал стал заметно несовместимым, если grid-gap-rows также используется.

const grid = document.querySelector('.grid');
const gridItems = document.querySelectorAll('.grid-item');
const rowSize = 5;
const setColumns = value => grid.style.setProperty('--template-columns', value);

gridItems.length <= 2 ? setColumns(`0.333fr`) : setColumns(`1fr`);

const positionGridItems = () => {
   gridItems.forEach((x, i) => {
       if (document.body.clientWidth < 711) {
           x.style = ''
           return
       } else {
           const rowSpan = Math.ceil(
               gridItems.offsetHeight) / rowSize
           )
           x.style.setProperty('--row-span', `span ${rowSpan}`)
       }
   });
};

function debounce(func, wait, immediate) {
   var timeout
   return function() {
       var context = this,
           args = arguments
       var later = function() {
           timeout = null
           if (!immediate) func.apply(context, args)
       }
       var callNow = immediate && !timeout
       clearTimeout(timeout)
       timeout = setTimeout(later, wait)
       if (callNow) func.apply(context, args)
   }
};

document.addEventListener('DOMContentLoaded', event => {
   positionGridItems()
});

window.addEventListener('resize', debounce(positionGridItems, 20));

Теперь здесь происходит вся магия. Сначала мы получаем элементы DOM сетки и его элементов, мы устанавливаем значение rowSize (которое эквивалентно значению grid-auto-row в нашем файле CSS). Мы создаем функцию setColumns, которая изменяет переменную grid-template-columns, если имеется менее трех элементов (полная строка), чтобы поддерживать размеры элементов сетки.

В нашей функции positionGridItems мы выполняем цикл gridItems, если в браузере удаляются встроенные стили размером менее 711 пикселей. Что-нибудь выше 711px мы получаем высоту каждого элемента и делим его на наше значение rowSize. Затем мы устанавливаем нашу переменную --row-span, которая является значением нашего свойства grid-row-ends. И это почти вся тяжелая работа! Затем мы переходим к созданию функции debounce (взятой из поста Дэвида Уолша) и затем вызываем нашу функцию positionGridItems для события DOMContendLoaded. Мы вызываем ее на событии DOMContentLoaded, чтобы предотвратить мерцание контента. Затем, чтобы завершить все это, мы добавляем слушатель debounce событий для повторного вызова функции при изменении размера браузера.

#JavaScript #CSS #HTML
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

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

Попробовать

В этом месте могла бы быть ваша реклама

Разместить рекламу