You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

滚动时切换元素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.top value in the scroll-down logic.
  • The transition: position 0s rule prevents odd visual glitches that can happen when switching between absolute and fixed.

内容的提问来源于stack exchange,提问作者Paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:07:54