От автора: если вы когда-либо пытались поместить липкий элемент в макет сетки и наблюдали, как элемент прокручивается вместе с остальным содержимым, вы, возможно, замечали, что position: sticky с CSS Grid не работает. Не стоит волноваться! Вполне возможно совместить эти два макета для работы вместе. Все, что вам, вероятно, понадобится, это еще одна строка CSS.
Проблема
Давайте начнем с основной проблемы, с которой вы, вероятно, столкнетесь, потому что сначала не всегда очевидно, почему ваш элемент сетки не прилипает.
Допустим, мы составляем шаблонный макет статей о различных конфетах. У нас есть заголовок в левом столбце макета сетки, и мы установили заголовок как липкий:
article { display: grid; grid-template-columns: 20em 1fr; grid-gap: 4em; } .title { position: sticky; top: 2rem; }
К сожалению, наш заголовок не прикрепляется к верхней части области просмотра, а вместо этого прокручивается вместе с остальным текстом:
Если мы добавим рамку к нашему прикрепленному заголовку (или воспользуемся инспектором CSS Grid), наша основная проблема станет более очевидной:
Алгоритм изменения размера элемента сетки CSS эффективно определяет размер элемента сетки (нашего липкого заголовка), чтобы заполнить высоту слота сетки, в который он был помещен. Мы не видим каких-либо липких эффектов, потому что его вычисленная высота такая же, как и содержимое сетки рядом с ним.
Тонкие подробности о размерах
Поскольку мы не использовали какие-либо свойства CSS, определяющие размер элементов сетки (мы вернемся к ним через минуту!), CSS Grid по умолчанию использовал свой «нормальный» алгоритм определения размера, при определении размера прикрепленного заголовка.
Наш заголовок h1…
Не заменяемый элемент, такие как img, video, embed, iframe и т.д. Они имеют специальные правила.
Не имеет «предпочтительного соотношения сторон». Такое внутреннее соотношение сторон может быть установлено для определенных элементов таблицей стилей пользовательского агента или с помощью свойства aspect-ratio.
… Поэтому алгоритм вернулся к «растянутой» схеме определения размеров. Это в основном гарантирует, что размер блока в этом измерении установлен таким образом, чтобы он заполнял контейнер макета, в котором он находится (для упрощения, слот сетки).
Как это исправить
Одним из способов решения этой проблемы является определение внешней высоты для нашего липкого заголовка, например, height: 10em, max-height: 50vh независимо. Однако указывать такую буквальную высоту для нашего контента — хакерство — нам не нужна конкретная высота, мы хотим, чтобы вычисленная высота была достаточной для размещения содержимого элемента. Вместо этого мы можем изменить способ выравнивания этого элемента по слоту сетки.
Мы можем указать одно из следующего:
align-self: это свойство, которое указано в липком заголовке, сообщает элементу, как выровнять себя по направлению блока слота сетки, в котором он находится. align-self: start хорошо сработает в нашем примере, так как оно выровняет элемент по «начальному» краю слота сетки (в данном случае верхний край).
align-items: это свойство, если оно указано в article (родительском элементе сетки), сообщает каждому элементу сетки, как выровнять себя по направлению блока слота сетки, в котором он находится.
(Примечание: сокращения place-self и place-items также будут работать, они справятся как с блоками, так и со встроенными осями).
Было бы неплохо выровнять базовую линию текста нашего прикрепленного заголовка и базовую линию текста нашего первого абзаца. Если мы установим align-items: baseline; на article, это заставит алгоритм определения размеров CSS Grid использовать схему «fit-content». В этом есть некоторая сложность, но в нашем случае алгоритм использовал «максимальный размер содержимого» нашего элемента сетки или «наименьший размер, который блок может принимать по этой оси, при этом все еще вписываясь в его содержимое».
Поскольку размер прикрепленного заголовка теперь изменяется в соответствии с его содержимым, мы получаем то поведение position: sticky, которое нам нужно:
Наши обновленные стили:
article { display: grid; grid-template-columns: 20em 1fr; grid-gap: 4em; /* The new line we added! */ align-items: baseline; } .title { position: sticky; top: 2rem; }
Вот и все! Надеюсь, это поможет вам выйти из сложной ситуации.
Автор: Melanie Richards
Источник: melanie-richards.com
Редакция: Команда webformyself.