如何避免点击水平滚动元素内锚点链接时页面垂直滚动至顶部
解决纯CSS水平滑块锚点跳转时页面Y轴滚动问题
问题描述
使用纯CSS制作水平滑块,点击锚点链接实现X轴滚动时,整个页面会同时沿Y轴滚动,导致滑块被置于页面顶部,需要避免该行为。
解决方案
问题源于浏览器默认锚点跳转逻辑:会让目标元素在全局视口中可见,因此触发页面Y轴滚动。通过以下纯CSS调整可解决:
- 给每个滑块元素(
.slide)设置足够大的scroll-margin-top,让浏览器无法通过滚动页面Y轴来满足锚点对齐要求,从而仅触发容器内的X轴滚动。 - 确保滚动容器(
.gallery)已开启平滑滚动,保证X轴切换的流畅性。
修改后的完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> html { scroll-timeline: --progress-bar; scroll-behavior: smooth; } body { height: 300vh; margin: 0; } .progress-bar { position: fixed; z-index: 10; left: 0; top: 0; width: 100%; height: 0.25em; transform-origin: 0 50%; background: red; animation: grow-progress; animation-duration: auto; animation-timing-function: linear; animation-timeline: --progress-bar; transform: scaleX(0); } .gallery-wrap { width: 100%; height: 600px; background: pink; padding: 100px 20%; box-sizing: border-box; } .gallery-frame { width: 100%; height: 100%; position: relative; } .gallery { width: 100%; height: 100%; display: flex; overflow-x: scroll; scroll-snap-type: x mandatory; scroll-timeline: --progress-bar inline; align-items: center; scroll-behavior: smooth; scrollbar-width: none; } .gallery::-webkit-scrollbar { display: none; } .index-bar { height: 6px; width: 100%; background: red; position: absolute; top: 0; left: 0; animation: grow-progress; animation-duration: auto; animation-timing-function: linear; animation-timeline: --progress-bar; transform-origin: left; transform: scaleX(calc(1 / 3)); z-index: 1; } .nav { width: 100%; background: #ffffff69; position: absolute; display: flex; justify-content: space-between; padding: 16px; box-sizing: border-box; z-index: 1; } .nav a { width: 36px; display: block; aspect-ratio: 1 / 1; background: black; border-radius: 100%; } .slide { width: 100%; flex-shrink: 0; scroll-snap-align: center; align-self: stretch; position: relative; display: flex; align-items: center; scroll-margin-top: 100vh; /* 关键:阻止页面Y轴滚动 */ } .slide .nav { opacity: 0; } .screen1 { background: #fff0ce; } .screen2 { background: #e4f1fd; } .screen3 { background: #ccfff5; } @keyframes grow-progress { to { transform: scaleX(1); } } </style> </head> <body> <div class="progress-bar"></div> <div class="gallery-wrap"> <div class="gallery-frame"> <div class="gallery"> <div class="index-bar"></div> <div class="nav" style="pointer-events:none"> <!-- 修正拼写错误:pointer-evet → pointer-events --> <a href="#slide1"></a> <a href="#slide2"></a> </div> <div id="slide1" class="slide screen1"> <div class="nav"> <a href="#slide3"></a> <a href="#slide2"></a> </div> </div> <div id="slide2" class="slide screen2"> <div class="nav"> <a href="#slide1"></a> <a href="#slide3"></a> </div> </div> <div id="slide3" class="slide screen3"> <div class="nav"> <a href="#slide2"></a> <a href="#slide1"></a> </div> </div> </div> </div> </div> </body> </html>
注:同时修正了原代码中的拼写错误pointer-evet:none为pointer-events:none。
内容的提问来源于stack exchange,提问作者Ziv Feldman
相关产品推荐
相关产品推荐

