Тема 03

Тема 3. Layout: позиционирование, Flexbox, Grid, адаптивность

Тема 3. Layout: позиционирование, Flexbox, Grid, адаптивность

В теме 1 мы описали структуру документа, в теме 2 — оформление отдельных элементов: цвет, шрифт, размеры коробки. Но интерфейс — это не набор независимо оформленных блоков, а их взаимное расположение на плоскости: колонки рядом, шапка сверху, карточки сеткой, боковая панель, прижатая к краю. За это отвечает раскладка (англ. layout) — совокупность механизмов CSS, определяющих, где именно окажется каждый элемент. Раскладка — та часть CSS, которая исторически менялась сильнее всего: от табличной вёрстки девяностых через float к специально спроектированным Flexbox и Grid. Мы разберём её послойно — от потока документа, работающего по умолчанию, к позиционированию, затем к двум современным модулям раскладки, и завершим адаптивностью: тем, как одна вёрстка обслуживает экраны от телефона до широкого монитора.

Поток документа и модели отображения

Нормальный поток: блочные и строчные контексты

Пока к элементам не применены никакие свойства раскладки, браузер размещает их в нормальном потоке (англ. normal flow) — порядке по умолчанию, заданном спецификацией 1. Правило потока простое и предсказуемое: элементы идут в том же порядке, в каком записаны в разметке, и каждый следующий встаёт после предыдущего. Различие в том, как именно встаёт, — и здесь работают два контекста.

Блочные элементы (<div>, <p>, <section>, заголовки) выстраиваются сверху вниз, каждый с новой строки, и по умолчанию занимают всю доступную ширину родительского элемента — сколько бы места ни требовало содержимое. Два абзаца подряд окажутся один под другим, даже если в каждом всего одно слово.

Строчные элементы (<span>, <a>, <em>, <strong>) выстраиваются слева направо внутри строки, как слова в тексте, и переносятся на следующую строку только когда заканчивается место. Их ширина и высота определяются содержимым; задать им width или вертикальные отступы напрямую нельзя — это одно из типичных мест, где начинающий разработчик безуспешно пытается «раздвинуть» строчный элемент.

Нормальный поток: блочные элементы во всю ширину друг под другом, строчные — в ряд с переносом
Блочный и строчный контекст нормального потока

Нормальный поток — не архаизм, который нужно поскорее отключить, а разумная основа. Большая часть текстового контента прекрасно раскладывается именно им, и хорошая вёрстка обычно оставляет поток работать там, где он справляется, вмешиваясь только там, где нужна нестандартная геометрия.

Свойство display: block, inline, inline-block, none

К какому контексту относится элемент, определяет не только его тег, но и свойство display, которое можно переназначить 2. Четыре его базовых значения стоит знать наизусть.

display: block делает элемент блочным: новая строка, полная ширина, работают width, height, вертикальные отступы. display: inline — строчным: элемент течёт в строке, игнорирует заданные ширину и высоту. display: none полностью убирает элемент из потока и из отрисовки — он не занимает места и недоступен, как будто его нет в разметке (в отличие от visibility: hidden, который прячет элемент, но оставляет занятое им место).

Отдельного внимания заслуживает display: inline-block — гибрид, который течёт в строке рядом с соседями, как строчный, но при этом принимает width, height и вертикальные отступы, как блочный. Долгое время inline-block был рабочей лошадкой для раскладки горизонтальных рядов — кнопок, пунктов меню, карточек, — пока эту роль не переняли Flexbox и Grid. Сегодня его основное применение — точечное: элемент, который должен вести себя как слово в тексте, но с заданными габаритами.

Значения display этим не исчерпываются: flex и grid, которым посвящены отдельные разделы темы, тоже задаются через это свойство. Формально display управляет сразу двумя вещами — тем, как элемент ведёт себя снаружи (блочный или строчный по отношению к соседям), и тем, какой контекст раскладки он создаёт внутри для своих потомков.

Контекст форматирования и сворачивание полей

Контейнер с блочными потомками создаёт вокруг них блочный контекст форматирования (англ. block formatting context, BFC) — изолированную область, внутри которой действуют правила блочного потока 1. Понятие звучит абстрактно, но за ним стоят вполне ощутимые эффекты, и один из них мы уже встречали.

В теме 2, разбирая блочную модель, мы отметили, что вертикальные margin-ы соседних блоков схлопываются (англ. margin collapsing): при margin-bottom: 20px у одного блока и margin-top: 30px у следующего промежуток окажется 30 px, а не 50. Теперь можно назвать причину: схлопывание — свойство именно блочного контекста форматирования, в котором соприкасающиеся вертикальные поля объединяются в одно, равное большему из них. Схлопываются и поля вложенных элементов с полями родителя, если между ними нет рамки, padding-а или содержимого, — из-за чего margin-top дочернего элемента иногда «протекает» наружу и сдвигает весь родительский блок.

Новый BFC создаётся не всегда, а при определённых условиях: у элемента задан overflow отличный от visible, display: flow-root, он является flex- или grid-элементом, плавает через float. Внутри такого контекста поля больше не схлопываются с внешними, а плавающие элементы не выходят за его границы. display: flow-root — современное и наименее побочное средство завести чистый BFC, когда нужно, например, чтобы родитель охватывал вложенные плавающие элементы или чтобы прекратить нежелательное схлопывание.

Позиционирование

position: static, relative, absolute, fixed, sticky

Свойство position выводит элемент из-под управления нормального потока и позволяет задавать его положение явно, через смещения top, right, bottom, left 3. У него пять значений, и различаются они тем, относительно чего отсчитывается положение.

position: static — значение по умолчанию: элемент в нормальном потоке, смещения игнорируются. Это «выключенное» позиционирование.

position: relative оставляет элемент в потоке (место под него сохраняется), но позволяет сместить его визуально относительно исходного положения. Само по себе относительное позиционирование применяют нечасто; куда важнее его побочная роль — оно делает элемент точкой отсчёта для абсолютно позиционированных потомков.

position: absolute полностью извлекает элемент из потока — соседи смыкаются, как будто его нет, — и позиционирует его относительно ближайшего предка, у которого position отличен от static. Если такого предка нет, отсчёт идёт от корневого блока страницы. Отсюда устойчивый приём: родителю ставят position: relative, чтобы «поймать» абсолютно позиционированного потомка внутри своих границ. Так размещают бейджи на карточках, кнопки закрытия в углу модального окна, подсказки.

position: fixed тоже извлекает элемент из потока, но привязывает его к вьюпорту — видимой области окна. Такой элемент остаётся на месте при прокрутке страницы; типичные применения — «липкая» шапка, кнопка «наверх», плавающая панель действий.

position: sticky — гибрид относительного и фиксированного. Пока элемент в пределах видимости прокручивается обычным образом (как relative), но при достижении заданного порога (top: 0) «прилипает» к краю и держится там, пока родительский контейнер не уйдёт из виду. Это поведение заголовков разделов в длинных списках, которые остаются на виду, пока листаешь свой раздел, и уступают место следующему.

Схемы позиционирования: relative со смещением и сохранённым местом, absolute вне потока, sticky у края
Поведение `relative`, `absolute` и `sticky` относительно потока

Контекст наложения и z-index

Как только элементы перестают идти строго друг за другом и начинают перекрываться, возникает вопрос: какой из них окажется сверху? Порядок наложения регулируется свойством z-index — целым числом, задающим положение элемента по воображаемой оси, направленной от экрана к зрителю. Больший z-index — ближе к зрителю, поверх остальных.

Тонкость в том, что z-index действует не глобально, а внутри контекста наложения (англ. stacking context) — изолированной группы, порядок внутри которой считается отдельно. Элемент с z-index: 9999 внутри одного контекста никогда не перекроет элемент из другого контекста, который стоит выше по дереву, — сколько бы девяток мы ни приписали. Новый контекст наложения создаётся не только через position с ненулевым z-index, но и рядом других свойств: opacity меньше единицы, transform, filter, will-change. Это частый источник недоумения: разработчик поднимает z-index до астрономических значений, а элемент всё равно оказывается под соседом — потому что проблема не в величине, а в том, что они в разных контекстах. Понимание границ контекста наложения устраняет большую часть подобных «магических» багов.

float как устаревающий механизм

Свойство float изначально решало узкую типографскую задачу — обтекание изображения текстом, как в бумажной вёрстке. Плавающий элемент сдвигается к краю контейнера, а последующий контент обтекает его сбоку. На безрыбье доспециализированных модулей раскладки float два десятилетия использовали не по прямому назначению — для построения многоколоночных сеток, выстраивания элементов в ряд, вёрстки целых страниц. Приём работал, но требовал костылей: очистки обтекания (clear, «clearfix»-хаки), борьбы со схлопыванием высоты контейнера, ручного расчёта ширин в процентах.

С появлением Flexbox и Grid эта роль float отмерла: то, ради чего его выкручивали, теперь решается напрямую и без побочных эффектов. За float осталась исходная, честная задача — обтекание врезки текстом. В новом коде использовать его для раскладки нет причин, но знать о нём необходимо: он до сих пор встречается в старых кодовых базах, и понимание его механики нужно, чтобы такой код читать и переписывать.

Flexbox: одномерный layout

Главная и поперечная оси, контейнер и элементы

Flexbox (полное название — CSS Flexible Box Layout) — первый из двух современных модулей, спроектированных специально для раскладки 4. Его назначение — распределять элементы вдоль одной оси: в ряд или в столбец. Одномерность — ключевая характеристика: Flexbox управляет раскладкой по одному направлению, оставляя перпендикулярное на втором плане.

Раскладка включается объявлением display: flex на контейнере. Его прямые потомки автоматически становятся флекс-элементами и выстраиваются вдоль главной оси (англ. main axis); перпендикулярная ей — поперечная ось (англ. cross axis). Направление главной оси задаёт свойство flex-direction: row (по умолчанию, слева направо) или column (сверху вниз). Всё поведение флекс-контейнера описывается в терминах этих двух осей, поэтому с них и стоит начинать: сначала определить, где главная ось, а затем читать остальные свойства как распределение вдоль неё и поперёк неё.

Флекс-контейнер: главная ось с justify-content, поперечная ось с align-items
Оси Flexbox и свойства выравнивания вдоль каждой из них

Свойства распределения: justify-content, align-items, gap

Два свойства управляют выравниванием, и различаются они осью. justify-content распределяет элементы вдоль главной оси: прижать к началу (flex-start), к концу (flex-end), по центру (center), разложить с равными промежутками (space-between, space-around, space-evenly). align-items выравнивает элементы поперёк, по поперечной оси: flex-start, flex-end, center, stretch (растянуть на всю высоту контейнера — значение по умолчанию), baseline (по базовой линии текста).

Держать в голове, какое свойство по какой оси работает, проще всего через привязку к назначению, а не к слову: justify-content — «главная», align-items — «поперечная». При flex-direction: column оси меняются местами, и теперь уже justify-content управляет вертикалью — это регулярно сбивает с толку, пока не привыкнешь думать осями, а не «горизонталью и вертикалью».

Промежутки между элементами задаёт свойство gap. До него интервалы приходилось расставлять через margin на самих элементах, что порождало возню с крайними элементами (лишний отступ у первого или последнего). gap добавляет промежутки только между элементами, не по краям, и работает как во Flexbox, так и в Grid — это одно из самых удобных приобретений современного CSS.

flex-grow, flex-shrink, flex-basis: реакция на переполнение

«Flexible» в названии — про способность элементов растягиваться и сжиматься, деля свободное или недостающее место. Поведением каждого элемента управляют три свойства.

flex-basis задаёт базовый размер элемента вдоль главной оси до перераспределения — своего рода стартовую ширину (или высоту в колонке). flex-grow — коэффициент, с которым элемент забирает избыток свободного места: при flex-grow: 0 (по умолчанию) элемент не растягивается, при 1 — растёт, деля излишек с другими растущими элементами пропорционально их коэффициентам. flex-shrink — зеркальный коэффициент сжатия при нехватке места: при 1 (по умолчанию) элемент сжимается, при 0 — сохраняет размер, отказываясь ужиматься.

На практике эти три свойства почти всегда задают одной сокращённой записью flex:

.sidebar { flex: 0 0 240px; }  /* не растёт, не сжимается, ровно 240px */
.content { flex: 1 1 auto; }   /* забирает всё оставшееся место */

Запись flex: 1 (эквивалент flex: 1 1 0) — самый частый идиом: «пусть элементы поделят доступную ширину поровну». Комбинацией фиксированных и гибких элементов описывается большинство панельных раскладок: боковая колонка неизменной ширины и основная область, занимающая остальное.

Типовые паттерны

Несколько задач раскладки встречаются так часто, что стали каноническими, и Flexbox решает их короче всего.

Центрирование по обеим осям — задача, которая в старом CSS требовала ухищрений, а здесь занимает три строки:

.center {
  display: flex;
  justify-content: center;  /* по главной оси */
  align-items: center;      /* по поперечной */
}

Прижатый к низу футер (англ. sticky footer) — подвал, который держится у нижнего края окна, даже когда контента мало, но уходит вниз за содержимым, когда его много. Решается вертикальным флекс-контейнером на всю высоту вьюпорта, у которого основная область растягивается:

body {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
main { flex: 1; }  /* забирает всё свободное место, выталкивая футер вниз */

Классическая трёхколоночная раскладка (англ. holy grail) — шапка, подвал и три колонки между ними (навигация, контент, боковая панель) — тоже собирается на Flexbox, хотя для неё, как и для любой двумерной задачи, естественнее подходит Grid, к которому мы сейчас и перейдём.

Grid: двумерный layout

Линии, треки, ячейки, зоны

Grid (CSS Grid Layout) — второй модуль раскладки, и его отличие от Flexbox принципиально: Grid работает сразу в двух измерениях, управляя строками и колонками одновременно 5. Там, где Flexbox раскладывает поток элементов вдоль одной оси, Grid задаёт заранее спроектированную сетку, в ячейки которой элементы расставляются.

Терминология сетки опирается на четыре понятия. Линии (англ. grid lines) — горизонтальные и вертикальные разделители, нумеруемые с единицы (и с конца — отрицательными числами). Треки (англ. tracks) — полосы между соседними линиями, то есть колонки и строки. Ячейки — пересечения одной строки и одной колонки, наименьшая единица сетки. Зоны (англ. areas) — прямоугольные группы ячеек, которым можно дать имя и адресовать целиком.

Анатомия Grid: нумерованные линии, треки-колонки и строки, ячейка, именованная зона, gap
Линии, треки, ячейки и зоны сетки Grid

Сетка объявляется на контейнере через display: grid и описание треков:

.layout {
  display: grid;
  grid-template-columns: 240px 1fr;   /* колонка 240px и колонка «остальное» */
  grid-template-rows: auto 1fr auto;  /* шапка по содержимому, тело, подвал */
  gap: 16px;
}

Здесь появляется единица fr (fraction) — доля свободного места, аналог flex-grow для сетки. grid-template-columns: 1fr 2fr делит ширину в отношении 1 : 2; 240px 1fr отдаёт первой колонке фиксированные 240 px, а второй — весь остаток. fr избавляет от ручного расчёта процентов и корректно учитывает gap.

Явная и неявная сетка; grid-template-areas

Треки, заданные через grid-template-columns и grid-template-rows, образуют явную сетку. Но элементов может оказаться больше, чем ячеек; тогда Grid достраивает неявные треки автоматически. Их размер задаётся свойствами grid-auto-rows и grid-auto-columns, а направление, в котором сетка прирастает, — grid-auto-flow. Так ведёт себя, например, лента карточек: колонок задано фиксированное число, а строки создаются по мере поступления карточек.

Размещать элементы по сетке можно двумя способами. Через номера линий — grid-column: 1 / 3 (от первой до третьей вертикальной линии, то есть на две колонки) — или, наглядно, через именованные зоны. Второй способ превращает раскладку в почти графическую схему:

.page {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
}
.page > header  { grid-area: header; }
.page > nav     { grid-area: sidebar; }
.page > main    { grid-area: main; }
.page > footer  { grid-area: footer; }

Текстовая «картинка» в grid-template-areas читается как план этажа: видно, что шапка и подвал тянутся на обе колонки, а середина разделена на боковую панель и основную область. Это одно из самых выразительных мест CSS — раскладка описывается декларативно и понятна с первого взгляда, а перестроить её под другой размер экрана можно, переписав одну эту «картинку» в медиа-запросе.

Адаптивные сетки: auto-fit, auto-fill, minmax

Особую ценность Grid раскрывает в связке функций repeat, minmax и ключевых слов auto-fit / auto-fill, дающих сетку, которая сама подстраивает число колонок под доступную ширину — без единого медиа-запроса:

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
}

Читается это так: создавай столько колонок, сколько поместится, при условии что каждая не уже 240 px и не шире равной доли остатка. На широком экране карточки лягут в четыре-пять колонок, на планшете — в две, на телефоне — в одну, и всё это описано единственным правилом. Разница между auto-fit и auto-fill тонкая и проявляется, когда элементов меньше, чем помещается колонок: auto-fit схлопывает пустые треки, растягивая имеющиеся карточки на всю ширину, а auto-fill сохраняет пустые колонки, оставляя карточки исходного размера. Этот приём — «Repeat, Auto-fit, Minmax» — настолько распространён, что стал почти шаблоном для сеток карточек, плиток и галерей.

Критерии выбора между Grid и Flexbox

Grid и Flexbox не конкуренты, а инструменты для разных задач, и выбор между ними сводится к одному вопросу: раскладка одномерна или двумерна.

Flexbox естествен, когда элементы выстраиваются вдоль одной оси и их размер должен зависеть от содержимого: панель инструментов, ряд кнопок, список тегов, горизонтальное меню. Его логика — «от контента»: элементы сами занимают столько места, сколько им нужно, и делят остаток. Grid естествен, когда нужно управлять двумя измерениями сразу или задать жёсткую структуру, в которую контент вписывается: макет страницы целиком, сетка карточек с выравниванием по строкам и колонкам, сложные формы. Его логика — «от раскладки»: сначала проектируется сетка, затем в неё расставляется содержимое.

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

Адаптивная вёрстка

Подход mobile-first

Одна и та же страница должна быть удобной и на телефоне шириной 360 px, и на мониторе шириной 1920 px. Подход, ставший стандартом, — mobile-first: базовые стили пишутся для узкого экрана, а стили для широких добавляются поверх, по мере роста доступного места. Причина не только в растущей доле мобильного трафика. Раскладка для узкого экрана обычно проще — один столбец, вертикальный поток, — и надстраивать над простой основой усложнения удобнее, чем упрощать сложное. Технически mobile-first выражается в том, что дополнительные правила навешиваются медиа-запросами с условием min-width: «начиная с такой-то ширины — применить». Это согласуется с идеей прогрессивного улучшения: сначала работоспособная база, затем обогащение возможностями там, где для них есть место.

Медиа-запросы и брейкпоинты

Медиа-запрос (англ. media query) — условие, при котором применяется группа правил; в теме 2, вводя prefers-color-scheme, мы обещали разобрать этот механизм здесь 6. Для адаптивной раскладки главная медиа-фича — ширина вьюпорта:

/* база: один столбец, mobile-first */
.grid { display: grid; grid-template-columns: 1fr; gap: 16px; }

/* с 768px — две колонки */
@media (min-width: 768px) {
  .grid { grid-template-columns: repeat(2, 1fr); }
}

/* с 1200px — четыре */
@media (min-width: 1200px) {
  .grid { grid-template-columns: repeat(4, 1fr); }
}

Ширина, при которой раскладка меняется, называется точкой разрыва (англ. breakpoint). Распространённая ошибка — привязывать брейкпоинты к диагоналям популярных устройств: модельный ряд меняется, а «айфонные» 375 px устаревают. Правильнее выбирать точки разрыва по содержимому: там, где раскладка начинает выглядеть плохо — строки становятся слишком длинными, карточки чрезмерно широкими, — там и ставить брейкпоинт, независимо от того, какому устройству эта ширина соответствует.

Container Queries как альтернатива медиа-запросам

У медиа-запросов есть принципиальное ограничение: они реагируют на размер вьюпорта, а не на размер места, отведённого конкретному компоненту. Одна и та же карточка может стоять и в узкой боковой колонке, и в широкой основной области; вьюпорт при этом один, а вот пространства у карточки в двух местах разное — и медиа-запрос эту разницу не различает. Компонент оказывается вынужден «знать» о глобальной ширине окна, хотя логично ему было бы реагировать на собственный контейнер.

Эту брешь закрывают контейнерные запросы (англ. container queries) — относительно недавнее дополнение CSS 7. Родительский элемент объявляется контейнером, а его потомки получают возможность реагировать на его размер:

.card-host { container-type: inline-size; }

@container (min-width: 400px) {
  .card { grid-template-columns: auto 1fr; }  /* картинка слева от текста */
}

Теперь карточка перестраивается сама, исходя из ширины отведённого ей места, где бы её ни разместили. Это сдвиг от «страница знает про все свои компоненты» к «компонент самодостаточен и заботится о себе» — то, что давно ожидалось от по-настоящему модульного, переиспользуемого интерфейса. Медиа-запросы не отменяются: они по-прежнему уместны для решений уровня всей страницы (общий каркас, поля, глобальная типографика), тогда как контейнерные запросы — для адаптации отдельных компонентов.

Гибкий layout без точек разрыва

Крайняя точка развития адаптивности — раскладка, которая почти не нуждается в явных брейкпоинтах, а плавно подстраивается сама. Такой подход называют интринсивным дизайном (англ. intrinsic web design, термин Джен Симмонс) 8. Он опирается на уже знакомые нам средства: clamp и min/max из темы 2 для «жидких» размеров, сетки на repeat(auto-fit, minmax(...)), свойство flex-wrap для рядов, переносящихся по мере нехватки места. Вместо ступенчатого переключения между фиксированными макетами на заданных ширинах раскладка непрерывно течёт, занимая ровно столько места, сколько есть.

Дисциплина здесь в том, чтобы поручать вычисление размеров самому CSS, а не перечислять вручную случаи для каждого диапазона. Правило grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)) заменяет три медиа-запроса из примера выше — и делает это устойчивее, потому что не привязано ни к каким конкретным порогам. На практике интринсивный подход и брейкпоинты сочетают: мелкую адаптацию отдают гибким единицам и авторастущим сеткам, а явные точки разрыва оставляют для немногих случаев, где раскладка должна перестроиться качественно, а не просто сжаться.

Итоги темы

Раскладка в CSS — это несколько слоёв механизмов, надстроенных друг над другом. В основании лежит нормальный поток: блочные элементы идут сверху вниз, строчные — слева направо, и большая часть контента раскладывается им без вмешательства. Позиционирование через position выводит отдельные элементы из потока и привязывает их к предку, вьюпорту или порогу прокрутки; вместе с ним приходит контекст наложения, объясняющий, почему z-index работает не так прямолинейно, как кажется. Устаревший float из инструмента раскладки вернулся к своей единственной честной роли — обтеканию врезки текстом.

Основную работу по раскладке сегодня делят два специализированных модуля. Flexbox распределяет элементы вдоль одной оси и хорош, когда размер идёт от содержимого; Grid проектирует двумерную сетку, в которую вписывается контент. Выбор между ними — вопрос размерности задачи, а не вкуса, и на практике они работают в связке: Grid держит каркас страницы, Flexbox — ряды внутри него. Адаптивность выстраивается поверх всего этого: mobile-first как отправная точка, медиа-запросы для решений уровня страницы, контейнерные запросы для самодостаточных компонентов и гибкие единицы для раскладки, которая подстраивается сама, обходясь без лишних точек разрыва. Освоив эти механизмы, можно собрать интерфейс, одинаково пригодный от телефона до широкого монитора, — что и станет задачей практического занятия 3.

Литература

  1. Consortium} {. W. W. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. — 2011, https://www.w3.org/TR/CSS21/.
  2. Consortium} {. W. W. CSS Display Module Level 3. — 2023, https://www.w3.org/TR/css-display-3/.
  3. Consortium} {. W. W. CSS Positioned Layout Module Level 3. — 2023, https://www.w3.org/TR/css-position-3/.
  4. Consortium} {. W. W. CSS Flexible Box Layout Module Level 1. — 2018, https://www.w3.org/TR/css-flexbox-1/.
  5. Consortium} {. W. W. CSS Grid Layout Module Level 2. — 2023, https://www.w3.org/TR/css-grid-2/.
  6. Consortium} {. W. W. Media Queries Level 5. — 2024, https://www.w3.org/TR/mediaqueries-5/.
  7. Consortium} {. W. W. CSS Containment Module Level 3. — 2024, https://www.w3.org/TR/css-contain-3/.
  8. Bell A., Pickering H. Every Layout: Relearn CSS Layout. — 2023, https://every-layout.dev/.

Дополнительные материалы. Тема 3. Layout: позиционирование, Flexbox, Grid, адаптивность

Поток документа и модели отображения

  • MDN: поточная раскладка CSS — определение нормального потока и различий между блочными и строчными элементами, со ссылками на смежные темы: контексты форматирования, взаимодействие потока с переполнением и режимами письма.
  • MDN: введение в контексты форматирования — обзор всех типов контекстов форматирования (блочного, строчного, флекс- и грид-контекста) и условий, при которых каждый из них возникает.
  • MDN: блочный контекст форматирования — способы создания BFC (float, overflow, display: flow-root и др.) и то, как новый контекст решает две конкретные задачи: содержит внутри себя плавающие элементы и отменяет схлопывание margin с соседями.
  • HTML Academy: свойство display — разбор значений block, inline, inline-block и none на примерах кода и скриншотах.

Позиционирование

  • HTML Academy: CSS position — разбор всех пяти значений position с примерами кода, скриншотами и отдельным разделом про z-index и доступность.
  • MDN Learn Web Development: позиционирование — учебный модуль с пошаговыми примерами для каждого значения position, живыми демонстрациями в отдельных файлах и тестами для самопроверки в конце.
  • SF Education: как работает CSS position — текстовое объяснение назначения и контекста применения каждого значения position без примеров кода.

Flexbox: одномерный layout

  • Flexbox Froggy — браузерная игра-тренажёр: свойства флекс-контейнера отрабатываются на серии уровней, где нужно расставить лягушек по кувшинкам.
  • Дока: гайд по Flexbox — руководство по всем свойствам флекс-контейнера и флекс-элементов с интерактивными демо для каждого свойства и разделом вопросов для собеседований.

Grid: двумерный layout

  • CSS Grid Garden — браузерная игра-тренажёр на свойства Grid: нужно поливать грядки с морковью, управляя сеткой через код.
  • Grid by Example — сайт Рейчел Эндрю с короткими видео и интерактивными примерами по функциям спецификации Grid, а также готовыми шаблонами для типовых задач раскладки; на английском языке.
  • Дока: гайд по Grid — руководство по свойствам грид-контейнера и элементов с демо и наглядными диаграммами линий, ячеек и треков.
  • Flex vs Grid: объяснение разницы на практике (блог Timeweb) — сравнение на четырёх сценариях («карточки в ряд», «кнопка внизу карточки», «облако тегов», «макет страницы»), какой из двух модулей раскладки решает задачу естественнее.

Адаптивная вёрстка

  • MDN Learn Web Development: отзывчивый дизайн — учебный модуль о происхождении подхода, mobile-first, медиавыражениях и роли Flexbox, Grid и Multicol как изначально отзывчивых инструментов раскладки; отдельно разбирает адаптацию изображений, типографики и метатег viewport.
  • MDN: использование медиавыражений — справочник по синтаксису @media: типы устройств, медиа-фичи (min-width, hover и др.), логические операторы and, not, only и запись через запятую.
  • fruntend: полное руководство по Container Queries в CSS — синтаксис и свойства container-type, container-name, container на примере одной и той же карточки в широком и узком контейнере, сравнение с медиа-запросами, таблица поддержки браузерами.
  • Jen Simmons: Everything You Know About Web Design Just Changed (An Event Apart, YouTube) — запись доклада 2018 года, в котором введён термин «интринсивный дизайн»: разбор перехода от вёрстки, собираемой обходными приёмами, к раскладке, описываемой напрямую средствами Grid и Flexbox.