Прилипающие CSS Grid элементы

Источник: «Sticky CSS Grid Items»
Если вы когда-нибудь пытались разместить прилипающий элемент в макетной сетке grid и наблюдали, как элемент прокручивается вместе с остальным содержимым, вы могли прийти к выводу, что position: sticky не работает с CSS Grid.

Проблема: position sticky не работает

Давайте начнём с основной проблемы, с которой вы, вероятно, столкнётесь, потому что сначала не всегда очевидно, почему ваш grid-элемент не прилипает, position sticky не работает.

Допустим, мы собираем шаблон макета для статей о различных сладостях. У нас есть заголовок в левом столбце grid макета, и мы установили его sticky:

article {
display: grid;
grid-template-columns: 20em 1fr;
grid-gap: 4em;
}

.title {
position: sticky;
top: 2rem;
}

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

Если мы добавим границы (border: 10px solid;) к нашему sticky заголовку (или используем инспектор GSS Grid), наша основная проблема станет более очевидной. Посмотреть пример на CodePen.

Алгоритм изменения размера элементов CSS Grid эффективно определяет размер grid элемента (нашего sticky заголовка), что бы заполнить высоту grid слота, в который он был помещён. Мы не видим ни каких эффектов sticky, потому что его вычисленная высота такая же, как и у содержимого в соседнем grid слоте.

Мелкие подробности о размерах

Сейчас всё станет скучным, просто перейдите к раздела "Как это исправить", если нужно только решение проблемы!

Поскольку мы не использовали какие-либо CSS свойства определяющие размер наших grid элементов (скоро мы к ним вернёмся), CSS Grid по умолчанию использовал свой "нормальный" алгоритм определения размера при определении размера sticky заголовка.

Наш заголовок h1...

...поэтому алгоритм вернулся к "растянутой" схеме определения размеров. В основном это гарантирует, что размер блока в этом измерении установлен таким образом, что бы заполнять контейнер макета в котором он находится (или упрощая grid слот).

Как это исправить

Один из способов решения этой проблемы — указать внешний размер высоты для нашего sticky заголовка, например: height: 10em, max-height: 50vh, или что-то подобное. Однако указывать конкретную высоту для нашего контента это халтура, на м не нужна конкретная высота, мы хотим, что бы вычисленная высота была достаточной для размещения содержимого элемента. Вместо этого мы можем изменить способ выравнивания этого элемента по grid слоту.

Мы можем указать одно из следующих свойств:

place-self и place-items так же будут работать; они обрабатывают обе оси, ось блока (или ось столбца) и внутренней оси (или ось строки)

Было бы неплохо выровнять базовую линию текста нашего sticky заголовка и базовую линию текста первого абзаца. Если мы установим align-items: baseline; в article, которая заставляет алгоритм определения размера использовать схему "подгонки содержимого". В этом есть некоторая сложность, но в нашем случае алгоритм использовал "максимальный размер содержимого" нашего grid элемента или "наименьший размер, который блок может занимать по этой оси, при этом всё ещё вписываясь в его содержимое".

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

Наши обновлённые стили:

article {
display: grid;
grid-template-columns: 20em 1fr;
grid-gap: 4em;

/* The new line we added! */
align-items: baseline;
}

.title {
position: sticky;
top: 2rem;
}

Вот и всё! Надеюсь это поможет вам выйти из sticky ситуации.

Дополнительные материалы

Предыдущая Статья

Объяснение Git: Диапазоны коммитов

Следующая Статья

CSS: Отзывчивые макеты, меньше CSS медиа запросов