Flexbox: раскладка вдоль оси
Одна строка превращает контейнер в гибкий ряд: выравнивание, распределение места, переносы и знаменитое flex: 1.
Что ты научишься делать
- Разложишь элементы в ряд и выровняешь их по обеим осям
- Прижмёшь один элемент вправо, не трогая остальные
- Соберёшь шапку сайта и сетку карточек на флексах
#Одна строка меняет всё
display: flex пишется родителю. После этого все его прямые дети становятся флекс-элементами и выстраиваются в ряд.
Зазоров между ними нет, высота выравнивается автоматически, расстояние задаётся одним свойством. Всё то, чего так не хватало с inline-block.
Так не надо
.menu li {
display: inline-block;
margin-right: 16px;
}
/* + разметка без переносов строк */Зазоры от пробелов, отступ у последнего пункта лишний, выровнять по высоте нечем.
Так надо
.menu {
display: flex;
gap: 16px;
}Два свойства вместо возни. Разметку можно писать как удобно, gap ставит расстояние только между элементами.
#Две оси
Вся логика флексов держится на понятии осей. Главная ось — направление, вдоль которого выстраиваются элементы. Поперечная — перпендикулярная ей.
По умолчанию главная ось горизонтальная. Свойство flex-direction: column поворачивает её вертикально — и тогда все остальные свойства меняются местами.
| Свойство | Ось | Что делает |
|---|---|---|
justify-content | Главная | Распределяет элементы вдоль оси |
align-items | Поперечная | Выравнивает элементы поперёк |
align-content | Поперечная | Распределяет строки, когда включён перенос |
gap | Обе | Расстояние между элементами |
#justify-content: вдоль оси
| Значение | Результат |
|---|---|
flex-start | Всё прижато к началу (по умолчанию) |
center | По центру |
flex-end | Прижато к концу |
space-between | Крайние по краям, промежутки одинаковые |
space-around | У каждого свой отступ; между элементами он вдвое больше, чем по краям |
space-evenly | Все промежутки, включая краевые, одинаковые |
#align-items: поперёк оси
По умолчанию стоит stretch: все элементы растягиваются на высоту самого высокого. Именно поэтому карточки в ряду сами получаются одинаковой высоты — этого годами добивались костылями.
Остальные значения: flex-start, center, flex-end и baseline — выравнивание по базовой линии текста, а не по краю блока.
#Центрирование, за которое боролись двадцать лет
.hero { display: flex; justify-content: center; /* по горизонтали */ align-items: center; /* по вертикали */ min-height: 400px;}#Как элементы делят место
У самих флекс-элементов есть три свойства. Обычно их пишут вместе, сокращением flex.
flex-grow— насколько жадно элемент забирает свободное место. 0 — не растёт.flex-shrink— насколько охотно сжимается, когда места не хватает. 0 — не сжимается.flex-basis— базовый размер до распределения.auto— по содержимому.
.a { flex: 1; } /* grow 1, shrink 1, basis 0 — делят место поровну */.b { flex: auto; } /* grow 1, shrink 1, basis auto — с учётом содержимого */.c { flex: none; } /* не растёт и не сжимается — фиксированный */.d { flex: 1 1 240px; } /* растёт, сжимается, стартует с 240px */#Перенос на новую строку
По умолчанию флекс-элементы не переносятся: они сжимаются до последнего и вылезают за край. flex-wrap: wrap разрешает перенос.
Связка flex-wrap: wrap плюс flex: 1 1 240px даёт простую отзывчивую сетку без единого медиазапроса: элементы стараются быть не уже 240 пикселей, а когда не помещаются — переносятся.
#order: порядок только для глаз
Свойство order меняет положение элемента в ряду, не трогая разметку. Соблазн большой: подвинуть картинку влево одной строкой вместо перестановки тегов.
Ловушка в том, что порядок меняется только визуально. Клавиша Tab и программы чтения с экрана идут по исходному коду, поэтому фокус будет прыгать: с виду вторая кнопка получит фокус первой. Для мелких перестановок в одном ряду это терпимо, для порядка полей формы или пунктов меню — нет.
Правило простое: если перестановка меняет смысл последовательности, менять надо разметку, а не order.
#Три приёма, которые нужны постоянно
/* 1. Прижать элемент вправо в шапке */.header__nav { margin-left: auto; /* auto съедает всё свободное место слева */}/* 2. Прижать подвал карточки книзу, какой бы длины ни был текст */.card { display: flex; flex-direction: column;}.card__footer { margin-top: auto;}/* 3. Поменять порядок, не трогая разметку */.sidebar { order: -1; }Где спотыкаются почти все
display: flex написан ребёнку вместо родителя
Почему Флексом становится контейнер, а не элементы внутри. Правило на ребёнке просто делает флекс-контейнером его самого.
Как надо Пиши display: flex тому элементу, чьих детей нужно разложить.
Элементы не переносятся и вылезают за край
Почему По умолчанию flex-wrap: nowrap: браузер сжимает элементы, а когда сжимать некуда — они выходят за границы.
Как надо Добавь flex-wrap: wrap.
Отступы между элементами заданы через margin
Почему У крайних элементов появляется лишний отступ, приходится писать :last-child и считать края.
Как надо Одно свойство gap у контейнера — расстояние только между элементами.
Длинный текст растянул колонку и сломал ряд
Почему У флекс-элементов min-width по умолчанию равен auto: элемент не может стать уже своего содержимого.
Как надо Добавь проблемному элементу min-width: 0 — теперь он сможет сжаться, а текст перенесётся.
- Флекс-контейнер flex container
- Элемент с
display: flex. Управляет раскладкой своих детей. - Флекс-элемент flex item
- Прямой ребёнок флекс-контейнера.
- Главная ось main axis
- Направление, вдоль которого выстраиваются элементы. Задаётся
flex-direction. - Поперечная ось cross axis
- Перпендикулярная главной. По ней работает
align-items. - gap gap
- Расстояние между элементами внутри контейнера, без отступов по краям.
Проверь себя
Флекс-контейнером становится родитель, а раскладываются его прямые дети.
При горизонтальной главной оси поперечная — вертикальная. По горизонтали центрирует <code>justify-content</code>.
Это сокращение от <code>flex: 1 1 0</code>: растёт, сжимается, стартует с нуля. Все такие элементы делят место поровну.
<code>auto</code> у отступа съедает всё свободное место — элемент уезжает вправо, а остальные остаются на местах.
У флекс-элементов <code>min-width</code> по умолчанию <code>auto</code>: они не сжимаются уже содержимого. Явный ноль снимает это ограничение.
Задание
Шапка и сетка карточек
Собери две вещи на флексах:
- шапка: логотип слева, меню и кнопка прижаты вправо, всё выровнено по центру по вертикали, расстояние между элементами задано через
gap; - сетка: карточки в ряд, переносятся при нехватке места, каждая не уже 200px и растягивается.
Никаких float и inline-block.
Подсказка 1
Шапка: .header { display: flex; align-items: center; gap: 20px; }
Подсказка 2
Меню вправо: .nav { display: flex; gap: 16px; margin-left: auto; }
Подсказка 3
Сетка: .grid { display: flex; flex-wrap: wrap; gap: 12px; } и .card { flex: 1 1 200px; }
Показать решение
<header class="header"> <a class="logo" href="#">Полка</a> <nav class="nav"> <a href="#">Меню</a> <a href="#">О нас</a> </nav> <a class="btn" href="#">Заказать</a></header><div class="grid"> <article class="card"><h3>Эспрессо</h3><p>120 ₽</p></article> <article class="card"><h3>Капучино</h3><p>190 ₽</p></article> <article class="card"><h3>Раф</h3><p>240 ₽</p></article></div>* { box-sizing: border-box; }.header { display: flex; align-items: center; gap: 20px; padding: 14px 18px; background: #14173a; border-radius: 12px; margin-bottom: 16px;}.nav { display: flex; gap: 16px; margin-left: auto;}.logo { color: #fff; font-weight: 700; text-decoration: none; }.nav a { color: #c6c9de; text-decoration: none; font-size: 14px; }.btn { padding: 8px 16px; color: #fff; background: #6544e0; border-radius: 999px; text-decoration: none; font-size: 14px; }.grid { display: flex; flex-wrap: wrap; gap: 12px;}.card { flex: 1 1 200px; padding: 18px; background: #f5f5fa; border-radius: 12px;}.card h3 { margin: 0 0 8px; font-size: 16px; }.card p { margin: 0; font-weight: 700; }