Относительно недавно ко мне обратился клиент, занимающийся разработкой своего сайта-блога про криптовалюту, блокчейн и всякое такое. Большую часть работы человек сделал сам, используя визуальные редакторы на одной известной системе управления контентом, но с одним пунктом у клиента возникли проблемы.

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

Глоссарий моей мечты

Не стал сильно грузится, заказчик сам хотел как можно проще и без лишнего кода, поэтому вверху страницы глоссария разместил буквы в алфавитном порядке, а ниже список терминов и их определений. Про клике на букву происходил скролл на блок терминов, начинающихся с данной буквы. Решение так себе, но клиенту нужно было подешевле и побыстрее. Помнится, что я делал что-то похожее на Ghost CMS, но с использованием скрипта, который вписанные на страницу термины препарировал, извлекал из них первые буквы, и сам вставлял их вверх страницы, создавая из них якорные ссылки к нужному блоку терминов. Здесь ситуация попроще, никаких скриптов, чистый scroll-behavior: smooth.

Спустя пару дней заказчик вернулся с новой идеей. Показал мне анимацию, где на мобильном при прокрутке глоссария, буква вверху блока залипала до момента пока ее снизу не подбивала исчезнуть с экрана другая буква. Объяснять долго, вот вам ниже гифка (вообще-то видео, но похоже на гифку).

Я объяснил что сделать такое без скрипта не получится, а первоначальная идея, вроде бы, была именно в том, что обойтись без сложностей. «Ну, может есть решение без скриптов», - сказал клиент. Я ответил, что поищу, хотя делать этого не собирался, ведь точно без скриптов такого не сделать, как я думал тогда. Однако от скуки загуглил, или яндексанул (как там теперь правильно?) и нашел чудесный и очень простой, как оказалось, трюк. О нем и расскажу далее.

😀

Я графоман, очень люблю писать, но ниже есть код, который можно скопировать себе и не читать все, что я тут пишу. Хотя мне было бы приятно, если бы вы читали

Скроллим чужие списки

Один креативный разработчик с западно-европейских берегов по имени Филипп Браунен пытался сделать залипающий хэдер, который мог бы вписаться в общую высоту контейнера и при этом нормально координироваться с другими элементами для создания вместе с ними общей высоты. Спойлер: ему это почти удалось, но с костылями, которые всегда возникают когда приходится делать фиксированную шапку и при этом не уродовать нижестоящий блок несуразными отступами, заступами и еще какими-нибудь затупами (я не про себя 😀).

Хорошим решением для такого эффекта является использование position: sticky. Автор его и использовал, но под его задачи, нужно было использовать еще много чего из CSS. Потому что sticky сочетает в себе два других вида позиционирования и находится в потоке документа в позиции relative до тех пор, пока не достигнет краев своего прокручиваемого родительского контейнера, после чего занимает позицию fixed.

Элемент с position: fixed не заботится о родителе, в котором он находится, или о любом из его предков. Он вырвется из потока документа и разместится непосредственно в том месте, где вы ему укажете с помощью свойств top, left и так далее, оставаясь в зоне видимости на экране. А sticky-элемент с удовольствием сбежит из области просмотра, но никогда не выйдет за пределы границ своего прямого родителя.

Последнее свойство position: sticky, как оказалось, можно использовать для создания того, что мне было поручено заказчиком - прокручиваемый глоссарий с закреплением вверху текущей буквы, с которой начинаются термины.

Теперь код.

Прокручиваем и прилепляем

Итак, основная идея состоит в том, чтобы создать список, состоящий из нескольких блоков, вверху каждого из которых должен быть «липкий хэдер».

Список с залипающей шапкой
<section class="roll">
    <div class="roll-list">
        <h2 class="roll-sticky">Буква</h2>
        <ul>
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </div>

    <div class="roll-list">
        <h2 class="roll-sticky">Буква</h2>
        <ul>
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </div>

    <div class="roll-list">
        <h2 class="roll-sticky">Буква</h2>
        <ul>
        <li></li>
        <li></li>
        <li></li>
        </ul>
    </div>
</section>

Элементов с классом .roll-list может быть сколько угодно, главное не забыть в каждый из них добавить вверху залипающий заголовок, в моем случае roll-sticky.

Далее нужно побеспокоиться о CSS. Сначала сделаем родитель прокручиваемым и ограничим его высоту. Последнее нам необходимо, чтобы появился эффект залипания. У меня тут небольшой элемент для примера, но если вы будете делать что-то большее, то можно указать высоту равную хоть 100vh.

Список с залипающей шапкой
.roll {
  max-height: 18rem;
  overflow-y: scroll;
}

Из обязательного у нас остается лишь задать нужные объявления непосредственно для залипающей шапки. Обязательно указываем top: 0, чтобы элемент понял, что ему нужно оказаться вверху.

Список с залипающей шапкой
.roll-sticky {
    position: sticky;
    top: 0;
}

Можно добавить ряд стилей для того, чтобы все выглядело более или менее красиво. В CodePen ниже я добавил рамки, отступы и цвета, но обязательными же правилами являются лишь те, что находятся чуть выше.

Вот весь код:

Вот такое простое решение для такой нетривиальной задачи. Добавить здесь собственно нечего. Все работает как нужно. Возможно и вам такой эффект без JavaScript когда-нибудь пригодится для работы или для своих собственных проектов.


Спасибо, что дочитали статью. Я буду продолжать искать интересные CSS-решения, так как это очень увлекательно, и позволяет отдохнуть от однообразных трудовых будней. Всего доброго 👋