Адаптивное оглавление
В этой демонстрации разберём, как создать оглавление, которое подстраивается под ширину экрана.
Начнём с разметки.
Перейдём к стилизации.
Создадим правило, которое содержит базовые стили для элемента с классом .toc
— контейнера для оглавления. Ограничим его по ширине ширине. Выровняем по центру с помощью автоматических внешних отступов. Укажем внутренние отступы, чтобы добавить воздуха.
Чтобы разместить название главы и номера страниц на одной строке, элемент с классом .toc__entry
сделаем грид-контейнером.
Для определения ширины колонок используем значения auto
и max-content
.
Для текстового контента max-content
означает, что контент не будет переноситься вообще, даже если это приведет к переполнению. А вот значение auto
длинные названия глав заставит переноситься на следующую строку, как только закончится свободное место. Учитывая, что номер страницы не может быть очень большим, максимум 3-4 знака, а название главы может быть сколь угодно длинным, такое поведение нас полностью устраивает.
В каждой строке оглавления .toc__entry
будет своя сетка, а значит своя ширина для колонки с названием главы и своя ширина для колонки с номером страницы.
Можете поэкспериментировать и уменьшить/увеличить ширину окна минибраузера.
Чтобы упростить стилизацию, используем именованные области grid-areas
. С их помощью определим как будут располагаться элементы внутри грид-контейнера.
Для названия главы укажем название области chapter
, для номеров страниц — page
.
Добавим выравнивание элементов внутри .toc__entry
по нижней границе.
Установим промежутки между элементами сетки. Это поможет визуально отделить их друг от друга.
Добавим нижний отступ для .toc__entry
, чтобы увеличить пространство между строками в оглавлении.
Добавим правило для элемента с классом .toc__chapter
и поместим его в нужной области сетки. Укажем название грид-области chapter
.
Аналогично поступим с элементом .toc__page
. Для него название грид-области укажем равным значению page
.
Декоративный элемент-точки (их ещё называют «leaders» или «leader lines») создадим за счёт псевдоэлемента ::after
для строки оглавления .toc__chapter
. Точки будут заполнять всё свободное пространство между названиями глав и номерами страниц.
В CSS-свойстве content
для ::after
добавим точек с запасом.
Чтобы улучшить читабельность CSS, длинную строку с точками разобьём на несколько.
Установим для ::after
position: absolute
, а для элемента .toc__chapter
— position: relative
.
Обратите внимание, для ::after
мы не указали ни координаты, ни размеры. По умолчанию значения CSS-свойств left
, width
и right
— auto
и псевдоэлемент занимает нужное нам пространство. Псевдоэлемент не наслаивается ни на заголовок главы, ни на номер страницы. А при достижении ширины родителя точки просто переносятся на следующую строку.
Чтобы скрыть лишние точки, используем CSS-свойство overflow
со значение hidden
.
Добавим небольшой внутренний отступ слева, чтобы точки не прилипали к названию главы.
Добавим для точек выравнивание по правому краю.
Потестируем оглавление. Для начала зададим длинный текст для названия главы.
Текст переносится на следующую строку, заполнители-точки занимают необходимое пространство.
Проведём ещё один тест. Уменьшим ширину оглавления.
Все элементы на местах, заголовки переносятся, точки заполняют свободное пространство. Всё работает как нужно.
Уберём жёсткую фиксацию по ширине. Вернём CSS-свойство max-width
.
Оглавление готово.
Несколько бонусных шагов
Чтобы лучше разобраться в реализации заполнителя. Уберём заполнитель у всех элементов, кроме одного.
Подсветим контейнер .toc__chapter
и его псевдоэлемент.
Зададим псевдоэлементу статичное позиционирование, чтобы эмулировать «static-position containing block».
Уменьшим объём текста в свойстве content
, чтобы увидеть поведение блока при изменении контента.
Вернём абсолютное позиционирование и исходное содержание для псевдоэлемента.
Сделаем так, чтобы «containing block» стал другим элементом.
Поднимем «containing block» ещё выше. На этом шаге можно изменить масштаб в мини-браузере и растянуть его пошире, чтобы оглавление начало центроваться.
Вообще удалим относительное позиционирование у всех предков и познакомися с «initial containing block».