如何同时实现Scroll-Snap滚动吸附与背景色过渡效果?
解决Scroll-Snap与背景色过渡共存的问题
问题核心很明确:当给main设置height:100vh时,滚动条属于main元素而非window,但你原来的代码监听的是window的滚动事件,导致背景色切换逻辑完全不触发;去掉height后,滚动条回到window,背景色生效,但scroll-snap因为没有明确的滚动容器高度而失效。
修复方案
- 将滚动事件的监听对象从
window改为main元素 - 调整滚动位置的计算逻辑,基于
main的滚动状态而非window - 保留
main的height:100vh以维持scroll-snap的功能
修改后的完整代码
JavaScript
const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add('show'); } else { entry.target.classList.remove('show'); } }); }); // 监听main元素的滚动事件,而非window $('main').scroll(function() { // selectors var $main = $(this), $body = $('body'), $panel = $('.panel'); // 基于main的滚动位置和自身高度计算触发点 var scroll = $main.scrollTop() + ($main.height() / 3); $panel.each(function () { var $this = $(this); if ($this.position().top <= scroll && $this.position().top + $this.height() > scroll) { $body.removeClass(function (index, css) { return (css.match (/(^|\s)color-\S+/g) || []).join(' '); }); $body.addClass('color-' + $(this).data('color')); } }); }).scroll(); const hiddenElements = document.querySelectorAll('.hidden'); hiddenElements.forEach((el) => observer.observe(el));
CSS(保留原有核心配置)
body { margin: 0; padding: 0; font-family: sans-serif; background-color: rgb(36, 164, 138); transition: background-color 1s ease; } div { place-items: center; align-content: center; min-height: 100vh; color: white; position: relative; scroll-snap-align: start; } .panel { min-height: 100vh; display: flex; justify-content: space-around; align-items: center; font-family: sans-serif; } main { scroll-snap-type: y mandatory; overflow-y: scroll; height: 100vh; /* 必须保留,保证scroll-snap生效 */ } .color-green { background-color: rgb(36, 164, 138); } .color-red { background-color: rgb(211, 79, 79); } .color-blue { background-color: rgb(67, 91, 175); } .color-salmon { background-color: lightsalmon; } .hidden { opacity: 0; filter: blur(5px); transform: translateX(-100%); transition: all 1s; } .show { opacity: 1; filter: blur(0); transform: translateX(0); }
HTML(无需修改)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS SNAP EFFECT</title> <link rel="stylesheet" href="styles.css"> <script defer src="app.js"></script> <script src="https://code.jquery.com/jquery-3.7.0.js" integrity="sha256-JlqSTELeR4TLqP0OG9dxM7yDPqX1ox/HfgiSLBj8+kM=" crossorigin="anonymous"> </script> </head> <body> <main> <div class="panel" data-color="green"> <h1 class="hidden">First</h1> </div> <div class="panel" data-color="red"> <h1 class="hidden">Second</h1> </div> <div class="panel" data-color="blue"> <h1 class="hidden">Third</h1> </div> <div class="panel" data-color="salmon"> <h1 class="hidden">Last</h1> </div> </main> </body> </html>
修改后,scroll-snap会因为main的固定高度正常工作,背景色过渡也会因为监听了正确的滚动容器而触发,两者就能完美共存了。
内容的提问来源于stack exchange,提问作者Kyle Tobin
相关产品推荐
相关产品推荐

