Распространенные шаблоны компоновки CSS Flexbox с примерами кода

Теоретически довольно просто использовать flexbox (Flexible Box Module) для создания сложных макетов, но я часто обнаруживал, что добавляю display: flexк элементу, а затем быстро тратил целую вечность, пытаясь понять, как заставить что-либо вести себя так, как я ожидаю. .

шаблоны компоновки CSS Flexbox

Если вы чем-то похожи на меня: вот список из 10 примеров макетов flexbox с CSS, которые вы можете скопировать и вставить, чтобы начать создавать свои собственные макеты. Мы рассмотрим эти основные шаблоны макета (щелкните, чтобы перейти к примеру):

Растянуть все
Растяжка посередине
Переменная сетка
сетка 3x3
3х3 (1:1)
3х3 (16:9)
Вертикальные полосы
Турники
Вертикальный стек
Каменная кладка

В каждом примере предполагается, что ваш HTML содержит элемент с классом, containerкоторый затем содержит несколько дочерних элементов, каждый из которых имеет класс item(количество дочерних элементов зависит от примера):

<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>

</div>

Растянуть все, фиксированный интервал

Самый простой паттерн flexbox: заставить несколько блоков растянуться и заполнить всю ширину их родительского элемента. Все, что вам нужно сделать, это установить display: flexконтейнер и flex-growзначение выше 0для дочерних элементов:

.container {
  display: flex;
}

.item {
  flex-grow: 1;
  height: 100px;
}

.item + .item {
  margin-left: 2%;
}

Мы используем +селектор только для добавления промежутков между парами элементов (по сути, просто пропуская левое поле для первого элемента в списке).

Увеличение flex-growувеличивает количество пространства , на которое может растягиваться элемент, по сравнению с любым другим элементом. Если мы установим flex-growздесь 2средний элемент, мы разделим доступное пространство на 6 блоков (по 1 блоку для каждого элемента плюс 1 дополнительный для среднего элемента, 1+1+2+1+1). Средний элемент получает два фрагмента ( flex-grow: 2), а все остальные элементы получают один фрагмент ( flex-grow: 1).

Растяжка посередине, фиксированный интервал

Обычный шаблон приложений и веб-приложений заключается в создании верхней панели, в которой мы хотим растянуть только средний элемент, но оставить самые правые и самые левые элементы фиксированными. Если мы просто хотим, чтобы один элемент растягивался, мы можем установить фиксированную ширину (например 100px) для элемента, который должен оставаться статичным, и flex-grow: 1для элемента, который должен растягиваться:

.container {
  display: flex;
}

.item {
  height: 100px;
  width: 100px; /* A fixed width as the default */
}

.item-center { 
  flex-grow: 1; /* Set the middle element to grow and stretch */
}

.item + .item { 
  margin-left: 2%; 
}

Даже если средний элемент здесь имеет определение width, 100pxон flex-growрастянется, чтобы занять все доступное пространство.

Переменная сетка

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

Для этого нам необходимо:

  1. Установите flex-wrap: wrapв контейнере (иначе все itemsбудет отображаться в одной строке)
  2. Установите justify-content: space-betweenконтейнер, чтобы создать пространство только между элементами (а не между краем родительского элемента и элементами)
  3. Установите для каждого элемента widthзначение 49%(или что-то подобное, равное или меньшее 50%)
  4. Установите каждый третий элемент так, widthчтобы 100%он заполнил всю эту строку. Мы можем выбрать каждый третий элемент в списке с помощью nth-child()селектора.
.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.item {
  width: 48%;
  height: 100px;
  margin-bottom: 2%;
}

.item:nth-child(3n) {
  width: 100%;
}

Если вы хотите, чтобы первая строка была на всю ширину, а два следующих элемента разделяли строку, обратите внимание, что вы не можете писать .item:nth-child(1n) { width: 100% }— это будет нацелено на все элементы. Вы должны настроить таргетинг на первый элемент, выбрав каждый третий элемент, а затем отступив на два элемента: .item:nth-child(3n-2) { width: 100% }.

сетка 3x3

Мы можем создать сетку 3x3, задав предпочтительную flex-growширину для всех дочерних элементов (здесь это делается с помощью сокращения: ). Поля между элементами — это остатки от каждой строки, т.е. (100%-32x3)/2=2%. Я сопоставил поля ( ), чтобы добиться равномерного расстояния между всеми элементами:0flex-basisflexflex: 0 32%margin-bottom: 2%

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.item {
  flex: 0 32%;
  height: 100px;
  margin-bottom: 2%; /* (100-32*3)/2 */
}

Вы можете изменить, flex-basisчтобы увеличить или уменьшить количество элементов в каждой строке. flex: 0 24%поместит 4 элемента в каждую строку, flex: 0 19%поместит 5 элементов в каждую строку и так далее.

Сетка 3x3, ограниченные пропорции (1:1)

Мы можем создать сетку, полную элементов с ограниченными пропорциями, используя несколько хитрый paddingприем CSS. Если мы используем %при установке paddingэлемента , то в этом случае paddingон устанавливается относительно родительского элемента этого элемента . Мы можем использовать этот эффект для создания квадрата, установив элемент и на одно и то же значение (и фактически установив элемент с помощью ):width.containerwidthpadding-bottomheightpadding-bottom

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.item {
  width: 32%;
  padding-bottom: 32%; /* Same as width, sets height */
  margin-bottom: 2%; /* (100-32*3)/2 */
  position: relative;
}

Поскольку мы создали элемент, который фактически состоит только из заполнения, и для содержимого не осталось места, нам нужно установить position: relativeв .itemэтом примере и добавить дочерний элемент с помощью position: absolute, и использовать этот элемент для «сброса» холста. и добавить контент.

Сетка 3х3, ограниченные пропорции (16:9)

Чтобы изменить пропорции элементов, все, что вам нужно сделать, это изменить пропорции widthи padding-bottomна .item. Изменение widthповлияет на количество элементов в каждой строке, чтобы не повлиять на структуру сетки, которую мы можем, например, изменить padding-bottomдля 18%создания прямоугольников 16:9 (эквивалентно 32:18).

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.item {
  width: 32%;
  padding-bottom: 18%; /* 32:18, i.e. 16:9 */
  margin-bottom: 2%; /* (100-32*3)/2 */
}

График: вертикальные столбцы

Если вы хотите использовать flexbox для создания простой визуализации графика, все, что вам нужно сделать, это установить align-items контейнер flex-endи определить height для каждого столбца. flex-end убедитесь, что столбцы привязаны к нижней части графика.

.container {
  display: flex;
  height: 300px;
  justify-content: space-between;
  align-items: flex-end;
}

.item { width: 14%; }
.item-1 { height: 40%; }
.item-2 { height: 50%; }
.item-3 { height: 60%; }
.item-4 { height: 20%; }
.item-5 { height: 30%; }

График: горизонтальные полосы

Используя ту же технику, что и для вертикальных полос, мы можем просто добавить flex-directionзначение containerсо значением, column чтобы создать набор горизонтальных полос. flex-direction может иметь значение row (по умолчанию) или column, где a row проходит горизонтально (→), а a — column вертикально (↓). Вы также можете изменить направление обоих, используя row-reverse(←) и column-reverse (↑) соответственно.

.container {
  display: flex;
  height: 300px;
  justify-content: space-between;
  flex-direction: column;
}

.item { height: 14%; }
.item-1 { width: 40%; }
.item-2 { width: 50%; }
.item-3 { width: 60%; }
.item-4 { width: 20%; }
.item-5 { width: 30%; }

Вертикальный стек (по центру)

Чтобы создать вертикальный стек и заставить элементы работать сверху вниз, все, что нам нужно сделать, это изменить flex-direction значение по умолчанию row на column:

.container {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.item {
  height: 40px;
  margin-bottom: 10px;
}

Кладка (или мозаика)

1
2
3
4
5
6
7
8
9
10

Вы, наверное, видели макеты каменной кладки (или мозаики) по всему Интернету, но вполне вероятно, что все они были основаны на Masonry или аналогичной библиотеке JavaScript. Flexbox может показаться отличным кандидатом для окончательного создания этого макета только с помощью CSS, и это, безусловно, возможно, но это удивительно хакерски.

Одна из основных проблем создания макета каменной кладки с помощью flexbox заключается в том, что для того, чтобы элемент влиял на позиционирование элемента над и под ним, нам нужно изменить flex-directionконтейнер на column, что заставляет элементы перемещаться сверху вниз. Это создает макет, который выглядит великолепно и похож на эффект каменной кладки, но может сбивать с толку пользователей; это создает неожиданный порядок элементов. Если вы читаете слева направо, элементы будут казаться перетасованными и появляться в случайном порядке, например, 1, 3, 6, 2, 4, 7, 8 и т. д.

К счастью, мы можем использовать order свойство для изменения порядка отображения элементов. Мы можем объединить это свойство с некоторым умным использованием nth-child() селектор для динамического упорядочивания элементов в зависимости от их первоначального порядка. Если мы хотим создать макет с тремя колонками, мы можем разделить все элементы на три "группы", например, так:

/* Re-order items into rows */
.item:nth-child(3n+1) { order: 1; }
.item:nth-child(3n+2) { order: 2; }
.item:nth-child(3n)   { order: 3; }

/* Force new columns */
.container::before,
.container::after {
  content: "";
  flex-basis: 100%;
  width: 0;
  order: 2;
}

Я написал another post that explains in detail how this works and why. Это позволит установить order на 1 для 1-го элемента, 4-го элемента, 7-го элемента и т.д. Элементы с одинаковыми order значения будут упорядочены по возрастанию в соответствии с порядком исходного кода, или с тем, какое значение было set сначала, поэтому в данном примере мы создаем три набора, упорядоченных следующим образом: 1, 4, 7, 10 (3n+1) с order: 1, 2, 5, 8 (3n+2) c order: 2, и 3, 6, 9 (3n) с order: 3. Эти три группы представляют собой три колонки. Если сложить их вместе, то порядок станет следующим 1, 4, 7, 10, 2, 5, 8, 3, 6, 9.

Если мы позаботимся о том, чтобы отобразить каждую из этих групп как один столбец (не больше и не меньше), это создаст иллюзию, что элементы вернулись к своему первоначальному порядку, когда вы читаете слева направо. Если мы визуально разберем сетку как строки, то первая строка будет содержать первый элемент из каждой группы (1, 2, 3), второй ряд будет содержать второй элемент из каждой группы (4, 5, 6), и так далее. Затем мы вставляем между колонками элементы, которые занимают 100 % высоты родительской колонки, which force the columns to line break и не сливаться случайно с соседними колонками. Вот полный фрагмент CSS:

.container {
  display: flex;
  flex-flow: column wrap;
  align-content: space-between;
  height: 680px;
}

.item {
  width: 32%;
  margin-bottom: 2%; /* (100-32*3)/2 */
}

/* Re-order items into rows */
.item:nth-child(3n+1) { order: 1; }
.item:nth-child(3n+2) { order: 2; }
.item:nth-child(3n)   { order: 3; }

/* Force new columns */
.container::before,
.container::after {
  content: "";
  flex-basis: 100%;
  width: 0;
  order: 2;
}

Визуально это позволяет добиться чего-то очень близкого к эффекту каменной кладки. Как влияет порядок вкладок? К счастью, никак. order изменяет только визуальное представление объектов, но не порядок вкладок, поэтому вкладки в сетке будут работать как положено.

Если вы хотите сделать макет кладки с более чем тремя колоннами (или хотите лучше понять, как это работает), рекомендую прочитать the dedicated post on how to create masonry layouts with CSS.

Источники:
  1. машинный перевод
  2. Common CSS Flexbox Layout Patterns with Example Code

Комментарии