I want to have a layout of sticky cards using grid layout. This is what I managed to achieve:
<div class="cards">
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
<div class="card">5</div>
</div>
:root {
--card-top-offset: 3rem;
--card-h: 36rem;
}
.cards {
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
gap: calc(var(--card-h) / 2);
align-items: baseline;
}
.card {
position: sticky;
top: 0;
height: var(--card-h);
transition: all 0.5s;
}
for (const cards of document.querySelectorAll(".cards")) {
let i = 0;
for (const card of cards.children) {
if (card.classList.contains("card")) {
card.style.top = `calc(5vh + ${i} * var(--card-top-offset))`;
i += 1;
}
}
cards.style.setProperty(
"grid-template-rows",
`repeat(${i}, var(--card-h))`,
);
}
It works fine for the first 4 cards, however the fifth one unsticks sooner that I expect. I think that’s due to the fact that the parent element cards
is ending. Is there any way to achieve this behavior using css grid? I found some other approaches but it involved hard-coding certain heights on some elements and I would like to avoid that.
2
Answers
The issue you’re encountering is due to the fact that the sticky positioning relies on the height of the parent container. When the parent container ends, the sticky element cannot stick to the top anymore. To achieve the behavior you’re looking for, you can leverage CSS Grid with some tweaks.
Here, each card has a –i custom property that determines its position relative to the top. This avoids hardcoding heights and allows for a more dynamic setup. The position: sticky is still used, but with a calculated top offset.
According to Mozilla:
Your last card is overlapping when:
This is how the sticky works. The only solution is to increase the height of the container, but at the end of it will overlap anyway accordingly to the sticky behaviour. The solution will be as below if you want to use position: sticky;
As you can see it is still not what you want to achieve(I do believe :)).
I would suggest you to not use position sticky and use different approach:
Adjust for your needs 🙂