Как создать плиточную раскладку без использования JS библиотек

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

Стандартный грид-контейнер из четырех колонок можно легко получить с помощью CSS flexbox или CSS grid. Он выглядит примерно так:

Стандартный макет сетки из 4 столбцов с CSS Flexbox

Хотя в этом подходе нет ничего плохого, как видно на изображении выше, при наличии динамического контента могут возникать большие промежутки. Существует несколько способов борьбы с избыточным пространством — ограничивать количество слов или делать столбцы одинаковой высоты.

В этом уроке я вам покажу другой подход. Он называется кирпичной кладкой или плиточной раскладкой (masonry layout). Он широко используется для галерей изображений, поскольку в большинстве случаев изображения не могут быть ограничены так же, как и текст. Если бы мы взяли тот же пример, что и выше, Masonry-раскладка выглядела бы примерно так:

4-колонная кирпичная кладка

Как видно на изображении, большие промежутки теперь изящно обработаны. Существует множество учебников в интернете о создании masonry-раскладки, но они либо рекомендуют использовать дорогие сторонние библиотеки JavaScript с избыточным кодом, либо утверждают, что Masonry-эффект можно достичь с помощью чистого CSS (без JavaScript). Хоть, теоретически, Masonry-раскладку можно создать и без JavaScript, существуют несколько важных ограничений, которые постоянно мешают ей работать! Первый метод, основанный только на CSS, использует CSS grid и работает путем нацеливания на разные дочерние элементы. Это может сработать со статическим контентом, но если вы не знаете количество элементов в сетке, у вас могут возникнуть проблемы. Есть также способ создания masonry-раскладки с помощью CSS-grid или flexbox, но это изменяет порядок элементов. Несмотря на то, что этот способ подходит для галерей изображений, где порядок самих изображений не так важен, в ситуациях, где мы хотим отобразить последние сообщения в Masonry-раскладке, этот подход не сработает. Кроме того, ради справедливости стоит отметить, что в Firefox существует новое экспериментальное свойство, которое, наконец, приводит все элементы к работе… за исключением того, что это свойство до сих пор не поддерживается в основных браузерах, за исключением Firefox, и вам необходимо включить экспериментальные функции вашего браузера, чтобы увидеть его в действии. Вся эта информация подразумевает, что в настоящее время мы застряли с использованием JavaScript для достижения masonry-раскладки. Практически все уроки в интернете советуют использовать JS библиотеки для ее достижения. Однако это совершенно не обязательно, так как вы можете постичь красивую masonry-раскладку всего несколькими строками JavaScript. Вот как это сделать:

Создание плиточной раскладки с использованием CSS и только Vanilla JS

The HTML Markup

<div class="post-container">
   <div class="post-inner">
      <!--You Need a List of Articles Here-->
      <article class="post hentry">
         Article One
      </article>
   </div>
</div>

Мы будем использовать вышеуказанную разметку HTML. Вы можете использовать любые классы, которые вам нравятся, но важно, чтобы элементы asonry-раскладки были обернуты в контейнер (в нашем случае это div с классом «post-inner»). Также нам понадобится дополнительная оболочка, чтобы всё сработало (здесь она называется «post-container»).

CSS

Наш CSS-код позволяет создавать многоколоночный макет:

@media (min-width: 54rem) {

	.masonry-layout {
		box-sizing: border-box;
		--columns: 1;
		--gap: 2rem;
		display: grid;
		grid-template-columns: repeat(var(--columns), 1fr);
		grid-gap: var(--gap);
		padding: 2rem;
	}

	.masonry-layout > div > img,
	.masonry-layout > div > div {
		width: 100%;
		margin-bottom: 2rem;
	}

	.masonry-layout.columns-1 {
		--columns: 1;
	}

	.masonry-layout.columns-2 {
		--columns: 2;
	}

	.masonry-layout.columns-3 {
		--columns: 3;
	}

	.masonry-layout.columns-4 {
		--columns: 4;
	}
}

Не изменяйте здесь этот CSS, он вам понадобится для работы js-кода, который мы собираемся добавить.

JS

Вот JavaScript-код, который мы будем использовать.

const fecthMasonry = function( container, items, columns ) {
	const containerElement = document.getElementsByClassName( container )[ 0 ] || '';
	if ( ! containerElement ) {
		return;
	}
	const wrapperElement = containerElement.parentNode;
	const masonryElements = document.querySelectorAll( '.' + items );
	containerElement.parentNode.removeChild( containerElement );
	const newElement = document.createElement( 'div' );
	newElement.setAttribute( 'id', container );
	newElement.classList.add( 'masonry-layout', 'columns-' + columns );
	wrapperElement.appendChild( newElement );
	let countColumn = 1;
	for ( let i = 1; i <= columns; i++ ) {
		const newColumn = document.createElement( 'div' );
		newColumn.classList.add( 'masonry-column-' + i );
		newElement.appendChild( newColumn );
	}
	for ( let i = 0; i < masonryElements.length; i++ ) {
		const col = document.querySelector( '#' + container + ' > .masonry-column-' + countColumn );
		col.appendChild( masonryElements[ i ] );
		countColumn = countColumn < columns ? countColumn + 1 : 1;
	}
};
/* Pass data to generate masonry layout */
fecthMasonry( 'framework-post-inner', 'post', 4 );

Первая функция fetchMasonry — вспомогательная, которая получает данные, необходимые для создания masonry-раскладки. Именно здесь происходит волшебство, и вам не нужно ничего менять. Вторая функция — это место, где вы указываете, какие DOM-элементы отображать в Masonry-раскладке. Мы передаем три параметра. Первый — имя класса родительского элемента. В нашем случае это framework-post-inner. Второй параметр — класс элементов внутри Masonry-раскладки. Финальный параметр — сколько столбцов вы хотите иметь. Вы можете выбрать от 2 до 4.

Вот и все! Если вам понравилась эта статья, поделитесь ею, ну а я желаю вам удачи в вашем следующем проекте!

Source: Masonry Layout JS Vanilla