如何仅当用户开始滚动并且其粘性变得明显时才更改“position:sticky”元素的外观?

问题描述 投票:0回答:3

我有一些非常简单的 CSS 代码,可以使一个特定的 div 容器“粘住”,当用户向下滚动时,该 div 元素会按预期锁定在屏幕顶部。

我正在尝试弄清楚如何制作它,以便用户向下滚动并且该元素的“粘性”变得清晰时,有问题的粘性元素会改变外观?也许当它到达父容器的顶部时,也许只是当用户滚动经过某个点时——可能有多种方法可以对此进行编码,但我似乎无法弄清楚。

具体来说,我想要做的是——当它们开始滚动时添加一个 1px 的底部边框,粘性元素如下。在那之前,让边框不可见/不存在。

另请注意,我读到边框会导致粘性元素出现奇怪的问题,而阴影是解决此问题的方法,因此我目前正在为“边框”执行此操作:

box-shadow: inset 0 0px 0 #000000, inset 0 -1px 0 #000000;

谢谢!

javascript html css
3个回答
1
投票

只需将您的样式放入一个类中,然后在 HTML 中切换该类即可

//Simply with jQuery
$(window).scroll(function () {
   if ($(this).scrollTop() > 150) {
      $('.element').addClass('your_class_name');
   } else {
      $('.element').removeClass('your_class_name');
   }
});

//With JavaScript
window.onscroll = function() {
if (document.body.scrollTop > 150 || document.documentElement.scrollTop > 150) {
    document.querySelector(".element").classList.add("your_class_name");
  } else {
    document.querySelector(".element").classList.remove("your_class_name");
  }
};

如果用户滚动到

class
,这将添加 
150px


1
投票

最终使用 IntersectionObserver 来实现此目的。基于滚动的方法的缺点是什么?也许在某些情况下?元素的大小是否根据屏幕大小、使用的浏览器等动态/响应式调整?这可能会导致在错误的时刻做出改变,这可能看起来非常糟糕。 IntersectionObserver 似乎一致地根据粘性元素和父 div 的相对位置进行更改——因此它应该在所有用例中保持一致。

https://css-tricks.com/how-to-detect-when-a-sticky-element-gets-pinned/


0
投票

我最终跟踪了元素在滚动上的“顶部”位置,这似乎很适合我们的目的。

这是一个示例,尽管采用的是 React hook 和 TS 的形式。我相信你能明白要点:

// hook to determine if a sticky element is in a "sticking" state
// this tracks it's top position and compares it to the previous top position on scroll
// if it hasn't changed, it's sticking
export default function useIsSticking({ elementRef }: { elementRef: React.RefObject<HTMLElement> }) {
  const previousTop = useRef<number>(-1)
  const [isSticking, setIsSticking] = useState<boolean>(false)

  const trackSticky = useCallback(
    () => {
      if (!elementRef.current) return;

      const currentTop = elementRef.current.getBoundingClientRect().top;

      if (previousTop.current === currentTop) {
        setIsSticking(true);
      } else {
        setIsSticking(false);
      }

      previousTop.current = currentTop;
    }, []
  );

  useEffect(() => {
    window.addEventListener('scroll', trackSticky);
    return () => {
      window.removeEventListener('scroll', trackSticky);
    }
  }, []);


  return { isSticking }
};


© www.soinside.com 2019 - 2024. All rights reserved.