Основы CSS верстки для веб-разработчиков

Логотип CSSМногие разработчики, особенно те, кто пришел в веб из других областей программирования, сталкиваются с парадоксом CSS. С одной стороны, его синтаксис кажется предельно простым: селекторы, декларации, правила и т.д.. С другой — создание даже базовых, устойчивых макетов часто превращается в хаотичное перебирание свойств и значений в надежде, что «вот сейчас заработает».

Причина этой боли кроется в фундаментальном непонимании. Нас часто учат что делать (какие свойства использовать), но почти никогда не объясняют как и почему это работает. CSS-верстка — это не язык разметки, а система взаимосвязанных алгоритмов компоновки.

Представьте, что вы пытаетесь выучить JavaScript, только глядя на синтаксис переменных и циклов, не понимая концепций замыканий, контекста выполнения или прототипов. Это обречено на провал. Данная статья — попытка построить тот самый фундамент, на котором можно уверенно строить любые интерфейсы.

Основы CSS верстки для веб-разработчиков

Фундаментальные принципы

Первый и самый важный принцип, который нужно усвоить раз и навсегда:

В CSS всё является боксом (коробкой).

Каждый элемент на странице, будь то заголовок, параграф, ссылка или изображение, генерирует прямоугольную область (бокс). Весь процесс верстки можно свести к трем простым шагам: браузер получает множество этих боксов, затем располагает их на экране, следуя определенным алгоритмам компоновки.

Этот подход унаследован от полиграфии и вёрстки документов, где элементы тоже имеют свою область. Однако ключевое отличие веба в том, что процесс происходит динамически, «на лету», по правилам, заложенным в браузере. Исходный алгоритм, который управляет этим процессом по умолчанию, называется «нормальным потоком» (Normal Flow). Именно с него начинается любая вёрстка.

Пример 1

Свёрстанная страница в нормальном потоке.

<h1>Заголовок</h1>
<p>Параграф текста с <span>выделенным элементом</span> внутри.</p>
<ul>
  <li>Элемент списка 1</li>
  <li>Элемент списка 2</li>
</ul>

Нормальный поток: основа основ

Когда вы не применяете к элементам специальные свойства для изменения их поведения (вроде display: flex), они располагаются согласно нормальному потоку. Это базовый алгоритм, созданный для отображения текстовых документов. Его логика проста и соответствует чтению: в западных языках элементы выстраиваются слева направо и сверху вниз.

Нормальный поток в CSS

В CSS эти направления имеют специальные имена:

  1. Инлайн-направление (inline direction): основное направление текста (по умолчанию — слева направо). В этом направлении выстраиваются так называемые инлайн-элементы (текст, картинки, <span>, <strong>).
  2. Блочное направление (block direction): направление, в котором блоки «падают» под действием силы тяжести документа (по умолчанию — сверху вниз). В этом направлении располагаются блочные элементы (заголовки, параграфы <p>, разделы <div>).

Браузеры поставляются со встроенной таблицей стилей, которая определяет, какие теги по умолчанию являются блочными, а какие — строчными. Именно поэтому семантически правильный HTML-документ без единой строчки CSS уже выглядит как структурированная страница.

Пример 2

Стилизация в рамках нормального потока

p {
  /* Блочный элемент: имеет ширину, margin сверху/снизу */
  margin-bottom: 1em;
  width: 80%;
  max-width: 600px;
}

strong {
  /* Инлайн-элемент: обтекает текст, не ломает поток */
  color: #d35400;
  font-weight: bold;
}

Блочная модель: из чего сделан бокс

Понимание того, что всё — это бокс, приводит нас к ключевой концепции: блочной модели (Box Model). Она описывает, как вычисляются размеры каждого бокса. Он состоит из нескольких концентрических слоев, начиная от центра:

Блочная модель в CSS: margin, border, padding, content
  1. Контент: внутренняя область, где отображается текст или дочерние элементы. Её размеры можно задать через width и height.
  2. Внутренний отступ: прозрачная область вокруг контента, отделяющая его от границы. Задаётся свойством padding.
  3. Граница: линия (или стиль), окружающая padding и контент. Задаётся свойством border.
  4. Внешний отступ: прозрачная область вне границы, которая отталкивает соседние элементы. Задаётся свойством margin.

Здесь кроется историческая сложность: по умолчанию в браузерах используется модель content-box. В ней свойство width: 200px задаёт ширину только области контента. padding и border добавляются к ней снаружи, в итоге реальная ширина элемента становится больше.

Пример 3

Использование модели content-box (в браузерах по умолчанию).

.box-content {
  box-sizing: content-box; /* Значение по умолчанию */
  width: 200px;
  padding: 20px;
  border: 5px solid blue;
  /* Фактическая ширина = 200px + 20px (левый паддинг) + 20px (правый паддинг) + 5px (левая граница) + 5px (правая граница) = 250px */
}

Для упрощения жизни разработчиков появилась модель border-box. В ней width: 200px задаёт ширину всего бокса целиком, включая padding и border. Область контента при этом сжимается, чтобы уместить эти значения. Эта модель интуитивно понятнее и стала стандартом де-факто.

Пример 4

Использование модели border-box (у разработчиков де-факто).

.box-border {
  box-sizing: border-box; /* Рекомендуемое значение */
  width: 200px;
  padding: 20px;
  border: 5px solid green;
  /* Фактическая ширина остаётся 200px! */
  /* Ширина контента = 200px - 20px - 20px - 5px - 5px = 150px */
}

Всегда добавляйте в начало ваших стилей правило, которое сбрасывает модель для всех элементов на border-box. Это сэкономит вам массу нервов.

Пример 5

Фиксируем модель border-box для всех элементов на странице.

*,
*::before,
*::after {
  box-sizing: border-box;
}

Особенности инлайн-боксов и схлопывание отступов

Поведение инлайн-боксов существенно отличается от блочных. Поскольку они существуют внутри строк текста, их вертикальные отступы (margin-top, margin-bottom) и явные высоты не работают. Их границы и отступы также ведут себя неочевидно: если инлайн-элемент переносится на несколько строк, его бокс визуально «разрывается».

Разрыв инлайн-бокса при переносе строки в CSS

Пример 6

«Странное поведение» инлайн-элементов.

<p>Это длинный текст, и вот <span class="highlight">этот выделенный инлайн-элемент</span> может вести себя странно при переносе.</p>
.highlight {
  background-color: yellow;
  padding: 0 5px; /* Работает */
  margin: 0 10px; /* Работает по горизонтали */
  /* margin-top: 20px; НЕ РАБОТАЕТ! */
  border-left: 2px solid red;
  border-top: 2px solid red; /* Визуально разорвётся при переносе */
}

Схлопывание вертикальных отступов

Ещё одна «магия» нормального потока — схлопывание вертикальных отступов (Margin Collapse). Когда два блочных элемента расположены друг под другом, вертикальное пространство между ними определяется не суммой их отступов (margin-bottom первого + margin-top второго), а большим из этих двух значений. Это поведение унаследовано от типографики для равномерного распределения абзацев.

Схлопывание вертикальных отступов элементов в CSS

Пример 7

Схлопывание вертикальных отступов.

.block-a {
  margin-bottom: 40px;
  background: lightblue;
}

.block-b {
  margin-top: 20px; /* Этот отступ СХЛОПНЕТСЯ с margin-bottom: 40px сверху */
  background: lightcoral;
}
/* Итоговое расстояние между элементами — 40px, а не 60px. */

Схлопывание также происходит между родителем и первым/последним дочерним элементом, если между ними нет «преграды» (границы, внутреннего отступа или контента). Чтобы его предотвратить, можно:

  1. Добавить родителю padding-top: 1px или border-top: 1px solid transparent.
  2. Использовать более современный и чистый способ: создать новый контекст форматирования с помощью display: flow-root.

Пример 8

Предотвращаем схлопывание вертикальных отступов.

.parent {
  display: flow-root; /* Лучший способ предотвратить схлопывание */
  background: #eee;
}

.child {
  margin-top: 30px; /* Теперь отступ останется внутри родителя */
}
Робот собирает из блоков сайт

Собери свой код. Запусти сайт!

От наброска на салфетке до первого работающего лендинга. Наш онлайн-курс «Веб-верстка с нуля и до профессионала» — это интенсивный трек, где ты не будешь зубрить теорию, а с первого дня начнешь превращать идеи в чистый HTML и CSS.

Собери свой первый проект под руководством практикующих разработчиков.

Подробнее о курсе

Позиционирование: вывод элементов из потока

Алгоритм позиционирования (Positioning) позволяет нам вручную управлять расположением боксов, вплоть до полного вывода их из нормального потока. Это ключ к созданию сложных, многослойных интерфейсов. Активируется свойством position.

Значение Находится в потоке? Точка отсчёта Основное назначение
static (по умолчанию) Да Не применимо Обычное поведение в потоке.
relative Да Его обычное место в потоке Создание контекста для абсолютно позиционированных детей. Смещение элемента относительно себя самого (свойства top, left).
absolute Нет Ближайший предок с position не static Точное позиционирование внутри заданной области (например, иконка внутри кнопки).
fixed Нет Окно просмотра (viewport) Элементы, закреплённые на экране (шапка, модальные окна).
sticky Да (до «прилипания») Ближайший прокручиваемый предок Гибридная модель: элемент ведёт себя как relative, пока не достигнет заданной позиции на экране, затем «прилипает» как fixed.

Знание того, как работает margin в связке с фиксированной шириной, позволяет легко центрировать блочный элемент.

Пример 9

Центрирование элемента по горизонтали.

.centered-block
.centered-block {
  width: min(600px, 100%); /* Фиксированная или процентная ширина */
  margin-left: auto; /* Браузер вычисляет отступ слева */
  margin-right: auto; /* Браузер вычисляет отступ справа */
  /* Доступное пространство по горизонтали делится поровну между двумя auto-отступами. */
}

Контекст наложения (Stacking Context) и z-index

Когда мы начинаем двигать элементы с помощью позиционирования, они могут начать перекрывать друг друга. Так мы входим в третье измерение CSS — глубину, управляемую свойством z-index. Однако z-index работает не в вакууме, а внутри контекстов наложения (Stacking Context).

Контекст наложения — это изолированный слой. z-index элемента влияет только на его положение внутри контекста наложения своего родителя. Самый распространённый способ создать новый контекст — задать элементу position (кроме static) и z-index (кроме auto). Это же делают opacity < 1, transform, filter и другие свойства.

Проблема

Элемент с z-index: 1000 может быть перекрыт элементом с z-index: 1, если первый находится внутри контекста наложения с низким z-index, а второй — в контексте с более высоким.

Пример 10

Особенности наложения элементов.

Особенности наложения элементов в CSS
<div class="parent-a" style="position: relative; z-index: 1;">
  <div class="child" style="position: absolute; z-index: 1000;">Я внутри parent-a</div>
</div>
<div class="parent-b" style="position: relative; z-index: 2;">
  <div class="child" style="position: absolute; z-index: 1;">Я внутри parent-b</div>
</div>

В этом примере синий блок (z-index: 1) будет поверх фиолетового (z-index: 1000), потому что контекст наложения parent-b (z-index: 2) находится выше parent-a (z-index: 1).

Для явного создания контекста без побочных эффектов позиционирования используйте isolation: isolate.

Пример 11

Применение нового контекста наложения с помощью isolation: isolate.

.modal-overlay {
  isolation: isolate; /* Создаёт новый контекст наложения */
  /* Теперь z-index детей модального окна не будет «конкурировать» с z-index элементов вне этого оверлея */
}

Flexbox и Grid: современные системы компоновки

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

Flexbox (одномерная компоновка) фокусируется на распределении пространства и выравнивании элементов вдоль одной оси (горизонтальной или вертикальной). Его философия — дать контейнеру возможность гибко управлять размерами и порядком своих непосредственных детей.

Пример 12

Применение одномерной компоновки.

123
.flex-container {
  display: flex; /* Включаем алгоритм Flexbox */
  justify-content: space-between; /* Распределяем дочерние элементы по главной оси */
  align-items: center; /* Выравниваем элементы по поперечной оси по центру */
  flex-wrap: wrap; /* Позволяем перенос на новую строку */
}

.flex-item {
  flex: 1 1 200px; /* Сочетание роста, сжатия и базового размера */
}

CSS Grid (двумерная компоновка) позволяет вам сначала определить сетку (строки и колонки), а затем точно размещать элементы в созданных областях. Это делает Grid идеальным для макетов всего сайта.

Пример 13

Применение двумерной компоновки.

ШапкаБоковая панельОсновное содержаниерекламаПодвал
.grid-container {
  display: grid; /* Включаем алгоритм Grid */
  grid-template-columns: 1fr 2fr 1fr; /* Определяем три колонки */
  grid-template-rows: auto 1fr auto; /* Определяем три строки */
  gap: 20px; /* Расстояние между элементами сетки */
  grid-template-areas:
    "header header header"
    "sidebar main ads"
    "footer footer footer";
}

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }

Ключевое отличие от старой модели: и Flexbox, и Grid используют современную, единую систему выравнивания (align-items, justify-content), которая больше не зависит от свойств шрифта (как vertical-align) и работает предсказуемо, ориентируясь на границы боксов.

Логические свойства и адаптация к языкам

CSS развивается в сторону независимости от физического направления. Не все языки пишутся слева направо (арабский, иврит), а некоторые — сверху вниз (классический китайский, японский). Логические свойства заменяют физические понятия («верх», «низ», «лево», «право») на логические, связанные с режимом письма (writing-mode).

  • Вместо width/heightinline-size/block-size.
  • Вместо margin-leftmargin-inline-start.
  • Вместо top/bottom при позиционировании — inset-block-start/inset-block-end.

Использование логических свойств делает ваш код более устойчивым и адаптируемым.

Пример 14

Применяем логические свойства.

.card {
  /* Физические свойства */
  margin-left: 1rem;
  padding-top: 2rem;
  border-right: 2px solid;

  /* Логические эквиваленты (рекомендуется) */
  margin-inline-start: 1rem;
  padding-block-start: 2rem;
  border-inline-end: 2px solid;
}
/* Если поменять writing-mode родителя, логические свойства адаптируются автоматически. */

Часто задаваемые вопросы о CSS верстке

Почему margin-top дочернего элемента «выпадает» из родителя?

Это происходит из-за схлопывания вертикальных отступов. Если между margin-top первого дочернего элемента и margin-top родителя нет «преграды» (границы, внутреннего отступа или контента), браузер объединяет эти отступы, применяя результат за пределами родительского блока. Чтобы этого избежать, создайте новый контекст форматирования для родителя с помощью display: flow-root или добавьте ему padding-top: 1px.

Когда использовать Flexbox, а когда Grid?

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

Что такое «содержащий блок» (containing block) и почему это важно?

Содержащий блок — это прямоугольная область, относительно которой вычисляются размеры и положение текущего элемента. Например, процентная ширина width: 50% берётся от ширины содержащего блока. Понимание этого критично для работы с процентами и абсолютным позиционированием: для position: absolute содержащим блоком становится ближайший предок с position, отличным от static, а не просто родительский div.

Почему z-index иногда не работает?

Свойство z-index действует только в пределах одного контекста наложения (stacking context). Если ваш элемент находится внутри контекста с низким z-index, он никогда не сможет «перепрыгнуть» элемент из контекста с более высоким z-index, даже если его собственное значение огромно. Контекст создают не только position и z-index, но и свойства вроде opacity (меньше 1) или transform. Решение — вынести элементы в один контекст или явно управлять созданием контекстов с помощью isolation: isolate.

В чём разница между box-sizing: content-box и border-box?

Это два разных алгоритма расчёта размеров элемента. При box-sizing: content-box (значение по умолчанию) свойства width и height задают размер только области контента, а padding и border добавляются к нему снаружи. В модели border-box свойства width и height определяют размер всего бокса целиком (включая padding и border), что делает расчёты интуитивно понятнее. Именно поэтому * { box-sizing: border-box; } стало стандартом для большинства CSS-сбросов.

Как правильно центрировать элемент по вертикали в современном CSS?

Самый простой и универсальный современный способ — использование place-content: center на контейнере, у которого задана высота. Это работает для элементов с display: grid, display: flex и даже для display: block (при поддержке браузером). Альтернативно, во Flexbox можно использовать комбинацию align-items: center и justify-content: center, а в Grid — place-items: center. Главное — помнить, что для вертикального центрирования у контейнера должна быть явно заданная высота.

Зачем нужны логические свойства в CSS?

Логические свойства (например, margin-inline-start вместо margin-left) привязывают стили не к физическим сторонам экрана («левый», «правый»), а к началу и концу контекста письма (writing mode). Это делает ваш код адаптивным не только к разным размерам экрана, но и к разным языкам и направлениям письма (слева-направо, справа-налево, сверху-вниз). Использование логических свойств — это шаг к созданию по-настоящему интернациональных и доступных интерфейсов.

Как системно изучать CSS-верстку

Освоение CSS-верстки — это не заучивание сотен свойств, а понимание нескольких ключевых систем и их взаимодействия. Начните с прочного фундамента: боксовая модель и нормальный поток. Затем освойте механизмы выхода из потока — позиционирование. Только после этого переходите к мощным инструментам компоновки — Flexbox и Grid. Понимание контекстов наложения и логических свойств станет завершающим штрихом, который превратит вас из того, кто «подбирает стили», в того, кто уверенно проектирует макеты.

Хотите перейти от теории к практике и научиться применять эти концепции для создания современных, адаптивных и сложных интерфейсов под руководством опытных наставников? Запишитесь на наш интенсивный онлайн-курс по продвинутому CSS и вёрстке в нашей веб-студии. Мы разберём реальные кейсы, выстроим чёткую систему знаний, и вы начнёте не бояться макетов, а управлять ими.

Теги: