1216 字
6 分钟

页面滚动的卡片网站

欢迎来到我的博客!#

使用 Markdown 格式编写。

今天学到了什么#

  • sticky粘性定位
  • vw和vh单位
  • animation-timeline: view();
  • grid布局的一些细节

sticky粘性定位#

position: sticky;(粘性定位)是一种混合了 relativefixed 特性的定位方式。

简单来说: 元素在跨越特定阈值(例如 top: 0)之前,表现得像普通元素(随页面滚动);一旦滚动到了那个阈值,它就会“粘”在屏幕的那个位置不动,直到它的父容器滚动结束,它才会跟着父容器一起滚走。

在你的代码中的作用:

.main ul li {
position: sticky;
top: 0;
/* ... */
}
  1. 吸顶效果:当页面向下滚动时,每个卡片(li)滚动到视口顶部(top: 0)时,就会停在那里不动。
  2. 堆叠效果:因为后面的卡片也会滚上来并停在同一个 top: 0 的位置,所以视觉上后面的卡片会盖住前面的卡片,形成一种“卡片层叠堆积”的特效。
  3. 离开:当整个列表容器(ul.main)滚出屏幕时,这些粘住的卡片也会随之被带走。

使用条件:

  • 必须指定 topbottomleftright 中的至少一个阈值。
  • 父元素不能设置 overflow: hiddenoverflow: auto(除非是想在那个特定的滚动容器内粘性定位),否则 sticky 可能会失效(但在你的代码里,li 是直接在 body 滚动的,所以没问题)。

grid布局的一些细节#

这涉及 CSS Grid 布局的一个隐蔽特性。

原因: 在 Grid 布局中,子元素(Grid Item)的默认 min-heightauto。这意味着浏览器会强制让子元素的高度至少能装下它里面的所有内容。 如果你的文字内容算出来的高度(比如 417px)超过了父容器 li 设定的高度(40vw,比如 290px),Grid 就会优先满足“装下内容”的需求,从而忽略你设置的 height: 100%,导致 .l 撑破父容器。

为什么 style.css 没问题? 可能是因为原案例中的文字内容较少、字体渲染差异,或者图片撑开的方式不同,导致其内容高度恰好没有超过 40vw,所以没有触发这个溢出行为。

解决办法: 必须显式地告诉浏览器:“允许这个 Grid 子元素的高度小于它的内容高度”。 我已经帮你修改了代码,添加了 min-height: 0;

.main ul li .l {
display: grid;
justify-items: center;
align-items: center;
text-align: center; /* 之前加的 */
height: 100%;
min-height: 0; /* 新增:允许高度收缩,不再被内容强制撑大 */
}

这样 .l 就会乖乖听话,严格保持和 li 一样的高度了。如果文字实在太多,它会溢出被 lioverflow: hidden 切掉,而不会撑大盒子。

在这里我是又设置了 grid-template-rows: 100%;也能完成同样的效果

案例完整代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./MyStyle.css">
</head>
<body>
<!-- 头部制作 -->
<header class="header">
<div>
<h1>泰山美景·卡片滚动</h1>
<p>👇 滚动页面,查看卡片滚动效果。</p>
</div>
</header>
<!-- 主体部分 -->
<main class="main">
<ul>
<li>
<div class="l">
<div>
<h2>云海玉盘</h2>
<p>云海玉盘,是泰山的四大奇观之一,多在夏秋两季出现。</p>
<a href="#">了解更多</a>
</div>
</div>
<figure>
<img src="../素材/1.png" alt="">
</figure>
</li>
<li>
<div class="l">
<div>
<h2>云海玉盘</h2>
<p>云海玉盘,是泰山的四大奇观之一,多在夏秋两季出现。</p>
<a href="#">了解更多</a>
</div>
</div>
<figure>
<img src="../素材/2.png" alt="">
</figure>
</li>
<li>
<div class="l">
<div>
<h2>云海玉盘</h2>
<p>云海玉盘,是泰山的四大奇观之一,多在夏秋两季出现。</p>
<a href="#">了解更多</a>
</div>
</div>
<figure>
<img src="../素材/3.png" alt="">
</figure>
</li>
<li>
<div class="l">
<div>
<h2>云海玉盘</h2>
<p>云海玉盘,是泰山的四大奇观之一,多在夏秋两季出现。</p>
<a href="#">了解更多</a>
</div>
</div>
<figure>
<img src="../素材/4.png" alt="">
</figure>
</li>
</ul>
</main>
<article class="article">
.........
</article>
</body>
</html>
<style>
:root {
--cardHeight: 50vw;
--cardMargin: 4vw;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul,
ol {
list-style: none;
}
body {
background-color: #3a1d2b;
font-size: calc(1em + .5vw);
}
@keyframes scale {
0% {
transform: scaleX(1);
}
100% {
transform: scaleX(0.8);
}
}
.header {
width: 100vw;
height: 100vh;
background-color: #3a1d2b;
display: flex;
justify-content: center;
align-items: center;
color: #ffffff;
text-align: center;
}
.header h1 {
font-size: 3.5vw;
margin-bottom: 1vw;
}
.header p {
font-size: 1.5vw;
}
.main {
width: 80vw;
margin: 0 auto;
}
.main ul li {
position: sticky;
top: 0;
height: var(--cardHeight);
margin-bottom: var(--cardMargin);
background-color: white;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 100%;
border-radius: 1em;
overflow: hidden;
animation: scale 0.5s ease forwards;
animation-timeline: view();
}
.main ul li figure img {
height: 100%;
width: 100%;
}
.main ul li .l div {
width: 80%;
}
.main ul li .l {
display: grid;
justify-items: center;
align-items: center;
}
.main .l h2 {
/* 字体不加粗 */
font-weight: 300;
}
.main .l p {
margin: 1em 0
}
.main .l a {
text-decoration: none;
color: #fff;
background-color: rgb(188 87 36);
padding: .5em;
border-radius: .25em;
}
.article {
width: 50vw;
margin: 0 auto;
color: #ffffff;
}
</style>

赞助支持

如果这篇文章对你有帮助,欢迎赞助支持!

赞助
最后更新于 2026-01-04

目录