Вёрстка: поток, flex и grid
- Зачем это нужно
- Обычный поток и почему его мало
- Гибкая строка: главная ось
- Распределение вдоль оси
- Как делится свободная ширина
- Поперёк оси и перенос
- Сетка: колонки и строки сразу
- Адаптив без единого медиазапроса
- Когда что
- Медиазапросы: когда без них всё-таки нельзя
- Типичные ошибки
- Слова главы
- Тренажёр: набрать вслепую
- На чемпионате
- Куда углубиться
- Куда дальше: проверенные ресурсы
Зачем это нужно
Элементы описаны, цвета и размеры заданы. Осталось самое видимое: расставить всё по местам. Поле ввода и кнопка — в строку. Карточки операций — сеткой. Шапка сверху, подвал внизу, основное посередине.
Двадцать лет это делали приёмами, которые для расстановки не предназначались, и вёрстка была ремеслом со своими суевериями. Сейчас есть два инструмента, созданных ровно под эту задачу: гибкая строка и сетка. Их хватает практически на всё.
Эта глава — про то, что они делают, чем отличаются и как из одной строки получается интерфейс, который сам перестраивается под ширину экрана.
Обычный поток и почему его мало
По умолчанию браузер расставляет элементы сверху вниз: каждый блочный занимает всю доступную ширину и начинается с новой строки. Прогон показывает, что из этого выходит:
── три блока: в обычном потоке и во flex-контейнере (ширина 600) ──
обычный поток : x=1 ш=598 | x=1 ш=598 | x=1 ш=598
display:flex : x=1 ш=63 | x=64 ш=59 | x=123 ш=90
высота строки: поток 112px, flex 39px
В потоке «Сумма», «Адрес» и «Отправить» встали друг под другом, каждый шириной 598 — во всю ширину контейнера. Высота получилась 112 точек.
Одно свойство у родителя — и три блока встали в строку, каждый по ширине своего содержимого, а высота стала 39.
Обратите внимание, где написано свойство: у контейнера, а не у элементов. Это общая черта обоих инструментов — расстановкой управляет родитель. Потомки могут лишь уточнять своё поведение.
Гибкая строка: главная ось
.row {
display: flex;
gap: 12px;
align-items: center;
}
Распределение вдоль оси
Прогон ставит три блока по 100 точек в контейнер шириной 600 и меряет, где каждый оказался:
── justify-content: три блока по 100 в контейнере 600 ──
flex-start 1, 101, 201
center 150, 250, 350
flex-end 299, 399, 499
space-between 1, 250, 499
space-around 51, 250, 449
space-evenly 76, 250, 425
Свободного места ровно 300 точек, и разница только в том, куда оно уходит.
К началу, по центру, к концу — всё место с одной стороны, с двух или с другой.
«Между» прижимает крайние к краям: первый на 1, последний на 499. Промежутки одинаковые, снаружи ничего.
«Вокруг» даёт каждому элементу поле с двух сторон, поэтому между соседями получается вдвое больше, чем с краю: 51 и 449.
«Поровну» делает все промежутки одинаковыми, включая крайние: 76.
Практически чаще всего нужны три: к началу (по умолчанию), по центру и «между» — последний для шапки, где логотип слева, а кнопка справа.
Как делится свободная ширина
── flex: как делится ширина 600 ──
1 : 1 : 1 199 + 199 + 199
2 : 1 : 1 298 + 150 + 150
200 фикс + рост 200 + 398
Последняя строка — самый частый рабочий приём: боковая панель фиксированной ширины плюс основная область, которая забирает остаток. Две строки оформления вместо вычислений в процентах.
Поперёк оси и перенос
По умолчанию гибкая строка не переносит элементы: они сжимаются, а если сжиматься некуда — вылезают за край. Прогон на узком экране:
── тот же набор на flex без переноса и с переносом (окно 375) ──
nowrap ширины 200, 200, 200 строк 1 вылезает за окно: true
wrap ширины 200, 200, 200 строк 3 вылезает за окно: false
Первая строка — та самая горизонтальная прокрутка на телефоне, из-за которой страница выглядит сломанной. Одно свойство — и элементы переносятся.
Поперёк оси работают два свойства:
- выравнивание элементов — прижать к верху, к низу, по центру или растянуть (по умолчанию растянуть);
- выравнивание строк — что делать, когда строк несколько и осталось свободное место по вертикали.
Центрирование по обеим осям, за которым гонялись десять лет, сегодня выглядит так: display: flex; justify-content: center; align-items: center. Три строки, работает с содержимым любой высоты.
Сетка: колонки и строки сразу
Гибкая строка выстраивает вдоль одной оси. Сетка работает сразу по двум.
.grid {
display: grid;
grid-template-columns: 200px 1fr 1fr;
gap: 16px;
}
── grid: 200px 1fr 1fr, зазор 16, контейнер 600 ──
a: x=1 y=1 ш=200
b: x=217 y=1 ш=183
c: x=416 y=1 ш=183
d: x=1 y=46 ш=200
Арифметика сходится: у контейнера рамка по точке с каждой стороны, значит внутри 598. Из них 200 занимает первая колонка, две по 16 — зазоры, остаток 366 делится пополам между долями: по 183.
Четвёртый элемент ушёл на вторую строку сам. Строки мы не описывали вовсе: сетка создала её, потому что элементы кончились не там, где колонки. Это её обычное поведение — описывают колонки, строки появляются по мере надобности.
Адаптив без единого медиазапроса
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 12px;
}
── repeat(auto-fit, minmax(200px, 1fr)) при разной ширине окна ──
окно 900 колонок 4 строк 1 ширина карточки 216px
окно 640 колонок 3 строк 2 ширина карточки 205px
окно 375 колонок 1 строк 4 ширина карточки 375px
ни одного медиазапроса при этом не написано
Одна строка заменяет три медиазапроса, и границы перестроения получаются не круглыми числами из головы, а настоящей шириной содержимого.
Нижняя граница должна быть меньше самого узкого экрана. Если написать 400 точек, то на телефоне шириной 375 колонка окажется шире окна — и появится горизонтальная прокрутка. Пишут так: minmax(min(200px, 100%), 1fr).
Когда что
| задача | инструмент |
|---|---|
| строка с полем и кнопкой | гибкая строка |
| шапка: логотип слева, вход справа | гибкая строка, распределение «между» |
| боковая панель плюс основное | гибкая строка: фиксированная и растущая |
| карточки операций | сетка с авторасстановкой |
| таблица из подписей и значений | сетка из двух колонок |
| разметка всей страницы | сетка |
| центрировать одно в другом | гибкая строка |
Грубое правило: вдоль одной линии — гибкая строка, по двум измерениям — сетка. Внутри ячейки сетки спокойно живёт гибкая строка, и наоборот; сочетать их нормально.
Медиазапросы: когда без них всё-таки нельзя
Сетка с авторасстановкой закрывает большинство случаев. Но иногда нужно не «перенести», а изменить саму раскладку: убрать боковую панель, переставить шапку в столбец, спрятать часть.
.layout { display: grid; grid-template-columns: 260px 1fr; gap: 16px; }
@media (max-width: 720px) {
.layout { grid-template-columns: 1fr; }
}
Порядок в файле важен: правило внутри запроса должно идти после основного, иначе вес у них одинаковый и победит то, что ниже.
Типичные ошибки
Горизонтальная прокрутка на телефоне. Причин ровно три: гибкая строка без переноса, фиксированная ширина больше экрана и картинка без ограничения. Проверяется сужением окна за полминуты.
Свойство расстановки написано у элемента, а не у контейнера. Ничего не происходит, и это выглядит как «не работает».
Отступы вместо зазора. Появляются лишние поля с краю, и они схлопываются друг с другом. Зазор решает обе беды.
Вертикальное центрирование через отступы. Работает, пока высота содержимого не изменилась. Выравнивание поперёк оси работает всегда.
Медиазапрос выше основного правила. Вес одинаковый, побеждает нижнее — запрос молча не действует.
auto-fit с нижней границей шире телефона. Колонка не помещается в окно, и появляется прокрутка — та самая, ради избавления от которой всё и затевалось.
Слова главы
- Поток — расстановка по умолчанию: блочные сверху вниз во всю ширину.
- Гибкая строка — расстановка вдоль одной оси; свойство пишут у контейнера.
- Главная ось — направление, вдоль которого идут элементы; можно повернуть в столбец.
- Распределение вдоль оси — куда уходит свободное место: к краю, по центру, между, поровну.
- Доли роста — как элементы делят свободную ширину;
0 0 200px— фиксированная колонка. - Перенос — по умолчанию его нет, и элементы вылезают за край.
- Сетка — расстановка по двум измерениям; колонки описывают, строки появляются сами.
- Доля свободного места — единица
fr; считается после фиксированных колонок и зазоров. - Авторасстановка —
auto-fitс границами: адаптив без медиазапросов.
Тренажёр: набрать вслепую
Цель: скорость ≥ 95 зн/мин, точность ≥ 88%
display: flex; gap: 12px; align-items: center;
На чемпионате
Сначала раскладка, потом красота. Шапка, основное, подвал — сеткой; внутри каждой части гибкие строки. На это уходит десять минут, и дальше всё складывается само.
Проверяйте узкий экран каждые полчаса. Достаточно сузить окно до трёхсот семидесяти пяти точек. Горизонтальная прокрутка — самая заметная и самая дешёвая в исправлении ошибка.
Зазор вместо отступов. Он не схлопывается, не даёт лишних полей с краю и убирается одной строкой.
Авторасстановка вместо медиазапросов там, где она подходит. Одна строка против трёх блоков — и меньше мест, где можно ошибиться.
И про порядок: раскладку делают до того, как в интерфейсе появляются настоящие данные. Иначе оказывается, что адрес кошелька в сорок символов ломает всё, что было аккуратно выровнено по коротким подписям.
Куда углубиться
- Именованные области сетки — разметка страницы словами вместо номеров линий.
- Выравнивание отдельного элемента — когда один из ряда должен встать иначе.
- Порядок элементов — переставить местами без изменения разметки, и почему этим лучше не злоупотреблять.
- Запросы к контейнеру — правила по ширине родителя, а не окна.
- Прилипающие элементы — шапка, которая остаётся видимой при прокрутке.
Сводная проверка по всей главе: 8 вопросов, 5:00 на всё, без подсказок по ходу. Вопросы показываются по одному, ответ изменить нельзя. Если время выйдет — экзамен завершится с тем, что успел ответить. Пересдавать можно сколько угодно раз.
Куда дальше: проверенные ресурсы
- MDN: гибкая раскладка — на русском, с интерактивными примерами.
- MDN: сетка — колонки, строки, области.
- CSS-Tricks: A Complete Guide to Flexbox — самая цитируемая шпаргалка.
- CSS-Tricks: A Complete Guide to Grid — то же самое для сетки.
- MDN: медиазапросы — синтаксис и выбор границ.
Комментарии
Обсуждение живёт в GitHub Discussions и грузится с чужого домена — поэтому только по нажатию.