Веб-разработка

CSS: от каскада до Grid

Цели урока

  • Понимать алгоритм специфичности и каскада CSS
  • Строить одномерные раскладки на Flexbox с flex-grow/shrink/basis
  • Создавать двумерные layouts на CSS Grid с named areas и auto-fill
  • Применять mobile-first подход, clamp() и Container Queries

Предварительные знания

  • HTML и семантическая вёрстка

HTML без CSS - это газета 1995 года: чёрный текст на белом фоне, Times New Roman, никакой структуры. CSS превращает скелет в интерфейс. Но CSS коварен: два правила конфликтуют и непонятно почему, элемент не центрируется, layout рассыпается на мобильном. GitHub в 2020 переписал свои стили и сократил объём CSS на 30% - именно потому что понимание каскада и Grid превратило хаос в систему.

  • **GitHub** перешёл на CSS Grid для layout в 2020 году, сократив CSS-код на 30% и устранив баги с вложенными Flexbox
  • **Every Layout** (проект Heydon Pickering) показал, что 90% layouts строится из 7 CSS-паттернов без media queries
  • **Container Queries** позволяют Shopify создавать виджеты, которые автоматически адаптируются к любому сайту клиента

CSS: от таблиц до Grid

До 1996 года веб-разработчики верстали layout через HTML-таблицы - это был единственный способ создать колонки. CSS 1.0 (1996) принёс базовое форматирование текста, но не решил проблему layout. Десятилетие продолжалась эпоха float-верстки - колонки на основе float с clearfix-хаками. Flexbox появился в 2012 году и вошёл во все браузеры к 2015. CSS Grid - в 2017. До него единственным нативным решением для двумерных layouts были либо таблицы, либо нагромождения Flexbox. Container Queries - последняя революция, 2023 год: компоненты наконец могут адаптироваться к своему контейнеру, а не к окну браузера.

Селекторы и специфичность

**GitHub в 2020 году мигрировал с Sass на нативный CSS - и сократил кодовую базу стилей на 30%.** Причина: война специфичностей разрослась до состояния, когда никто не понимал, почему один стиль перебивает другой. CSS работает по принципу «найти элемент - применить стиль», и когда два правила конфликтуют - побеждает тот, у кого выше **специфичность** (specificity).

ТипПримерСпецифичность
inline stylestyle="color: red"1,0,0,0
#id#header0,1,0,0
.class, [attr], :pseudo-class.nav, [type="text"], :hover0,0,1,0
element, ::pseudo-elementdiv, p, ::before0,0,0,1
* (универсальный)*0,0,0,0

**Каскад** - алгоритм разрешения конфликтов. Приоритет (от высшего к низшему): 1) `!important` 2) inline styles 3) специфичность селектора 4) порядок в файле (позднее правило побеждает). **!important - крайняя мера.** Каждый `!important` создаёт долг, который придётся «перебивать» другим `!important`.

**BEM (Block Element Modifier)** - методология именования CSS-классов, которая решает проблему конфликтов без повышения специфичности. Все селекторы - классы одного уровня, коллизий нет.

**CSS Custom Properties** наследуются по DOM-дереву и изменяются через JavaScript: `element.style.setProperty('--color-primary', '#ff0000')`. В отличие от переменных Sass, они работают в runtime - идеально для тем и динамической стилизации.

У элемента <p class="text" id="intro"> есть два правила: `.text { color: blue; }` и `p { color: red; }`. Какой цвет будет у текста?

Flexbox: одномерные раскладки

**До Flexbox вертикальное центрирование было мемом веб-разработки.** Решение через `transform: translateY(-50%)` или `display: table-cell` - это были реальные продакшн-хаки. Flexbox решил это и сотни других задач одной строкой. Ключевое слово: **одномерный** - работает либо по горизонтали, либо по вертикали.

**Две оси Flexbox:** главная (main axis) определяется `flex-direction` - по умолчанию горизонтальная (`row`). Поперечная (cross axis) - перпендикулярна. `justify-content` управляет главной осью, `align-items` - поперечной.

СвойствоЗначенияЧто делает
flex-directionrow | column | row-reverse | column-reverseНаправление главной оси
justify-contentflex-start | center | flex-end | space-between | space-around | space-evenlyРаспределение по главной оси
align-itemsflex-start | center | flex-end | stretch | baselineВыравнивание по поперечной оси
flex-wrapnowrap | wrap | wrap-reverseПеренос элементов на новую строку
gap10px | 1remОтступы между flex-элементами
flexgrow shrink basis (например, 1 0 200px)Как элемент растягивается/сжимается

**`flex: 1 1 300px`** - самый полезный паттерн Flexbox. Элемент занимает минимум 300px, растёт при наличии свободного места и переносится при нехватке. Responsive-карточки без единого media query.

Что означает запись `flex: 1 0 200px` на flex-элементе?

CSS Grid: двумерные раскладки

**Flexbox - одномерный: строка ИЛИ колонка. Grid - двумерный: строки И колонки одновременно.** Dashboard, каталог, лэндинг с несколькими секциями - задачи для Grid. Это как таблица, но без ограничений `<table>`, без вложенных div-ов и без войны с вертикальным центрированием.

**`fr` (fraction unit)** - единица, уникальная для Grid. `1fr` означает «одна доля свободного пространства». `grid-template-columns: 1fr 2fr` - вторая колонка в два раза шире первой. `fr` - это как `flex-grow`, но для Grid.

**`grid-template-areas`** - самая наглядная фича Grid. Layout буквально «рисуется» текстом. Каждая строка в кавычках - ряд. Одинаковые имена объединяют ячейки. Точка (`.`) означает пустую ячейку.

ЗадачаFlexboxGrid
Навигация (горизонт.)ИдеальноИзбыточно
Центрирование элементаПодходитПодходит
Dashboard с sidebarКостылиИдеально
Карточки в рядХорошо с wrapХорошо с auto-fill
Перекрытие элементовНевозможноgrid-row/column + z-index
Произвольный 2D-макетНевозможноИдеально

**Flexbox и Grid не конкуренты - они дополняют друг друга.** Grid для макета страницы (header/sidebar/content/footer), Flexbox для компонентов внутри (nav links, card content, button group). Grid-контейнер часто содержит Flex-контейнеры.

Что делает `grid-template-columns: repeat(auto-fill, minmax(250px, 1fr))`?

Responsive Design

**60% мирового веб-трафика приходится на мобильные устройства.** Сайт, отлично выглядящий на 27-дюймовом мониторе, может быть непригодным на телефоне. Responsive design - подход, при котором один HTML-документ адаптируется к любому размеру экрана без дублирования контента.

**Mobile-first** означает: базовые стили - для самого маленького экрана, затем через `@media (min-width)` добавляются улучшения. Почему не desktop-first? Проще добавлять сложность, чем убирать. Мобильный layout (одна колонка) - естественное состояние HTML.

**Container Queries (2023)** - революция в responsive design. Media queries реагируют на размер *viewport* (всего окна). Container queries - на размер *родительского контейнера*. Компонент адаптируется независимо от того, где он размещён на странице.

ТехнологияРеагирует наКогда использовать
Media queriesРазмер viewport (окна)Глобальный layout: columns, navigation
Container queriesРазмер родителяКомпоненты: cards, widgets
clamp()Размер viewport (плавно)Typography, spacing - без breakpoints
auto-fill / auto-fitСвободное место в GridСетки карточек, каталоги
flex-wrapСвободное место в FlexНавигация, группы кнопок

**Не забывайте про `<meta name="viewport">`** в `<head>`. Без него мобильный браузер рендерит страницу как десктопную (шириной 980px) и масштабирует. Все media queries перестают работать как ожидается.

Responsive design - это добавить несколько media queries с breakpoints для популярных устройств (320px, 768px, 1024px)

Responsive design - это подход, включающий fluid grids, flexible images, современные CSS-функции (clamp, min, max), container queries и media queries. Breakpoints ставятся там, где ломается дизайн, а не под конкретные устройства

Устройств тысячи, и их размеры не укладываются в 3-4 breakpoint. Fluid typography через clamp(), auto-fill Grid и container queries адаптируются к любому размеру без breakpoints вообще. Media queries - один инструмент из многих, а не синоним responsive design

Чем Container Queries отличаются от Media Queries?

Ключевые идеи

  • **Специфичность решает конфликты:** inline > #id > .class > element. BEM и Custom Properties помогают избежать войны специфичностей
  • **Flexbox - одномерный:** строка или колонка. `justify-content` для главной оси, `align-items` для поперечной. `flex: 1 1 300px` - универсальная адаптивная карточка
  • **Grid - двумерный:** строки и колонки одновременно. `grid-template-areas` для сложных layouts, `auto-fill + minmax` для адаптивных сеток
  • **Responsive = подход, не media queries.** Mobile-first, clamp() для fluid typography, container queries для компонентов, auto-fill для сеток

Связанные темы

CSS стилизует HTML и взаимодействует с JavaScript:

  • HTML и семантическая вёрстка — CSS-селекторы работают с HTML-элементами и их атрибутами
  • JavaScript: основы языка — JavaScript динамически меняет CSS через style, classList и Custom Properties

Вопросы для размышления

  • Откройте DevTools на любом сайте, найдите элемент и посмотрите вкладку Computed - сколько CSS-правил конкурируют за одно свойство?
  • Попробуйте построить layout любимого сайта, используя только Grid и grid-template-areas. Насколько это проще, чем кажется?
  • Сузьте окно браузера до 320px. Какие сайты адаптируются плавно (fluid), а какие «прыгают» между breakpoints?

Связанные уроки

  • web-01 — HTML и семантика - основа для CSS-селекторов и BEM
  • web-03 — JavaScript динамически меняет CSS через classList и Custom Properties
  • web-04 — React и компонентная архитектура: CSS Modules и styled-components строятся на принципах специфичности
  • gd-02 — Выбор CSS layout (Flexbox vs Grid) аналогичен выбору архитектуры движка - разные инструменты для разных задач
  • mob-02 — Responsive design и mobile-first - прямо связаны с lifecycle мобильных приложений
  • se-01 — BEM и CSS Custom Properties реализуют принципы SOLID в стилизации
  • comp-01-intro
CSS: от каскада до Grid

0

1

Войти