. Плиточная раскладка на чистом CSS
Плиточная раскладка на чистом CSS

Плиточная раскладка на чистом CSS

Плиточная раскладка является одной из самых популярных. Не знаете, что это такое? Вспомните о Pinterest, Windows’ Metro и т.д. Если объяснять это на словах, то представьте сумасшедший эффект соединения блоков разных размеров в эстетически упорядоченном, часто шахматном порядке.

Плиточная раскладка не является чем-то новым. Так почему мы говорим о ней сейчас? Ведь есть же отличные решения для получения эффекта плиточной раскладки? Есть. Но можем ли мы продвинуть решение на чистом CSS чуть дальше? Можем ли мы использовать флексбокс для достижения требуемого эффекта?

Это мы и рассмотрим, но если вам лень читать весь текст, можете ограничиться изучением кода на github и jsbin.

Простейшая плитка

Начнем с базовой раскладки. Представьте примерно такую структуру DOM для нашей раскладки:

Мы хотим добавить колонки к нашему контенту. Сможем ли мы добиться хотя бы простого эффекта плиточной раскладки на основе нашей структуры DOM с минимальными усилиями, используя только колонки CSS3 или флексбокс?

Что такое многоколоночная раскладка и флексбокс?

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

Пробуем многоколоночную раскладку

В CSS для многоколоночных макетов есть свойства column-count и column-gap . Это позволяет сравнительно легко сделать базовую плиточную раскладку. Учтите, что в раскладке важно использовать свойство break-inside на блоках с контентом. Это помешает разбитию и распределению содержимого блоков между колонками. CSS для этой стартовой точки будет следующий:

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

Пробуем флексбокс

Можем ли мы добиться того же результата с помощью флексбокса? Это не настолько просто, как в случае с многоколоночной раскладкой. Я столкнулся с проблемами, когда решал ту же задачу с флексбоксом.

С первой попытки я собирался имитировать колоночную раскладку при помощи flex-direction: column . Проблема с использованием значения column заключается в том, что вам надо задать высоту раскладки, перед тем как оборачивать столбцы. Но это неидеальный вариант, так как любое переполнение ведет к горизонтальному скроллингу. Так что вы или смиритесь со скроллингом, или у вас должна быть возможность регулировать высоту раскладки, в таком случае вы сможете красиво все располагать. Если вы работаете с динамическим содержимым, размер которого варьируется, вам придется постоянно заниматься выравниванием при его добавлении. Это явно не соответствует смыслу флексбокса.

Рассмотрим следующий пример:

Этот код дает следующий результат. Обратите внимание на горизонтальный скроллинг, который нам совершенно не нужен.

Другой подход это использование flex-direction: row . Он также не совсем работает. Вы можете задать количество колонок, ограничивая ширину элементов в раскладке, но обертывание приведет к появлению ненужного пустого пространства или к необходимости выравнивания ширины всех элементов на основе align-items . Ни тот, ни другой результат нельзя назвать желательным. Вы можете оценить результат использования flex-direction: row с align-items: flex-start здесь.

Если вы готовы сильнее контролировать разметку и ее структуру, вы можете добиться желаемого эффекта с флексбоксом. Рассмотрим следующую структуру:

Рассмотрим этот код. Наши панели в идеале также должны быть блоками. Поэтому мы проведем небольшой рефакторинг.

У нашей простейшей плитки по прежнему есть потенциал. Мы сделаем ее круче и флексбокс поможет нам в этом.

Вложенные кластеры с контентом

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

Кластеры это по сути вложенные раскладки, с вертикальным или горизонтальным обтеканием. Флексбокс отлично подходит для этого.

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

Но это не совсем правильный подход. Задание размеров подойдет не для каждого случая. Лучше будет ввести колонкоподобные контейнеры, которые мы обсуждали ранее. Рассмотрим следующий вариант:

Поток кластеров может быть как горизонтальным, так и вертикальным. Если поток кластера горизонтальный, мы задаем колонки с сегментами, обтекающими вертикально и наоборот. Это изменяется с помощью flex-direction . Сегменты кластера увеличиваются/уменьшаются, заполняя пустое пространство, а кластеры работают как блоки.

Если нам нужен более тонкий контроль над сегментами кластеров, мы можем создать служебные классы, чтобы задать в процентах flex-basis . Нам не нужен служебный класс “полный размер”, так как мы можем просто включить один элемент в контейнер и он займет всю ширину или высоту. Для “половинки” мы зададим flex-basis: 50% . Достоинством такой имплементации будет возможность поместить любое количество колонок или рядов соответственно.

Как может выглядеть код? Как вариант:

Вы можете увидеть код в действии здесь. Вложенные кластеры это самая сложная часть для понимания, но с их помощью мы можем проще решать некоторые задачи.

Темизация и панели с изображениями

Наша задача это изоляция стилей структуры раскладки от темизирующих стилей. Это облегчает использование кода в других проектах. Если вы смотрели демонстрации кода в этой статье, вы заметили, что у панелей с контентом закругленные углы. Это сделано путем добавления минимальной темизации.

Как насчет изображений? Достаточно часто требуется вывести изображения как отдельные панели в плитке. Если мы поместим изображение внутри панели, на него будут влиять пэддинги, заданные для нашей темы. Так почему бы нам не использовать для изображения класс masonry-layout__panel-content с модификатором?

Это почти то, что надо. Надо добавить немного темизации, специфичной для изображений и будет самое то.

Проверить, как это выглядит, можно в демо. Примечание: так как имена классов имеют тенденцию раздуваться, в примерах кода используются аббревиатуры. Например, masonry-layout становится ml , masonry-layout-cluster становится ml-clstr . Заглушки для изображений выводятся желтым цветом.

Анимация панелей при наведении

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

Ну и новый блок для переворачивающихся карт:

Используя трансформации и переходы CSS, мы добавим анимацию при наведении для наших панелей, которые будут переворачиваться и показывать обратную сторону.

Вы можете увидеть этот эффект на первом элементе раскладки в демо.

Мы не ограничены переворачивающимися панелями. Мы можем добавлять различные эффекты к панелям при фокусе. В итоговом коде я еще добавлю кое-какие эффекты.

Добавляем отзывчивость

Если вы дошли до этого раздела, то наверняка заметили, что наша плиточная раскладка совсем не торт на маленьких экранах. Сделаем ее отзывчивой. Что мы хотим получить? При увеличении экрана мы хотим увеличивать число колонок в макете. А при уменьшении экрана, кроме уменьшения числа колонок мы будем разбирать кластеры, позволяя их сегментам занимать всю ширину раскладки. Разумеется, мы будем разрабатывать наши стили, начиная с мобильных. Вот пример с отзывчивым количеством столбцов:

Для вложенных кластеров мы будем игнорировать горизонтальный поток и flex-basis на маленьких экранах. Мы хотим, чтобы кластеры распадались и их сегменты занимали всю зону видимости, вне зависимости от того, являются ли они колонками или рядами.

Демонстрацию этого кода можно посмотреть здесь.

Используем препроцессор

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

Итак, для сравнения итоговый код CSS из примера в этой статье (без вендорных префиксов и темизации, в именах классов использованы аббревиатуры).

Заключение

Мы рассмотрели методику создания плиточной раскладки на чистом CSS. Мне действительно нравится результат. Плитка на чистом CSS может работать, хотя она и не безупречна. Я вижу потенциальные проблемы. Например, сложности будут,если вы хотите вывести блог, отсортированный по дате, это потребует дополнительных размышлений. Одним из решений будет использование колонок с последующим заполнением их в хронологическом порядке. В результате последняя запись будет в первом столбце, предыдущая во втором и так далее.

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

📎📎📎📎📎📎📎📎📎📎