我想使用网格布局来设计粘性卡的布局。这就是我设法实现的目标:
<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))`,
);
}
前 4 张卡效果很好,但第五张卡比我预期的要早脱开。我认为这是因为父元素
cards
正在结束。有没有办法使用 css 网格来实现这种行为?我发现了一些其他方法,但它涉及对某些元素的某些高度进行硬编码,我想避免这种情况。
您遇到的问题是由于粘性定位依赖于父容器的高度。当父容器结束时,粘性元素无法再粘在顶部。为了实现您正在寻找的行为,您可以利用 CSS 网格进行一些调整。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sticky Cards</title>
<style>
:root {
--card-top-offset: 3rem;
--card-h: 36rem;
}
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
.cards {
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
gap: calc(var(--card-h) / 2);
align-items: baseline;
position: relative;
padding-top: 5vh;
}
.card {
position: sticky;
top: calc(5vh + var(--card-top-offset) * var(--i));
height: var(--card-h);
transition: all 0.5s;
background: lightblue;
}
.card:nth-child(1) {
--i: 0;
}
.card:nth-child(2) {
--i: 1;
}
.card:nth-child(3) {
--i: 2;
}
.card:nth-child(4) {
--i: 3;
}
.card:nth-child(5) {
--i: 4;
}
</style>
</head>
<body>
<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>
</body>
</html>
这里,每张卡片都有一个 --i 自定义属性,用于确定其相对于顶部的位置。这避免了硬编码高度并允许更动态的设置。位置:粘性仍被使用,但具有计算的顶部偏移量。