FLEXBOX В CSS
Модель компоновки, известная как Flexbox (гибкие блоки), становится все более популярной. Это связано с удобством использования при создании рамок и макетов для отдельных HTML-элементов на странице. Кроме того, Flexbox открывает новые возможности для удобной и пр��стой настройки макетов. В этой статье я постараюсь объяснить все тонкости Flexbox и представить вам удобную шпаргалку по гибким блокам.
В двух словах, Flexbox предлагает простые решения для задач, которые раньше казались сложными. Например, если вам нужно выровнять элемент по вертикали или закрепить подвал (footer) внизу экрана, либо просто расположить несколько блоков в одной строке, чтобы они занимали все доступное пространство. Такие задачи можно решать и без flex, но результаты обычно оказываются более сложными и запутанными, особенно когда нужно создать адаптивный дизайн для мобильных устройств. С помощью Flexbox все эти задачи решаются элегантно и просто, как и задумано в модели flex.
Модуль компоновки CSS Flexible Box Layout (модуль CSS для гибких блоков), или Flexbox, был создан для устранения недостатков при создании различных HTML-структур и упрощения логики компоновки. Логический подход работает в неожиданных местах, где результат не был проверен – логика здесь имеет значение!
Flexbox позволяет элегантно управлять различными параметрами элементов внутри контейнера: направлением, порядком, шириной, высотой, выравниванием по разным осям, распределением свободного пространства, расширением и сжатием элементов.
Содержание:
- Основные понятия
- Свойства CSS Flexbox
- Для контейнера
- display:
- flex-direction:
- flex-wrap:
- flex-flow: direction wrap
- justify-content:
- align-content:
- align-items:
- column-gap:
- gap:
- Для элементов контейнера
- flex-grow:
- flex-shrink:
- flex-basis:
- flex: {grow shrink basis}
- align-self:
- order:
- Примечания
- Примеры использования Flex
- Поддержка браузерами
ОСНОВНЫЕ ПОНЯТИЯ
Flexbox состоит из контейнера и его дочерних элементов (гибких элементов).
-
Основная ось — это главное направление расположения элементов внутри контейнера. Направление можно изменить с помощью свойства
flex-direction
. При изменении оси изменяются только направления движения блоков внутри контейнера, а начальный и конечный размер контейнера остаются прежними. -
Начало и конец основной оси — элементы располагаются от начала к концу контейнера.
-
Поперечная ось — направление движения элементов, когда они не помещаются в контейнер по основной оси. Поперечная ось всегда перпендикулярна основной.
-
Начало и конец поперечной оси — строки заполняются по попереч��ой оси от начала до конца контейнера. В каждой такой строке располагаются элементы.
-
Размер (основной и поперечный) — базовое значение, по которому вычисляется ширина или высота внутренних элементов, если размер не указан точно (указан в процентах или не указан вовсе, а элемент нужно растянуть или сжать).
Чтобы включить flexbox, достаточно задать CSS-свойство display: flex;
или display: inline-flex;
для любого HTML элемента.
1
2
После активации свойств flex внутри контейнера создаются две оси: основная и поперечная. Все вложенные элементы (первого уровня) располагаются вдоль основной оси. По умолчанию основная ось горизонтальная и направлена слева направо (→), а поперечная ось вертикальная и направлена сверху вниз (↓).
Основную и поперечную оси можно поменять местами, и элементы будут располагаться сверху вниз (↓), а когда они не помещаются по высоте, будут двигаться слева направо (→) – оси просто меняются местами. При этом начальные и конечные позиции элементов не меняются – меняются только направления!
Еще одна важная особенность Flexbox — наличие строк в поперечном направлении. Если основной горизонтальной оси много элементов, и они не помещаются в контейнер, они будут перемещаться в другую строку. Это означает, что контейнер будет выглядеть так: контейнер, внутри него две строки с несколькими элементами в каждой строке.
СВОЙСТВА CSS FLEXBOX
Flexbox включает различные CSS-правила для управления всей конструкцией flex. Некоторые из них нужно применять к основному контейнеру, а другие — к элементам этого контейнера.
ДЛЯ КОНТЕЙНЕРА
display:
Включает свойство flex для элемента. Это свойство влияет на сам элемент и его вложенные элементы — только потомки первого уровня становятся гибкими контейнерами.
flex
— элемент растягивается на всю ширину и имеет свое пространство среди окружающих элементов. Переносы строк происходят в начале и в конце блока.inline-flex
— элемент отображается рядом с другими элементами. Его внутреннее содержимое форматируется как блочный элемент, а сам элемент рассматривается как встроенный.
flex-direction:
Изменяет направление основной оси контейнера. Поперечная ось меняется соответственно.
row
(по умолчанию) — направление элементов слева направо (→)column
— направление элементов сверху вниз (↓)row-reverse
— направление элементов справа налево (←)column-reverse
— направление элементов снизу вверх (↑)
Важно понимать, что при переходе от строки к колонке или от строки-реверс к колонке-реверс меняется только направление оси, а не что-то еще. Начало и конец размещения блоков остаются неизменными.
flex-wrap:
Управляет переносом элементов, которые не помещаются в контейнер.
nowrap
(по умолчанию) — вложенные элементы располагаются в одной строке (когда направление=row) или в одной колонне (при направлении=column), независимо от того, помещаются ли они в контейнер.wrap
— включает перенос элементов на следующую строку, если они не помещаются в контейнер.wrap-reverse
— аналогично wrap, но перенос идет вверх.
flex-flow: direction wrap
Объединяет оба свойства flex-direction и flex-wrap. Чаще всего их используют вместе.
/* только flex-direction */
flex-flow: row;
flex-flow: row-reverse;
flex-flow: column;
flex-flow: column-reverse;
/* только flex-wrap */
flex-flow: nowrap;
flex-flow: wrap;
flex-flow: wrap-reverse;
/* оба значения сразу: flex-direction и flex-wrap */
flex-flow: row nowrap;
flex-flow: column wrap;
flex-flow: column-reverse wrap-reverse;
justify-content:
Выравнивает элементы вдоль основной оси: если направление row, то по горизонтали, а если direction=column, то по вертикали.
flex-start
(по умолчанию) — элементы располагаются с начала (в конце может остаться место).flex-end
— элементы выравниваются к концу (оставляя пространство в начале).center
— по центру (слева и справа останется пространство).space-between
— внешние элементы прижимаются к краям (пространство между элементами распределяется равномерно).space-around
— свободное пространство равномерно распределяется между элементами (внешние элементы не прижимаются к краям). Расстояние между краем контейнера и внешними элементами будет в два раза меньше, чем между элементами внутри строки.space-evenly
— так же, как space-around, но расстояние от внешних элементов до краев контейнера такое же, как и между элементами.
align-content:
Выравнивает строки, содержащие элементы, вдоль поперечной оси. Похож на justify-content, но для противоположной оси.
Примечание: Работает только когда высота контейнера фиксирована (выше, чем высота внутри него строк).
То есть если flex-direction: row
, то это свойство выровняет невидимые строки вертикально. Важно, чтобы высота блока была фиксированной и превышала высоту строк, иначе сами строки растянут контейнер, и любое выравнивание теряет смысл, так как между ними не будет свободного пространства.
Но когда flex-direction: column
, строки двигаются горизонтально, и ширина контейнера, как правило, больше ширины строк, и выравнивать строки становится имеет смысл.
Это свойство редко нужно и часто заменяется свойством align-items
(см. ниже).
stretch
(по умолчанию) — строки растягиваются, чтобы заполнить всю линиюflex-start
— строки группируются в начале контейнера (в конце может остаться пространство).flex-end
— строки группируются в конце контейнера (оставляя пространство в начале)center
— строки группируются в центре контейнера (с краями останется пространство)space-between
— внешние строки прижимаются к краям (пространство между строками распределяется равномерно)space-around
— свободное пространство равномерно распределяется между строками (внешние элементы не прижимаются к краям). Расстояние между краем контейнера и внешними строками будет в два раза меньше, чем между элементами в середине строки.space-evenly
— аналогично space-around, но расстояние от внешних элементов до краев контейнера такое же, как и между элементами.
align-items:
Выравнивает элементы вдоль поперечной оси внутри строки (невидимой линии). То есть строки выравниваются через align-content, а элементы внутри этих строк выравниваются через align-items. На основной оси деления по строкам не существует, и элементы выравниваются через justify-content.
stretch
(по умолчанию) — элементы растягиваются, чтобы заполнить линию полностьюflex-start
— элементы выравниваются в начале строкиflex-end
— элементы выравниваются в конце строкиcenter
— элементы выравниваются по центру строкиbaseline
— элементы выравниваются по базовой линии текста
column-gap: gap:
Задает размер промежутка между элементами в контейнере. Соответственно:
column-gap:
— только для колонн.gap:
— распределяет и между колоннами, и между строками.
Размеры можно указывать в относительных или абсолютных значениях: px, em и т. д. или в %.
ДЛЯ ЭЛЕМЕНТОВ КОНТЕЙНЕРА
flex-grow:
Задает коэффициент увеличения элемента, когда в контейнере есть доступное пространство. По умолчанию значение flex-grow
равно 0, что означает, что ни один из элементов не должен увеличиваться и заполнять доступное пространство в контейнере.
Примеры:
- Если всем элементам задать
flex-grow: 1
, они будут равномерно растягиваться и заполнять все доступное пространство в контейнере. - Если одному из элементов задать
flex-grow: 1
, он займет все доступное пространство в контейнере, и выравнивание черезjustify-content
будет не работать: пространства для выравнивания не останется... - Если
flex-grow: 1
, а у одного из нихflex-grow: 2
, то он будет в два раза больше, чем остальные. - Если все блоки внутри флекса имеют
flex-grow: 3
, размеры будут одинаковыми. - Со значением
flex-grow: 3
и у одного из них сflex-grow: 12
, он будет в четыре раза больше, чем остальные.
Как это работает? Предположим, контейнер шириной 500px и содержит два элемента, каждый по 100px. То есть в контейнере свободно 300 пикселей. Если задать flex-grow: 2
первому элементу и flex-grow: 1
второму, блоки займут всю доступную ширину контейнера: первый блок займет 300px, а второй – 200px. Это происходит потому, что доступные 300px распределяются между элементами в соотношении 2:1, добавив 200px первому элементу и 100px второму.
Примечание: Возможно указание дробных значений, например: flex-grow: 0.5
.
flex-shrink:
Задает коэффициент уменьшения элемента. Это свойство противоположно flex-grow
и определяет, как элемент должен сжиматься, если в контейнере нет доступного пространства. То есть это свойство начинает работать, когда сумма размеров всех элементов больше размера контейнера.
По умолчанию flex-shrink: 1
.
Предположим, контейнер шириной 600px и содержит два элемента, каждый шириной по 300px — flex-basis: 300px;
. То есть два элемента полностью заполняют контейнер. Теперь зададим flex-shrink: 2
первому элементу и flex-shrink: 1
второму. Теперь давайте уменьшим ширину контейнера на 300px, то есть элементы должны сжаться на 300px, чтобы поместиться внутри контейнера. Они начнут сжиматься в пропорции 2:1, то есть первый блок сожмется на 200px, а второй на 100px; новые размеры элементов будут 100px и 200px.
Примечание: Можно указать дробные значения для свойства, например: flex-shrink: 0.5
.
flex-basis:
Задает базовую ширину элемента – ширину до применения других условий, влияющих на размер элемента. Конечная ширина будет зависеть от базовой ширины и значений flex-grow
, flex-shrink
и содержимого внутри блока.
Значение может быть указано в px, em, rem, %, vw, vh и т. д.
Если указать auto
, элемент получит базовую ширину, исходя из содержимого внутри него.
По умолчанию: auto
.
Иногда лучше указывать ширину элемента четко, используя привычное свойство width
. Например, width: 50%
означает, что элемент внутри контейнера будет занимать ровно 50%, при этом свойства flex-grow
и flex-shrink
будут продолжать работать. Это может быть необходимо, когда элемент растягивает содержимое внутри него за пределы указанных значений в flex-basis
.
flex-basis
будет "жестким", если заменить растяжение и сжатие: flex-basis: 200px; flex-grow: 0; flex-shrink: 0;
. Всё это можно записать как flex: 0 0 200px;
.
flex: {grow shrink basis}
Сокращённая запись для трех свойств: flex-grow
, flex-shrink
, flex-basis
.
По умолчанию: flex: 0 1 auto
.
Тем не менее, можно указать одно или два значения:
flex: none; /* 0 0 auto */
/* число */
flex: 2; /* flex-grow (flex-basis становится 0) */
/* не число */
flex: 10em; /* flex-basis: 10em */
flex: 30px; /* flex-basis: 30px */
flex: auto; /* flex-basis: auto */
flex: content; /* flex-basis: content */
flex: 1 30px; /* flex-grow и flex-basis */
flex: 2 2; /* flex-grow и flex-shrink (flex-basis становится 0) */
flex: 2 2 10%; /* flex-grow, flex-shrink и flex-basis */
align-self:
Позволяет изменить свойство align-items
для отдельного элемента.
По умолчанию: от align-items
контейнера.
stretch
— элемент растягивается, чтобы заполнить всю линию.flex-start
— элемент выравнивается в начале строки.flex-end
— элемент выравнивается в конце строки.center
— элемент выравнивается по центру строки.baseline
— элемент выравнивается по базовой линии текста.
order:
Позволяет изменять порядок (позицию) элемента в общей строке.
По умолчанию: order: 0
.
По умолчанию элементы имеют order: 0
и располагаются в порядке своего появления в HTML-коде и направлении строки. Но если изменить значение свойства order
, элементы будут располагаться в порядке значений: -1 0 1 2 3… Например, если для одного из элементов установить order: 1
, все нулевые заказы будут первыми, а затем элемент с 1.
Таким образом, вы можете, например, переместить первый элемент в конец, не меняя направление движения остальных элементов или HTML-кода.
ПРИМЕЧАНИЯ
КАК FEX-BASIS ОТЛИЧАЕТСЯ ОТ WIDTH?
Ниже приведены важные различия между flex-basis
и width
/height
:
flex-basis
работает только для основной оси. Это означает, что приflex-direction: row
flex-basis
управляет шириной, а приflex-direction: column
— высотой.flex-basis
применяется тол��ко к элементам flex. То есть, если отключить flex для контейнера, это свойство не подействует.- Абсолютные элементы внутри контейнера не участвуют в структуре flex. Поэтому
flex-basis
не влияет на элементы контейнера, если они имеютposition: absolute
. Им нужно указать ширину/высоту. - При использовании CSS-свойства flex с тремя значениями:
flex-grow
/flex-shrink
/flex-basis
, можно комбинировать и записывать их кратко:flex:0 0 50%
. В то время как при использованииwidth
,grow
иshrink
, их необходимо записывать отдельно. Это иногда просто неудобно.
Когда возможно, все же рекомендуется использовать flex-basis
. Используйте width
только тогда, когда flex-basis
не подходит.
Разница между flex-basis и width — ошибка или особенность?
Содержимое внутри flex-элемента расширяет его и не может выходить за его пределы. Однако если установить ширину с помощью width
или max-width
, а не flex-basis
, элемент внутри flex-контейнера сможет выйти за пределы контейнера (иногда такое поведение необходимо).
ПРИМЕРЫ РАСПОЛОЖЕНИЯ FLEX
В примерах не используются префиксы для кроссбраузерной совместимости. Это сделано для удобства чтения CSS. Поэтому смотрите примеры в последних версиях Chrome или Firefox.
1 ПРОСТОЙ ПРИМЕР С ВЕРТИКАЛЬНЫМ И ГОРИЗОНТАЛЬНЫМ ВЫРАВНЕНИЕМ
Начнем с самого простого примера — выравнивания по вертикали и горизонтали одновременно на любом высоте блока, даже изменяемой.
Текст посередине
Или так, без блока внутри:
Текст посередине
2 АДАПТИВНОЕ МЕНЮ НА FLEX
Создадим меню в верхней части страницы. На широком экране оно должно находиться справа, посередине —позиционироваться по центру, а на маленьком экране каждый элемент должен располагаться на новой строке.
3 АДАПТИВНЫЕ 3 КОЛОНКИ
Этот пример демонстрирует, как быстро и удобно создать 3 колонки, которые будут преобразовываться в 2, а затем в 1 при сжатии экрана.
1
2
3
4
5
6
4 АДАПТИВНЫЕ БЛОКИ НА FLEX
Предположим, нам нужно отобразить 3 блока: один большой и два маленьких. При этом блоки должны адаптироваться к маленьким экранам.
1
2
3
5 ГАЛЕРЕЯ НА FLEX И ПЕРЕХОД
Этот пример демонстрирует, как быстро создать красивый аккордео�� с изображениями, используя flex. Обратите внимание на свойство transition
для флекса.
6 FLEX ВНУТРИ FLEX (ТОЛЬКО ПРИМЕР)
Задача состоит в том, чтобы создать гибкий блок так, чтобы начало текста в каждом блоке находилось на одной горизонтальной линии. То есть, при сжатии ширины блоки увеличиваются в высоту. Изображение должно быть вверху, кнопка всегда внизу, а текст посередине должен начинаться на одной горизонтальной линии...
Для решения этой задачи блоки растягиваются с помощью flex и имеют установленную максимальную ширину. Каждый внутренний блок также является структурой flex, с направлением оси flex-direction: column;
, а элемент посередине (где текст) растягивается flex-grow: 1;
, чтобы заполнить всё доступное пространство и достигнуть результата — текст начинается на одной линии...
ПОДДЕРЖКА БРАУЗЕРАМИ
Существуют некоторые ограничения, однако все современные браузеры поддерживают конструкции flexbox. Некоторые из них все еще требуют префиксов.
Важно, чтобы свойства, требующие префиксов, находились перед оригинальными свойствами.
Пример правил flex с необходимыми префиксами:
/* Контейнер */
.flex {
display: -ms-flexbox;
display: flex;
display: -ms-inline-flexbox;
display: inline-flex;
-ms-flex-direction: column;
flex-direction: column;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-ms-flex-flow: column wrap;
flex-flow: column wrap;
-ms-flex-pack: justify;
justify-content: space-between;
-ms-flex-line-pack: distribute;
align-content: space-around;
}
/* Элементы */
.flex-item {
-ms-flex-positive: 1;
flex-grow: 1;
-ms-flex-negative: 2;
flex-shrink: 2;
-ms-flex-preferred-size: 100px;
flex-basis: 100px;
-ms-flex: 1 2 100px;
flex: 1 2 100px;
-ms-flex-item-align: center;
align-self: center;
-ms-flex-order: 2;
order: 2;
}
Лучше, если свойства с префиксами будут находиться перед оригинальными свойствами.
ЗАМЕТКИ
Не забудьте про видео. Иногда они бывают тоже интересными и понятными.