滚动时切换元素position absolute与fixed的交互效果实现需求
Got it, let's tackle this sticky icon scenario step by step! Here's a complete implementation that matches your exact requirements:
HTML Structure
First, let's set up the basic page structure with our two blocks and the icon:
<div class="green-block"> <div class="circle-icon"></div> </div> <div class="blue-block"></div>
Base CSS
Next, we'll style the blocks and set the icon's initial absolute position:
/* Reset default browser styles */ * { margin: 0; padding: 0; box-sizing: border-box; } .green-block { position: relative; /* Required for the icon's absolute positioning */ height: 800px; /* Make it tall enough to scroll past */ background-color: #4CAF50; } .circle-icon { position: absolute; top: 200px; /* Initial vertical position inside green block */ left: 50px; width: 60px; height: 60px; border-radius: 50%; background-color: white; transition: position 0s; /* Prevent weird transition glitches when switching positions */ } .blue-block { height: 1000px; /* Give enough space to scroll after the green block */ background-color: #2196F3; }
JavaScript Logic
The magic happens here—we'll listen for scroll events, track scroll direction, and toggle the icon's positioning based on where the blue block is:
const circleIcon = document.querySelector('.circle-icon'); const blueBlock = document.querySelector('.blue-block'); const greenBlock = document.querySelector('.green-block'); // Save the icon's initial position relative to the viewport const initialIconViewportTop = circleIcon.getBoundingClientRect().top; // Get the blue block's top offset from the start of the document const blueBlockDocumentTop = blueBlock.offsetTop; let lastScrollPosition = window.scrollY; window.addEventListener('scroll', () => { const currentScrollPosition = window.scrollY; const isScrollingDown = currentScrollPosition > lastScrollPosition; // Check if blue block has reached the top of the viewport const blueBlockIsAtViewportTop = currentScrollPosition >= blueBlockDocumentTop; // Check if we've scrolled back up to the icon's initial position area const backToIconInitialPosition = currentScrollPosition + initialIconViewportTop <= greenBlock.offsetTop + initialIconViewportTop; if (isScrollingDown) { // Switch to fixed positioning when blue block hits the viewport top if (blueBlockIsAtViewportTop) { circleIcon.style.position = 'fixed'; circleIcon.style.top = '0'; // Stick to viewport top once blue block is in place } } else { // Switch back to absolute positioning when scrolling up and we're past the initial position if (!blueBlockIsAtViewportTop && backToIconInitialPosition) { circleIcon.style.position = 'absolute'; circleIcon.style.top = '200px'; // Reset to original vertical position } } // Update last scroll position for next iteration lastScrollPosition = currentScrollPosition; });
Quick Notes:
- Make sure the green block has
position: relative—otherwise the icon's absolute positioning will be relative to the entire document instead of the green block. - If you want the icon to stick to a different position when fixed (not the top), just adjust the
circleIcon.style.topvalue in the scroll-down logic. - The
transition: position 0srule prevents odd visual glitches that can happen when switching betweenabsoluteandfixed.
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

