Поведение position sticky
У длинного списка иногда удобно сохранять рядом короткую навигацию: вернуться к началу курсов или перейти к учебной форме. Постоянное fixed прикрепило бы её к окну на всю страницу. position: sticky позволяет элементу сначала занимать обычное место, затем временно удерживаться возле края области прокрутки, сохраняя ограничения своего контейнера.
Вернёмся от лаборатории наложения к рабочему каталогу. Полностью удалите из HTML секцию lab-stack-lab, а из CSS — отдельный блок с её классами stack-stage, stack-panel и stack-label. Правила настоящей карточки и её метки сохраняются. Результат этого урока — небольшая панель внутри секции курсов, которая не сопровождает пользователя через всю учебную заявку.
Место панели в документе
Найдите в index.html заголовок courses-title. Сразу после него и перед ul.course-list добавьте следующий полный элемент. В этом месте обе ссылки указывают на существующие идентификаторы: начало каталога и секцию формы. Других секций ради панели создавать не нужно.
<nav class="lab-section-nav" aria-label="Навигация каталога">
<a href="#courses-title">Начало списка</a>
<a href="#request">Учебная заявка</a>
</nav>
В конец stylesheet добавьте следующий блок. Число z-index нужно для осмысленного перекрытия содержимого списка в том же участке страницы, а непрозрачный фон сохраняет читаемость панели. Оно не связано с диагностическими числами удалённой лаборатории.
@layer components {
.layout-lab .lab-section-nav { position: sticky; inset-block-start: 0; z-index: 10; display: flex; flex-wrap: wrap; gap: .5rem 1rem; padding-block: .75rem; background: var(--lab-bg); border-block-end: 1px solid var(--lab-line); }
.layout-lab #courses-title, .layout-lab #request { scroll-margin-block-start: 4rem; }
@media print { .layout-lab .lab-section-nav { position: static; } }
}
Панель ожидается непосредственно под заголовком списка. Пока её обычное положение ниже верхнего края, она ведёт себя как часть потока. При достаточной прокрутке начинает удерживаться возле начала блочной оси. Когда нижняя граница секции курсов ограничивает дальнейшее перемещение, панель уходит вместе с этой секцией. Внутри последующих блоков таблицы и формы она не должна продолжать висеть поверх текста.
Такой прогноз требует страницы, у которой действительно хватает пространства для прокрутки. На большом экране короткий список может целиком помещаться в видимой области, и закрепление окажется незаметным. Это не доказательство неподдерживаемого свойства. Сначала проверьте, пересекает ли обычное положение панели выбранный край и есть ли пространство для её дальнейшего удерживания.
Порог и область движения
Одного position: sticky недостаточно: по нужной оси требуется непустое ограничение вроде inset-block-start: 0. Без такого порога на этой оси поведение останется близким к относительному положению. Нулевая координата здесь означает верхний край для основного горизонтального документа. Это не внешняя высота хедера и не универсальная поправка для любого сайта.
Панель остаётся участником потока, поэтому следующие карточки получают место после неё. При закреплении коробка визуально меняет положение в заданных пределах, но её обычная область не исчезает так, как у абсолютного элемента. Поэтому не требуется добавлять пустой декоративный spacer только ради компенсации высоты. Такой лишний блок сделал бы обычный и закреплённый режимы сложнее.
Sticky ориентируется на ближайшего предка с соответствующим механизмом прокрутки, а не обязательно на тот элемент, который пользователь сейчас видит прокручивающимся. Например, overflow: hidden у промежуточной обёртки может изменить выбранную область. Поэтому неожиданное отсутствие закрепления часто требует проверки предков, а не увеличения z-index. Особенности опоры описаны в MDN о position.
Ограничение контейнера также важно. Если у родителя почти нет высоты сверх самой панели, двигаться внутри него некуда. Если панель выше доступной видимой области, удерживание у одного края не гарантирует удобный доступ ко всему её содержимому. Наш пример содержит две короткие ссылки и разрешённый перенос, а не большое меню, которое должно самостоятельно прокручиваться.
Порядок рисования и непрозрачный фон
Sticky создаёт собственный контекст наложения. Мы задаём небольшой номер, чтобы панель ожидаемо перекрывала карточки в своей группе. Это локальное решение, а не резервирование десятого уровня для всего ProfessorWeb. Если бы у родительской секции появился отдельный более низкий контекст, её внутренняя панель не смогла бы обойти соседнюю группу увеличением своего числа.
Без непрозрачного фона текст карточки оказался бы виден сквозь закреплённую область. Тогда правильное положение панели не означало бы читаемость её ссылок. В примере фон совпадает с основной страницей, а нижняя граница отделяет панель от списка. Мы не добавляем сложный blur, который изменил бы набор поддерживаемых свойств и потребовал бы отдельной проверки контраста.
При печати sticky не даёт читателю преимущества. Поэтому в том же компонентном блоке правило вывода возвращает position: static. Печатная версия должна следовать потоку страницы, а не имитировать положение возле края интерактивного окна. Это конкретная корректировка свойства; остальная печатная палитра уже определена более поздним слоем utilities.
Якоря и видимый заголовок
Ссылка панели остаётся обычным HTML-якорем. Она не вызывает JavaScript и не фильтрует курсы. Для целей перехода мы задали scroll-margin-block-start: 4rem, чтобы начальное положение заголовка оставляло запас возле верхнего края. Этот запас приблизителен для нашего короткого меню; он не вычисляет фактическую высоту любой перенесённой панели автоматически.
При увеличении текста навигация может стать выше. Тогда выбранный запас нужно снова проверить, особенно если заголовок попадает под закреплённую область. Не выдавайте постоянные четыре rem за универсальное решение для всех языков и масштабов. Сначала удерживаем саму панель компактной, затем смотрим реальное положение целей перехода.
Для диагностического опыта временно задайте родительской оболочке overflow: hidden. Предскажите изменение выбранной области sticky, затем удалите это объявление. Основной файл не должен сохранять случайное скрытие переполнения. В следующих уроках прокрутка появится у конкретной таблицы, а не у всей оболочки каталога, поэтому навигация не потеряет исходную границу.
Можно также временно оставить в списке один курс. Ожидается меньше доступного пространства для наблюдения закрепления. Затем восстановите все шесть записей. Такое сравнение отделяет механизм положения от случайной длины учебного содержимого. Нельзя обещать одинаково заметное движение для списка из одной короткой карточки и для большого каталога.
Проверяя интерфейс позже, пройдите ссылки клавиатурой и убедитесь, что видимый фокус не закрывается панелью. Это отдельное наблюдение, которое не заменяется наличием role или классом CSS. При подготовке продолжения браузерные опыты не выполнялись, поэтому мы сохранили предсказуемые условия, а не отчёт о доступности.
Теперь короткая навигация имеет обычное место, порог закрепления и ограничение секцией. Следующий урок добавит широкую таблицу сравнения. Её собственная прокрутка должна сохранить доступ ко всем столбцам, не превращая всю страницу в горизонтально движущуюся область.
Полное состояние этого шага находится в layout-lab/lesson-24 внутри исходников продолжения. Каждый снимок открывается отдельно; подключать CSS разных уроков одновременно не нужно.