Вертикальный ритм и списки
Типографика определила размеры текста, но длинный урок состоит не только из строк. Между объяснением, листингом и результатом возникают расстояния, которые показывают их связь. Если после каждого элемента оставить одинаковое большое поле, страница распадётся на отдельные островки. Если поля слишком малы, разделы сольются и станет трудно возвращаться к нужной мысли.
В этом уроке вы настроите вертикальный ритм reading-lab. Мы будем рассматривать расстояния как часть содержания: новый раздел отделяется сильнее, чем два абзаца одной мысли, а подпись держится рядом со своим изображением. Продолжайте состояние четвёртого урока и добавьте файл lesson-05.css после предыдущих дополнений.
Связь важнее одинакового числа
Посмотрите на последовательность в разделе build: вводное объяснение, листинг, пояснение условных функций и список. Эти элементы связаны, хотя выглядят по-разному. Большое поле перед листингом может помочь заметить смену формы, но такое же большое поле после каждого предложения станет препятствием для чтения.
Условимся различать три расстояния. Малое связывает подпись с объектом или два соседних элемента списка. Среднее разделяет абзацы и самостоятельные примеры. Большое отмечает начало нового раздела. Это смысловые роли, а не жёсткая арифметическая сетка для всех элементов страницы. Один и тот же компонент может требовать уточнения, если внутри него появился заголовок или несколько абзацев.
Для начального макета удобно мыслить шагами относительно основного размера текста. Тогда изменения остаются понятными: вы обсуждаете, насколько сильнее отделён раздел, а не ищете случайное значение, которое хорошо выглядит возле одного абзаца. Позднее вынесем эти шаги в параметры системы. Пока числа останутся непосредственно в правилах, чтобы вы могли увидеть механизм.
Ритм не требует строки пустого пространства после любого элемента. Например, подпись изображения должна быть ближе к изображению, чем к следующему абзацу. Иначе она зрительно начнёт относиться к новому объяснению. Аналогично заголовок раздела располагается ближе к первому абзацу своего раздела, чем к окончанию предыдущего.
Управляем полями текста
Ниже полный файл дополнения lesson-05.css:
.reading-lab .lab-prose p { margin-block: 0 1rem; }
.reading-lab .lab-prose h2 { margin-block: 2.5rem 1rem; }
.reading-lab .lab-prose h3 { margin-block: 1.75rem .75rem; }
.reading-lab .lab-prose section:first-child > h2 { margin-block-start: 0; }
.reading-lab .lab-prose ul, .reading-lab .lab-prose ol { margin-block: 1rem 1.5rem; padding-inline-start: 1.5rem; }
.reading-lab .lab-prose li + li { margin-block-start: .4rem; }
.reading-lab .lab-prose li > ul, .reading-lab .lab-prose li > ol { margin-block: .5rem; }
.reading-lab .lab-note > :last-child, .reading-lab .lab-card > :last-child { margin-block-end: 0; }
.reading-lab .lab-figure figcaption { margin-block-start: .5rem; }
Ожидается ясная граница между тремя разделами макета. Внутри разделов абзацы сохраняют более плотную связь. Первый заголовок не создаёт дополнительную пустую полосу после уже отстроенной шапки статьи: для него удалено только верхнее поле. У остальных заголовков это поле остаётся и обозначает новую смысловую область.
Селектор li + li применяется к элементу списка, перед которым уже есть другой элемент списка. Таким образом, у первой строки не появляется лишнее расстояние от верхней границы самого списка. Это удобнее, чем добавлять отдельный класс каждому пункту. При вложенных списках правило работает внутри каждого уровня; его результат нужно оценивать на реальной структуре.
У последнего абзаца заметки удаляется нижнее поле. Внешние отступы самой заметки уже отделяют её от окружения, а внутренний padding оставляет пространство до края. Двойное суммирование этих расстояний сделало бы нижнюю часть карточки неоправданно большой. Мы меняем конкретные контейнеры, а не глобально убираем последнее поле у любого элемента документа.
Списки как часть объяснения
Маркированный список в макете перечисляет роли текста, кода и разбора. Порядок этих пунктов не является инструкцией запуска, поэтому маркеры подходят. Нумерованный список ниже показывает последовательность действий. Визуальное оформление должно поддерживать эту разницу: не превращайте оба списка в одинаковые сетки карточек только ради общего компонента.
Проверьте длинный пункт, который переносится на несколько строк. Его продолжение должно выравниваться с началом текста, а не с маркером. Для этого сохранены естественное устройство списка и левый внутренний отступ. Если убрать padding без альтернативы, маркер может оказаться за пределами колонки. Слишком большой отступ, напротив, съест полезную ширину на небольшом экране.
Вложение требует осторожности. Два или три уровня иногда отражают реальную структуру, но глубокая лестница существенно сужает строку. Здесь лучше сначала спросить, нельзя ли описать вторую часть отдельным абзацем или таблицей. Такое решение относится к редактуре содержания. CSS не должен скрывать уровень вложенности или визуально выдавать дочерний пункт за равноправный.
Для самостоятельного сравнения замените один короткий пункт двумя предложениями, а в другой добавьте вложенный список из двух пунктов. Ожидайте сохранения различимых уровней и понятных расстояний. Если большой промежуток возник только внутри одного пункта, посмотрите на поля дочерних абзацев, а не увеличивайте отступы всего списка.
Ритм вокруг крупных объектов
Листинг и таблица уже получают собственные внешние поля в базе. Они должны отделяться от соседнего объяснения сильнее, чем два обычных абзаца, но оставаться внутри своего раздела. На длинной странице особенно заметно, если одинаковые объекты имеют разные верхние поля из-за случайных встроенных стилей.
Сравните две соседние заметки: одну с коротким текстом, другую с заголовком и двумя абзацами. Их высота будет разной, и это нормально. Одинаковыми должны оставаться смысловые расстояния до края и связь с окружающим текстом. Задавать всем заметкам фиксированную высоту ради совпадения прямоугольников опасно: содержание либо обрежется, либо появится искусственная пустота.
Также избегайте компенсации проблем отрицательными полями без объяснения причины. Если изображение уехало слишком далеко от подписи, сначала установите, какое правило создаёт отступ. Случайная поправка margin-top: -20px может хорошо выглядеть в одном макете и столкнуть элементы после изменения шрифта. Осмысленное правило должно зависеть от роли, а не от единственного снимка.
У вертикальных полей соседних блочных элементов есть особенности взаимодействия, включая схлопывание. Поэтому видимый промежуток не всегда равен сумме двух записанных чисел. В нашем примере главные расстояния назначены одному из соседей, чтобы их было проще читать. Основной механизм приведён в MDN о схлопывании полей; не переносите арифметику этих правил автоматически в flex- или grid-контейнер.
Теперь форма урока должна показывать его внутреннюю последовательность. Вы можете просмотреть страницу сверху вниз и различить начало раздела, обычное объяснение и крупный пример, не добавляя рамку вокруг каждого фрагмента. В следующем уроке используем цвет как поддержку этого ритма, сохранив знакомую палитру ProfessorWeb.