2025年,CSS锚点定位(Anchor Positioning)和滚动驱动动画(Scroll-Driven Animations)已经得到主流浏览器支持。锚点定位让元素可以相对于其他元素精确定位,而滚动驱动动画则让动画与滚动进度同步,无需JavaScript。本文通过四个实战案例,带你掌握这些现代CSS特性。
1. 为什么需要锚点定位与滚动驱动动画?
传统CSS无法让一个元素相对于另一个任意元素定位,通常需要JavaScript计算位置。锚点定位解决了这个问题。滚动驱动动画则让动画与滚动行为自然结合,例如视差效果、进度条等,性能更好且代码更简洁。
- 锚点定位:元素相对于其他元素定位,实现工具提示、下拉菜单等
- 滚动驱动动画:动画进度与滚动位置同步
- 视图转换动画:页面过渡动画,提升用户体验
2. 锚点定位基础:定义与使用
CSS锚点定位通过 anchor-name 和 position-anchor 实现。
/* 定义锚点元素 */
.anchor-element {
anchor-name: --my-anchor;
}
/* 定位元素相对于锚点 */
.positioned-element {
position: absolute;
position-anchor: --my-anchor;
top: anchor(--my-anchor bottom);
left: anchor(--my-anchor left);
}
/* 使用anchor()函数定位 */
.tooltip {
position: absolute;
position-anchor: --button-anchor;
bottom: anchor(--button-anchor top);
left: anchor(--button-anchor center);
translate: -50% 0;
}
/* HTML结构 */
<button class="anchor-element">悬停我</button>
<div class="tooltip">工具提示内容</div>
3. 实战案例一:锚点定位实现工具提示
使用CSS锚点定位构建纯CSS工具提示,无需JavaScript。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CSS锚点定位工具提示</title>
</head>
<body>
<h2>CSS锚点定位工具提示</h2>
<p>悬停在下方的按钮上查看工具提示效果</p>
<div class="demo-container">
<button class="trigger-btn" id="btn1">
按钮上方提示
<span class="tooltip tooltip-top">这是上方的提示</span>
</button>
<button class="trigger-btn" id="btn2">
按钮下方提示
<span class="tooltip tooltip-bottom">这是下方的提示</span>
</button>
<button class="trigger-btn" id="btn3">
按钮右侧提示
<span class="tooltip tooltip-right">这是右侧的提示</span>
</button>
</div>
<style>
.demo-container {
display: flex;
gap: 40px;
padding: 80px 40px;
justify-content: center;
}
.trigger-btn {
anchor-name: --btn;
position: relative;
padding: 10px 20px;
background: #1a73e8;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
}
.tooltip {
position: absolute;
position-anchor: --btn;
background: #333;
color: white;
padding: 6px 12px;
border-radius: 4px;
font-size: 14px;
white-space: nowrap;
opacity: 0;
transition: opacity 0.2s;
pointer-events: none;
}
.trigger-btn:hover .tooltip {
opacity: 1;
}
.tooltip-top {
bottom: anchor(--btn top);
left: anchor(--btn center);
translate: -50% -8px;
}
.tooltip-bottom {
top: anchor(--btn bottom);
left: anchor(--btn center);
translate: -50% 8px;
}
.tooltip-right {
left: anchor(--btn right);
top: anchor(--btn center);
translate: 8px -50%;
}
/* 工具提示箭头 */
.tooltip::after {
content: '';
position: absolute;
width: 8px;
height: 8px;
background: #333;
transform: rotate(45deg);
}
.tooltip-top::after {
top: 100%;
left: 50%;
translate: -50% -4px;
}
.tooltip-bottom::after {
bottom: 100%;
left: 50%;
translate: -50% 4px;
}
.tooltip-right::after {
right: 100%;
top: 50%;
translate: 4px -50%;
}
</style>
</body>
</html>
4. 实战案例二:滚动驱动动画实现进度条
使用 scroll-timeline 实现阅读进度条动画。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>滚动驱动进度条</title>
</head>
<body>
<h2>滚动驱动阅读进度条</h2>
<p>向下滚动页面,查看顶部的进度条变化</p>
<div class="progress-bar"></div>
<div class="content">
<h3>第一章</h3>
<p>这是文章的第一段内容。滚动页面可以看到顶部的进度条随着滚动位置变化而填充。这个效果完全使用CSS实现,不需要任何JavaScript代码。</p>
<p>CSS滚动驱动动画通过scroll-timeline属性将动画与滚动进度绑定。我们可以控制动画的起始和结束位置,实现精准的滚动同步效果。</p>
<h3>第二章</h3>
<p>滚动驱动动画有多种应用场景:阅读进度条、视差滚动、滚动触发的淡入效果等。它比传统的IntersectionObserver实现更简洁,性能也更好。</p>
<p>目前Chrome 115+、Edge 115+已经支持scroll-timeline属性。Firefox和Safari正在开发中,可以通过实验性标志启用。</p>
<h3>第三章</h3>
<p>除了scroll-timeline,还有view-timeline用于监测元素进入视口。我们可以用它实现滚动到某个元素时触发动画的效果。</p>
<p>继续滚动查看更多内容...</p>
<!-- 重复内容占位 -->
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
<style>
/* 定义滚动时间线 */
@scroll-timeline scroll-progress {
source: auto;
orientation: block;
start: 0px;
end: 100%;
}
.progress-bar {
position: fixed;
top: 0;
left: 0;
height: 4px;
background: linear-gradient(90deg, #667eea, #764ba2);
transform-origin: left center;
/* 使用滚动驱动动画 */
animation: grow-progress linear;
animation-timeline: scroll-progress;
}
@keyframes grow-progress {
from {
width: 0%;
}
to {
width: 100%;
}
}
.content {
max-width: 600px;
margin: 40px auto;
padding: 20px;
line-height: 1.8;
font-size: 18px;
}
.content h3 {
margin-top: 40px;
color: #333;
}
.content p {
margin: 16px 0;
color: #555;
}
</style>
</body>
</html>
5. 实战案例三:视图驱动动画实现淡入效果
使用 view-timeline 实现元素进入视口时的淡入动画。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>视图驱动淡入动画</title>
</head>
<body>
<h2>视图驱动淡入动画</h2>
<p>向下滚动,观察卡片逐个淡入出现</p>
<div class="cards-container">
<div class="card fade-in">卡片 1 - 使用 view-timeline 实现淡入</div>
<div class="card fade-in">卡片 2 - 当元素进入视口时触发动画</div>
<div class="card fade-in">卡片 3 - 无需JavaScript监听</div>
<div class="card fade-in">卡片 4 - 性能更好,更简洁</div>
<div class="card fade-in">卡片 5 - 支持自定义动画范围</div>
<div class="card fade-in">卡片 6 - 可以控制起始和结束位置</div>
<div class="card fade-in">卡片 7 - 动画与滚动进度同步</div>
<div class="card fade-in">卡片 8 - 现代CSS的强大能力</div>
</div>
<style>
.cards-container {
max-width: 500px;
margin: 40px auto;
padding: 20px;
}
.card {
padding: 30px 20px;
margin: 40px 0;
background: white;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
font-size: 18px;
text-align: center;
/* 视图驱动动画 */
animation: fade-in linear;
animation-timeline: view();
animation-range: entry 0% entry 100%;
}
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(30px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
/* 为每个卡片添加不同的延迟效果 */
.card:nth-child(1) { animation-range: entry 0% entry 100%; }
.card:nth-child(2) { animation-range: entry 10% entry 110%; }
.card:nth-child(3) { animation-range: entry 20% entry 120%; }
.card:nth-child(4) { animation-range: entry 30% entry 130%; }
.card:nth-child(5) { animation-range: entry 40% entry 140%; }
.card:nth-child(6) { animation-range: entry 50% entry 150%; }
.card:nth-child(7) { animation-range: entry 60% entry 160%; }
.card:nth-child(8) { animation-range: entry 70% entry 170%; }
body {
background: #f5f5f5;
padding-bottom: 200px;
}
h2 {
text-align: center;
padding-top: 40px;
}
p {
text-align: center;
color: #666;
}
</style>
</body>
</html>
6. 实战案例四:锚点定位实现自定义下拉菜单
使用锚点定位构建纯CSS下拉菜单,精确定位于触发按钮。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CSS锚点定位下拉菜单</title>
</head>
<body>
<h2>CSS锚点定位下拉菜单</h2>
<div class="menu-container">
<button class="menu-trigger" id="menu1">
产品列表 ▾
</button>
<ul class="dropdown-menu">
<li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >Web开发</a></li>
<li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >移动应用</a></li>
<li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >云服务</a></li>
<li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >人工智能</a></li>
<li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >数据分析</a></li>
</ul>
</div>
<div class="menu-container" style="margin-left: 200px;">
<button class="menu-trigger" id="menu2">
更多服务 ▾
</button>
<ul class="dropdown-menu">
<li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >咨询服务</a></li>
<li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >技术支持</a></li>
<li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >培训课程</a></li>
</ul>
</div>
<style>
.menu-container {
display: inline-block;
position: relative;
margin: 40px;
}
.menu-trigger {
anchor-name: --menu-trigger;
padding: 10px 24px;
background: #1a73e8;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
}
.dropdown-menu {
position: absolute;
position-anchor: --menu-trigger;
top: anchor(--menu-trigger bottom);
left: anchor(--menu-trigger left);
width: max-content;
min-width: 180px;
margin: 0;
padding: 8px 0;
background: white;
border-radius: 8px;
box-shadow: 0 8px 30px rgba(0,0,0,0.12);
list-style: none;
opacity: 0;
transform: translateY(-8px);
transition: opacity 0.2s, transform 0.2s;
pointer-events: none;
}
.menu-container:hover .dropdown-menu,
.menu-trigger:focus + .dropdown-menu {
opacity: 1;
transform: translateY(4px);
pointer-events: auto;
}
.dropdown-menu li {
padding: 0;
}
.dropdown-menu a {
display: block;
padding: 10px 20px;
color: #333;
text-decoration: none;
font-size: 15px;
transition: background 0.15s;
}
.dropdown-menu a:hover {
background: #f0f4ff;
color: #1a73e8;
}
.dropdown-menu a:focus {
outline: 2px solid #1a73e8;
outline-offset: -2px;
background: #f0f4ff;
}
/* 小三角形指示器 */
.dropdown-menu::before {
content: '';
position: absolute;
bottom: 100%;
left: anchor(--menu-trigger center);
translate: -50% 0;
width: 12px;
height: 12px;
background: white;
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}
</style>
</body>
</html>
7. 浏览器兼容性与降级方案
| 特性 | Chrome | Edge | Firefox | Safari |
|---|---|---|---|---|
| 锚点定位 (anchor-name) | 125+ | 125+ | 实验性 | 实验性 |
| scroll-timeline | 115+ | 115+ | 实验性 | 不支持 |
| view-timeline | 115+ | 115+ | 实验性 | 不支持 |
8. 最佳实践总结
- 使用命名锚点:为锚点元素设置
anchor-name,名称以--开头 - 回退方案:对于不支持锚点定位的浏览器,提供JavaScript回退
- 滚动动画性能:使用
transform和opacity属性驱动动画 - 渐进增强:将滚动驱动动画作为增强特性,不影响基本功能
- 测试兼容性:使用
@supports检测浏览器支持
/* 使用@supports进行特性检测 */
@supports (anchor-name: --test) {
.tooltip {
position: absolute;
position-anchor: --btn;
/* 锚点定位样式 */
}
}
@supports not (anchor-name: --test) {
.tooltip {
/* JavaScript回退方案 */
display: none;
}
.trigger-btn:hover .tooltip {
display: block;
/* 使用传统定位方式 */
}
}
/* 滚动驱动动画降级 */
@supports (animation-timeline: scroll()) {
.fade-in {
animation: fade-in linear;
animation-timeline: view();
}
}
@supports not (animation-timeline: scroll()) {
.fade-in {
/* 使用IntersectionObserver或直接显示 */
opacity: 1;
}
}
9. 总结
通过本文的案例,你掌握了CSS锚点定位和滚动驱动动画的核心技术:
- 锚点定位实现工具提示和下拉菜单
- 滚动驱动动画实现阅读进度条
- 视图驱动动画实现淡入效果
- 浏览器兼容性与降级方案
- 最佳实践与性能优化
CSS锚点定位和滚动驱动动画让开发者能够用纯CSS实现复杂的交互效果,减少对JavaScript的依赖。这些新特性将逐渐改变Web交互的开发方式。现在就开始在你的项目中尝试这些现代CSS特性吧!
本文原创,基于CSS Anchor Positioning和Scroll-Driven Animations规范。部分特性需要Chrome 115+或启用实验性标志。

