Создание гибких макетов с помощью Flexbox CSS

Создание гибких макетов с помощью Flexbox CSS

От автора: до появления CSS Grid был Flexbox (который официально известен как CSS Flexible Box Layout Module). Flexbox был разработан для управления макетом в одном направлении — строке (flex-direction: row или row-reverse) или столбце (flex-direction: column или column-reverse). Это контрастирует с сеткой, которая учитывает строки и столбцы.

Базовый гибкий макет создать просто: добавьте для родительского элемента display: flex или display: inline-flex. Эти значения display зададут контекст форматирования Flex для дочерних элементов этого элемента. Как и в случае с сеткой, flex и inline-flex задают внутренний режим отображения. Мы устанавливаем эти значения для контейнера, который ведет себя как блочный или встроенный элемент. Затем потомки этого контейнера располагаются в соответствии с правилами flex-макета.

Примечание. Для более старых версий браузеров на основе Blink, таких как Chrome (≤ 28) и WebKit, таких как Safari (≤8), требуется вендорный префикс. Если ваш проект по-прежнему поддерживает эти браузеры, вам необходимо использовать display: -webkit-flex или display: -webkit-inline-flex. Старые версии Firefox (≤21) также требуют префикса. Используйте для поддержки этих браузеров -moz-flex и -moz-inline-flex.

При добавлении display: flex или display: inline-flex для родительского элемента, его прямые дочерние элементы становятся flex-элементами, как показано на изображении ниже. Flex-элементами могут быть дочерние элементы или непустые текстовые узлы. Например, разметка ниже генерирует три ячейки flex-элементов, каждая из которых ведет себя в соответствии с правилами flex-компоновки:

<div style="display: flex"> <span>This text is contained by a SPAN element.</span> <b>This text is contained by a B element.</b> This text node is still a flex item.
</div>

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

Список с display: flex, примененным к родительскому элементу ul

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

Новый компонент медиа-объектов

Возьмем следующий код медиа-объекта:

<div class="media__object"> <img src="video-thumb1.jpg"> <div class="media__object__text">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
</div>

До Flexbox мы могли бы связать предыдущую разметку со следующим CSS:

.media__object img { float: left; height: auto; width: 150px;
}
.media__object__text { padding-left: 170px;
}
/* Давайте используем хак clearfix! */
.media__object::after{ content: ' '; display: block; clear: both;
}

Этот макет работает, но у него есть один главный недостаток: для него требуется ограничить ширину изображений, чтобы мы знали, какие поля использовать. Это ограничивает возможность использовать этот же компонент в нескольких контекстах. Вам может понадобиться изображение шириной 150 пикселей, когда этот компонент используется для виджета «Связанные посты», а для комментариев — всего 75 пикселей.

Попробуем сделать это с помощью Flexbox. Вот наш обновленный CSS:

.media__object { display: flex;
}
.media_object img { margin-right: 20px;
}

Это намного меньше CSS. Дополнительным бонусом является то, что нам не нужно беспокоиться о том, насколько широкое или высокое наше изображение. Мы также можем не заботиться о смещении. Имеет ли изображение ширину 200 пикселей или 20 пикселей, .media__object__text будет упираться в блок отступа нашего элемента img.

Создание гибких компонентов формы с помощью flex

Другой вариант использования Flexbox — создание гибких, вертикально выровненных компонентов формы. Рассмотрим шаблон интерфейса, приведенный на изображении ниже.

Поле формы с кнопкой рядом с ним

Здесь мы имеем поле для ввода формы и кнопку рядом с ним. Оба выровнены по вертикали, и кнопка имеет ширину 150 пикселей.

Что делать, если мы хотим, чтобы наш элемент ввода расширялся и заполнял доступное пространство в контейнере? Без Flexbox нам понадобится JavaScript и добавление разметки вручную, чтобы обновлять ширину поля для ввода в ответ на изменения ширины его родительского элемента. С Flexbox мы можем просто использовать flex.

Свойство flex фактически является сокращением для трех других свойств.

flex-grow указывает, что элемент должен растягиваться, если необходимо, значение должно быть положительным целым числом. Его начальное значение равно 0.

flex-shrink указывает, что элемент должен сжиматься при необходимости, значение должно быть положительным целым числом. Его начальное значение равно 1.

flex-basis: указывает начальную или минимальную ширину (когда ось flex горизонтальная) или высоту элемента (когда ось flex вертикальная). Это может быть длина или процент, или auto, начальное значение — auto.

Хотя каждое из этих свойств можно указать отдельно, спецификация настоятельно рекомендует использовать сокращенную форму. Вот пример:

div { display: flex;
}
input[type="text"], button { border: 0; font: inherit;
}
input[type="text"] { flex: 1 0 auto; }
button { background: #003; color: whitesmoke; display: block; text-align: center; flex: 0 0 150px;
}

Здесь мы использовали для элемента ввода flex: 1 0 auto. Поскольку его значение flex-growth равно 1, оно будет увеличиваться, чтобы заполнить доступное пространство родительского элемента. Однако для элемента кнопки мы использовали flex: 0 0 150px. Значения 0 для flex-growth и flex-shrink запрещает увеличение или уменьшение ширины кнопки, тогда как значение flex-base — 150px устанавливает ее ширину.

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

Результат flex: 0 0 150px

Хитрость с flex-grow и flex-shrink заключается в том, что они пропорциональны. Да, flex: 1 0 auto означает, что наше поле ввода будет шире нашей кнопки. Но изменение значения свойства flex нашей кнопки на flex: 1 0 auto не обязательно означает, что оба элемента будут иметь одинаковый размер, как показано на следующем изображении.

Оба элемента имеют одинаковое значение flex, но разные размеры

Вместо этого flex-элементы будут изменены, чтобы заполнить контейнер, принимая во внимание используемые ими значения min-width и max-width (которые могут быть их начальными значениями).

К сожалению, мы не можем использовать с flex-свойствами fr-единицы. Вместо этого используйте длину или процентное значение.

Вертикальное центрирование с помощью Flexbox

Наконец, давайте посмотрим, как вертикально отцентрировать контент с помощью Flexbox. Вертикально центрирующие элементы — одна из труднейших задач в CSS, особенно если высота вашего контента неизвестна. Но с помощью Flexbox нам требуется только одна дополнительная строка CSS-align-items: center:

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

Теперь наши flex-элементы и их содержимое расположены по вертикали во flex-контейнере, как показано на изображении ниже.

Распределение flex-элементов с помощью align-items: center

Создание макетов подобных сетке с помощью Flexbox

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

Макет в виде сетки с растягивающимися ячейками

Вот разметка, которую мы будем использовать:

<ul class="flex-aligned"> <li>A</li> <li>B</li> <li>C</li> <li>D</li> <li>E</li> <li>F</li> <li>G</li>
</li>

По умолчанию flex-элементы не переносятся. Чтобы создать приведенный выше макет, нам нужно сделать их переносимыми, используя свойство flex-wrap. Оно принимает три значения: nowrap (исходное значение), wrap и wrap-reverse. Мы будем использовать здесь:

.flex-aligned { display: flex; flex-wrap: wrap;
}

Теперь нам просто нужно указать, как должны вести себя flex-элементы, и какова их максимальная ширина. Поскольку мы хотим иметь максимум четыре столбца, мы установим значение 25% для flex-base. И так как мы хотим, чтобы наши flex-элементы растягивались, чтобы заполнить доступное пространство, мы установим для flex-grow — 1. Для flex-shrink мы оставим 0, чтобы наши блоки никогда не занимали менее 25% размера контейнера:

.flex-aligned li { flex: 1 0 25%;
}

Выбор flex или grid

Когда вы разрабатываете макеты страниц или компонентов, вы можете решить сами, когда лучше использовать Flexbox, а когда Grid.

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

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

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

Автор: Tiffany Brown

Источник: https://www.sitepoint.com/

Редакция: Команда webformyself.