如何实现topPanel居右、背景图居左且维持滚动联动效果?
布局调整导致背景滚动交互失效的解决指导
问题概述
我正在开发一个项目,已实现用户滚动时通过move1、move2、move3类控制背景图移动的功能。现需调整布局,将topPanel文本区域从顶部移至右侧,同时将背景图移至左侧,目标效果参考纽约时报的交互页面。尝试使用Grid布局调整后,背景图完全停止移动,需要解决指导。
问题原因与修复方案
核心问题分析
Grid布局改变了元素的定位上下文,原JS中依赖窗口滚动的位置计算逻辑不再适配;同时原body:after的背景覆盖范围未做限制,会被右侧文本区域遮挡,且滚动事件的触发条件也需要对应调整。
分步修复
重构Grid布局
- 给
body设置Grid布局,划分左侧背景区和右侧文本区,文本区固定宽度(如35vw),背景区占剩余空间 - 移除
topPanel的float属性,设置其为Grid项,占据右侧列并铺满高度
- 给
修正JS滚动位置计算
- 原代码基于窗口滚动计算元素位置,新布局中
topPanel是自身滚动容器,需改为基于topPanel的滚动距离计算元素相对位置 - 更新触发高亮和背景切换的阈值逻辑,确保元素进入
topPanel可视区域时触发
- 原代码基于窗口滚动计算元素位置,新布局中
调整背景元素样式
- 修改
body:after的定位,限制其仅在左侧Grid区域显示,避免覆盖右侧文本 - 优化背景图的尺寸和定位逻辑,确保在左侧区域完整展示
- 修改
修改后的完整代码
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <div class="topPanel"> <div class="inner"> <p>Scroll to see feature titles</p> <p>Scroll to see feature titles</p> <p>Scroll to see feature titles</p> <p>Scroll to see feature titles</p> <p>Scroll to see feature titles</p> <p>Scroll to see feature titles</p> <h2 class="feature feature1" id="title1">Feature 1</h2> <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. </p> <h2 class="feature feature2" id="myDiv">Feature 2</h2> <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p> <h2 class="feature feature3" id="title3">Feature 3</h2> <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p> </div> </div>
CSS
body { margin: 0; display: grid; grid-template-columns: 1fr 35vw; height: 100vh; overflow: hidden; } .topPanel { height: 100vh; overflow-y: auto; padding: 20px; background: white; position: relative; z-index: 1; } body:after { content: ""; z-index: 0; grid-column: 1; background: url(http://www.reedyrace.com/images/b64d-chassis.jpg) no-repeat 50% 0%; background-size: cover; transition: background-position 1s ease; } .inner { max-width: 800px; margin: 0 auto; } .highlight { background: red; } .move1 body:after { background-position: 0% 50%; } .move2 body:after { background-position: 0% 100%; } .move3 body:after { background-position: 100% 50%; }
JavaScript
$(document).ready(function() { var panelHeight = $(".topPanel").height(), topLimit = panelHeight; $(".topPanel").on("scroll", function() { // 先移除所有move类,避免叠加 $("body").removeClass("move1 move2 move3"); $(".feature").each(function() { // 计算元素相对于topPanel顶部的位置,减去滚动距离 var thisTop = $(this).offset().top - $(".topPanel").offset().top - $(".topPanel").scrollTop(); if (thisTop <= topLimit && thisTop > -$(this).height()) { $(".feature").removeClass("highlight"); $(this).addClass("highlight"); if ($(this).hasClass("feature1")) { $("body").addClass("move1"); } else if ($(this).hasClass("feature2")) { $("body").addClass("move2"); } else if ($(this).hasClass("feature3")) { $("body").addClass("move3"); } // 找到当前可视区域的元素后跳出循环,避免重复触发 return false; } }); }); });
内容的提问来源于stack exchange,提问作者newuser
相关产品推荐
相关产品推荐

