Учебное пособие по CSS Flexbox


Учебное пособие по CSS Flexbox

Flexbox также известен как CSS Flexible Box Layout Module и дает веб-дизайнерам полный контроль над расположением элементов страницы по оси. Flexbox используется для создания отзывчивых панелей меню, галерей изображений, списков продуктов и всевозможных других компонентов страницы. Ключевым моментом Flexbox является способность делать элементы отзывчивыми, что изменяет их ширину и высоту, чтобы заполнить пространство в заданном измерении. Это позволяет элементам страницы растягиваться и сжиматься внутри своих контейнеров, что сокращает бесполезное пространство и переполнение, а также упрощает создание адаптивных макетов.

Flex-генератор, позволяющий визуально расположить flex-элементы в flex-контейнере и сгенерировать css-код: Flexbox генератор.


Наш первый макет Flexbox

Чтобы начать работу с нашим первым макетом flexbox, нам нужно настроить очень простой контейнер с несколькими элементами внутри. Мы будем использовать следующие коды html и css:

Пример: html

Скопировать
<body>
    <nav class="container">
        <div>Home</div>
        <div>About</div>
        <div>Services</div>
    </nav>
</body>

Пример: css

Скопировать
body {
    margin: 10px;
    font-family: Verdana;
}

.container {
    border: 5px solid #eee;
}

.container>div {
    padding: 10px;
    text-align: center;
    font-size: 2em;
}

.container>div:nth-child(1) {
    background-color: #2F6B5F;
}

.container>div:nth-child(2) {
    background-color: #FCD35D;
}

.container>div:nth-child(3) {
    background-color: #fcd35d;
}

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

начало работы с flexbox

Контейнер и элементы

Во флексбоксе у нас есть контейнер и его элементы. Это два основных компонента любого Flexbox. Любой элемент html, который является прямым потомком контейнера flexbox, становится элементом flexbox. Обладая этими знаниями, мы можем преобразовать блочное отображение элементов на странице в отображение flexbox. Все, что нам нужно сделать, это добавить свойству display значение flexв контейнер:

.container {
    display: flex;
} 

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


Оси Flexbox (главная и поперечная)

В flexbox есть так называемая главная ось, которая проходит слева направо , и поперечная ось, которая проходит сверху вниз. Это определяет направление контейнера flexbox. Контейнер flexbox всегда имеет направление. По умолчанию направление горизонтальное, элементы отображаются слева направо. Его также называется строкой. Понятие осей flexbox важно сразу понять, потому что для управления элементами flexbox используются разные свойства css в зависимости от того, находятся ли они на главной оси или на поперечной оси. Ось контейнера flexbox управляется свойством flex-direction.

Мы можем преобразовать наш первый макет flexbox из строки в столбец с помощью этого свойства CSS.

.container {
    display: flex;
    flex-direction: column;
}

Теперь контейнер flexbox укладывает элементы сверху вниз, а не слева направо. Обратите внимание: ось сверху вниз теперь является главной осью, а ось слева направо - поперечной осью.
column flexbox flex-direction

Вот диаграмма, наглядно поясняющая вышеизложенную концепцию flexbox.
направления flex-direction

flex-direction: row; — горизонтальное расположение элементов будет использоваться для большого количества случаев работы с flexbox.


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

Давайте вернём направление flex-direction обратно в ряд (row), чтобы у нас была компоновка элементов слева направо. Теперь мы начнем смотреть на размещение flex-элементов вдоль главной оси. Поскольку мы вернулись к flex-direction: row; - это означает, что главная ось проходит горизонтально слева направо.


justify-content: flex-start;

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

.container {
    display: flex;
    justify-content: flex-start;
}

justify-content flex-start


justify-content: flex-end;

Это значение перемещает flex-элементы в конец flex-контейнера.

.container {
    display: flex;
    justify-content: flex-end;
}

justify-content flex-end


justify-content: center;

Назначение center свойству justify-content выравнивает flex-элементы по центру flex-контейнера.

.container {
    display: flex;
    justify-content: center;
}

justify-content center


justify-content: space-between;

Значение space-between обеспечивает равное расстояние между flex-элементами, но не добавляет пространство на концах ряда.

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

justify-content space-between


justify-content: space-around;

Работает так же, как и space-between, за исключением того, что добавляет пространство в начале и конце ряда.

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

пространство вокруг flex-элементов


Позиционирование элементов в Flexbox

Вам определенно понадобится разместить отдельные элементы в контейнере flexbox в тех случаях, когда стандартные параметры justify-content, которые мы только что обсудили, могут не подойти. Что делать, если вам нужно разместить два гибких элемента с одной стороны, а третий - с другой стороны. В этом случае мы можем использовать свойство margin. Нам нужно будет обращаться к отдельным элементам индивидуально, поэтому мы объявляем каждый элемент, назначив ему уникальный класс.

<body>
    <nav class="container">
        <div class="home">Home</div>
        <div class="about">About</div>
        <div class="services">Services</div>
    </nav>
</body> 

Представьте, что мы хотим переместить элемент Services вправо, но оставить элементы Home и About как есть. Как мы можем сделать это? Давайте теперь посмотрим на этот обновленный CSS-код:

.container {
    display: flex;
}

.services {
    margin-left: auto;
}

Это позволяет нам легко размещать отдельные элементы вдоль главной оси. Выглядит неплохо!
flex-элемент с левым полем авто

Чтобы переместить элементы About и Services вправо, мы можем просто установить значение css элементу About следующим образом:

.container {
    display: flex;
}

.about {
    margin-left: auto;
}

переместите два флекс-элемента вправо


Свойство flex

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

.container {
    display: flex;
}

.container > div {
    flex: 1;
} 

трехколоночный макет flexbox

Теперь давайте сделаем один элемент в два раза шире остальных. Для этого установим элементу Services значение flex 2.

.container {
    display: flex;
}

.container > div {
    flex: 1;
}

.container > .services {
    flex: 2;
}

flex установлен на 2

Благодаря свойству flex вы можете просто сделать один элемент резиновым, в то время как другие элементы сохранят фиксированную ширину. В приведенном ниже примере элемент About будет растягиваться и сжиматься при всех размерах экрана, в то время как Home и Services сохранят фиксированную ширину:

.container {
    display: flex;
}

.about {
    flex: 2;
}

свойство flex только для одного элемента

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

.container {
    display: flex;
}

.home, .services {
    flex: 1;
}

два flex-элемента и один фиксированный элемент


Как выровнять элементы с помощью Flexbox

Давайте теперь посмотрим, как можно расположить элементы вдоль поперечной оси. Помните, что ось контейнера flexbox определяется на основе его базового направления. По умолчанию свойство flex-direction имеет направление row. Это означает, что поперечная ось — это направление сверху вниз. По умолчанию flex-элементы растягиваются вдоль поперечной оси. Чтобы продемонстрировать это, сделаем наш flex-контейнер высотой 200 пикселей, и каждый элемент по-прежнему будет заполнять пространство сверху вниз:

.container {
    display: flex;
    height: 200px;
}

flexbox элементы по умолчанию растянуть

Когда контейнер flexbox имеет бо́льшую высоту, чем содержащиеся в нем элементы, мы можем использовать свойство align-items для позиционирования вдоль поперечной оси.

Свойство align-items управляет выравниванием элементов вдоль поперечной оси и имеет пять значений:

  • значение по умолчанию stretch,

  • flex-start,

  • flex-end,

  • center,

  • baseline.


align-items: flex-start;

Если установить значение flex-start свойству align-items, то элементы будут располагаться в верхней части контейнера:

.container {
    display: flex;
    height: 200px;
    align-items: flex-start;
}

flexbox выравнивает элементы в начале контейнера


align-items: center;

Значение center выстраивает элементы в середине контейнера:

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

Flexbox выравнивает элементы по центру


align-items: flex-end;

Значение flex-end помещает элементы в нижнюю часть flex-контейнера:

.container {
    display: flex;
    height: 200px;
    align-items: flex-end;
}

flexbox выравнивает элементы в конце


align-items: baseline;

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

Чтобы продемонстрировать это, нам нужно изменить содержимое каждого элемента. Мы можем просто назначить разные размеры шрифта для каждого элемента. Обратите внимание, что даже несмотря на то, что каждый элемент имеет содержимое разного размера, нижняя часть текста для каждого элемента идеально выстраивается как бы на «одной строке»:

.container {
    display: flex;
    height: 200px;
    align-items: baseline;
}

Пример базовой линии для выравнивания элементов flexbox


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

Что, возможно, принесло больше счастья веб-дизайнерам во всем мире, так это возможность идеально центрировать элемент как по горизонтали, так и по вертикали с помощью flexbox. Все, что этого нужно сделать — это применить оба свойства align-items: center; и justify-content: center; к контейнеру flexbox:

.container {
    display: flex;
    height: 200px;
    align-items: center;
    justify-content: center;
}

Выравнивание flexbox по вертикали и горизонтали


Выравнивание отдельных элементов Flex

Для выравнивания элементов вдоль поперечной оси мы будем использовать свойство align-self для отдельных элементов. В следующем примере мы пропишем его элементу About и переместим его наверх:

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

.about {
    align-self: flex-start;
}

align-self flex-start

В следующем примере также без проблем переместим вниз элемент Services:

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

.about {
    align-self: flex-start;
}

.services {
    align-self: flex-end;
}

flexbox align-self flex-end


Изменение направления оси с помощью column

Итак, теперь мы собираемся полностью изменить принцип работы контейнера flexbox. В Flexbox, как вы уже помните, по умолчанию свойству flex-direction установлено значение row (строка). Это означает, что элементы позицианируются слева направо. Если свойству flex-direction установить значение column (столбец), то изменится позиционирование элементов сверху вниз.


justify-content: flex-start;

Выравнивание флекс-элементов с начала:

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

justify-content flex-start


justify-content: flex-end;

Выравнивание флекс-элементов с конца:

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

justify-content flex-end


justify-content: center;

Выравнивание элементов по центру:

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

Выравнивание элементов по центру


justify-content: space-between;

Равномерно распределяет все элементы по высоте flex-блока. Первый элемент вначале, последний в конце:

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

flex direction column justify content space between


justify-content: space-around;

Равномерно распределяет все элементы по высоте flex-блока. Все элементы имеют полноразмерное пространство:

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

flex direction column justify content space around


justify-content: space-evenly;

Равномерно распределяет все элементы по высоте flex-блока. Все элементы имеют равное пространство вокруг:

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

flex direction column justify content space evenly


Сводка по осям Flexbox

Главная и поперечная оси изменяются в зависимости от значения свойства flex-direction.


flex-direction: row;

Главная ось перемещается слева направо, а поперечная ось перемещается сверху вниз.
flex direction row axix


flex-direction: column;

Главная ось перемещается сверху вниз, а поперечная ось перемещается слева направо.
Главная ось перемещается сверху вниз


flex-direction: row-reverse;

Главная ось перемещается справа налево, а поперечная ось перемещается сверху вниз.
Главная ось перемещается справа налево


flex-direction: column-reverse;

Главная ось перемещается снизу вверх, а поперечная ось перемещается слева направо.
Главная ось перемещается снизу вверх


Перенос элементов в Flexbox

В flexbox по умолчанию элементы не переносятся на новую строку, т.е. значение по умолчанию свойства flex-wrap равняется nowrap. Это значит, что если у нас есть набор элементов, которые слишком широки для их контейнера, то они будут его переполнять. Если вы хотите, чтобы элементы переносились на следующую строку при переполнении, нужно добавить контейнеру свойство flex-wrap и установить ему значение wrap.

В следующем примере установим для каждого флекс-элемента широкое значение, скажем, 343 пикселя. Так же мы включим функцию переноса:

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

.container > div {
    width: 343px;
}

flexbox flex-wrap включен

Если мы закомментируем декларацию flex-wrap: wrap; , то флекс-элементы не будут переноситься, даже если им назначена ширина, которая должна явно выходить за пределы flex-контейнера. Что происходит в этом сценарии, так это то, что flexbox автоматически уменьшает каждый флекс-элемент, чтобы он уместился в заданном пространстве:

.container {
    display: flex;
    /* flex-wrap: wrap; */
}

.container > div {
    width: 343px;
}

flex-wrap отключен


Flex grow, shrink и basis

Ранее мы видели, как использование свойства flex позволяет нам автоматически увеличивать и уменьшать каждый флекс-элемент по мере необходимости. Другими словами, это единственное свойство сделало все отзывчивым. Свойство flex на самом деле является сокращенным обозначением использования трех других свойств: flex-grow, flex-shrink и flex-basis. Следующие три блока css эквивалентны:

.about {
    flex: 1;
}
-----------------------
.about {
    flex: 1 1 0;
}
-----------------------
.about {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: 0;
}

Давайте исследуем каждое свойство. Свойство flex-basis — это способ установки начального основного размера flex-элемента.

Свойство flex-grow устанавливает величину динамического роста flex-элемента. Оно определяет, какая часть доступного пространства в flex-контейнере должна быть выделена для текущего флекс-элемента (flex grow factor — «коэффициент увеличения flex»). Свободное пространство — это разница между размером флекс-контейнера и размером всех его флекс-элементов вместе. Если все родственные флекс-элементы имеют одинаковый коэффициент flex-grow, то всем элементам предоставляется одинаковое количество доступного пространства, в противном случае оно распределяется в соответствии с соотношением, определённым различными коэффициентами flex-grow.

Свойство flex-shrink устанавливает коэффициент динамического сжатия флекс-элемента. Flex-элементы сжимаются, чтобы заполнить контейнер в соответствии с предоставленным значением, когда размер flex-элементов по умолчанию больше, чем размер flex-контейнера.

Например, представьте, что наш контейнер flexbox теперь имеет только два гибких элемента:

Пример: html

Скопировать
<body>
    <nav class="container">
        <div class="about">About</div>
        <div class="services">Services</div>
    </nav>
</body>

Пример: css

Скопировать
.container {
    display: flex;
}

.about {
    flex-basis: 200px;
}

.services {
    flex-basis: 200px;
}

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

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

.container {
    display: flex;
}

.about {
    flex-grow: 1;
    flex-basis: 200px;
}

.services {
    flex-grow: 1;
    flex-basis: 200px;
}

Пример flex-grow и flex-basis

В следующем примере css-правила гласят следующее: оба флекс-элемента About и Services будут начинаться с 200 пикселей. Затем дополнительное пространство будет выделено для флекс-элемента Services, а для флекс-элемента About дополнительное пространство не будет выделено:

.container {
    display: flex;
}

.about {
    flex-grow: 0;
    flex-basis: 200px;
}

.services {
    flex-grow: 1;
    flex-basis: 200px;
}

установка различных значений flex-grow и flex-basis

А теперь рассмотрим свойство flex-shrink. Обратите внимание, что для флекс-элемента About коэффициент flex-shrink равен 1, а для флекс-элемента Services — 0. Это означает, что если контейнер сжимается меньше, чем необходимый размер, чтобы обеспечить по крайней мере начальную ширину каждого флекс-элемента, то флекс-элемент About будет первым, чтобы начать сжиматься. Флекс-элемент Services пока сжиматься не будет.

Пример: css

Скопировать
.container {
    display: flex;
}

.about {
    flex-grow: 0;
    flex-shrink: 1;
    flex-basis: 300px;
}

.services {
    flex-grow: 0;
    flex-shrink: 0;
    flex-basis: 300px;
}

пример flex-shrink


Порядок вывода флексов внутри флекс-контейнера

Flexbox имеет функцию, аналогичную CSS Grid, в которой вы можете визуально переупорядочивать элементы, не изменяя при этом базовую разметку HTML. Мы можем немного изменить HTML, чтобы упростить понимание этой концепции упорядочивания. Что мы собираемся сделать сейчас, так это изменить способ отображения этих flex-элементов в браузере, не касаясь разметки HTML. Мы будем использовать свойство order только для flex-элементов.

Пример: html

Скопировать
<body>
    <nav class="container">
        <div class="flex1">Flex 1</div>
        <div class="flex2">Flex 2</div>
        <div class="flex3">Flex 3</div>
    </nav>
</body>

Пример: css

Скопировать
.container {
    display: flex;
}

.container > div {
    flex: 1;
}

.container > .flex2 {
    order: 1;
}

Установка элементу "flex2" order: 1 помещает его в контейнер последним.
как работает order

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

Имея это в виду, давайте попробуем сделать так, чтобы элемент Flex 2 шел первым, элемент Flex 3 - следующим, а элемент Flex 1 - последним:

.container {
    display: flex;
}

.container > div {
    flex: 1;
}

.container > .flex1 {
    order: 30;
}

.container > .flex2 {
    order: 10;
}

.container > .flex3 {
    order: 20;
}

Глядя ниже, мы получаем желаемый результат. Мы использовали 10, 20 и 30 в качестве значений, чтобы продемонстрировать, что числовое значение не является позицией, которую занимает элемент. Это так сказать вес. Происходит то, что браузер просматривает значение всех элементов и упорядочивает их от наименьшего к наибольшему. Элемент Flex 2 имеет наименьшее значение 10, поэтому он идет первым. Следующим наименьшим значением является элемент Flex 3 со значением 20, поэтому он идет следующим. Элемент Flex 1 имеет значение 30, поэтому он идет последним.
пример flex order


Использование медиа-запросов с Flexbox

Хороший трюк - использовать CSS медиа-запросов при работе с макетами Flexbox. Для начала, давайте обновим наш HTML, чтобы добавить еще один гибкий элемент.

Пример: html

Скопировать
<body>
    <nav class="container">
        <div class="home">Home</div>
        <div class="about">About</div>
        <div class="services">Services</div>
        <div class="contact">Contact</div>
    </nav>
</body>

Мы можем начать с этого CSS для обычного отображения кода на desktop.

Пример: css

Скопировать
.container {
    display: flex;
}

.container > div {
    flex: 1;
}

flexbox без медиа-запросов в представлении desktop

Теперь давайте создадим вид для планшета. Для экранов размером с tablet было бы неплохо иметь красивый двухкомпонентный дизайн. Для этого мы можем использовать удобный медиа-запрос. В приведенном ниже css-коде говорится, что если браузер переходит на 700 пикселей или ниже, включите flex-wrap и установите каждому flex-элементу свойство flex basis на 50%. (46% с учетом заполнения, маржи и т.д.).

.container {
    display: flex;
}

.container > div {
    flex: 1;
}

@media all and (max-width: 700px) {
    .container {
        flex-wrap: wrap;
    }

    .container > div {
        flex: 1 1 46%;
    }
}

Этот код дает нам красивую раскладку на планшете.
медиа-запрос, используемый для макета планшета

Наконец, мы можем добавить медиа-запрос для просмотра на мобильных устройствах:

.container {
    display: flex;
}

.container > div {
    flex: 1;
}

@media all and (max-width: 700px) {
    .container {
        flex-wrap: wrap;
    }

    .container > div {
        flex: 1 1 46%;
    }
}

@media all and (max-width: 550px) {
    .container > div {
        flex: 1 1 100%;
    }
}

Этот обеспечивает адаптивное меню на мобильном устройстве для удобной навигации:
меню навигации flexbox для мобильных устройств


Создание сетки изображений с помощью Flexbox

Flexbox также упрощает создание галерей изображений! Ниже представлена базовая HTML-разметка для нашей галереи изображений.

Пример: html

Скопировать
<body>
    <nav class="container">
        <div class="home"><img src="art.jpeg"></div>
        <div class="home"><img src="boats.jpeg"></div>
        <div class="home"><img src="cat.jpeg"></div>
        <div class="home"><img src="city.jpeg"></div>
        <div class="home"><img src="cleaning.jpeg"></div>
        <div class="home"><img src="field.jpeg"></div>
        <div class="home"><img src="flowers.jpeg"></div>
        <div class="home"><img src="globe.jpeg"></div>
        <div class="home"><img src="hand.jpeg"></div>        
    </nav>
</body>

Нам нужен только этот CSS!

Пример: css

Скопировать
.container {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}

.container > div > img {
    width: 230px;
}

.container > div {
    flex: 1;
}

Уже одно это дает нам довольно красивую галерею изображений с несколькими фрагментами CSS.
галерея изображений flexbox


Вот свойства Flexbox, которые нужно знать при работе с Flexbox.

Свойства контейнера Flexbox

  • display: flex - превращает элемент в flex-контейнер
  • flex-direction - устанавливает направление, в котором flex-элементы помещаются в flex-контейнер.
  • flex-wrap - позволяет включить перенос flex-элементов (по умолчанию nowrap).
  • flex-flow - сокращенное обозначение для flex-direction и flex-wrap
  • justify-content - определяет, как пространство распределяется между элементами на главной оси
  • align-content - выравнивает flex-элементы по поперечной оси.
  • align-items - определяет, как пространство распределяется между элементами на поперечной оси

Свойства элемента Flexbox

  • align-self - переопределяет элементы align-items для выравнивания одного элемента по поперечной оси.
  • flex - объединяет flex-grow , flex-shrink и flex-basis в одно свойство - определяет, как flex-элементы изменяют размеры, чтобы соответствовать доступному пространству
  • flex-grow - определяет, насколько flex-элементу разрешено расти, чтобы заполнить дополнительное пространство в flex-контейнере.
  • flex-shrink - определяет, насколько flex-элементу разрешено сжиматься, когда в flex-контейнере недостаточно места
  • order - указанное числовое значение - элементы с меньшим числом перемещаются влево, элементы с большим числом перемещаются вправо

Проверьте свойства Flexbox на визуальном Flex-генераторе!

Кликните свойства ниже, чтобы наглядно увидеть, как они влияют на flex-элементы в flex-контейнере с помощью Flexbox генератора!

Вот ещё один Flex-генератор, позволяющий визуально расположить flex-элементы в flex-контейнере и сгенерировать css-код: Flexbox генератор.