简体   繁体   English

根据条件滚动时如何在固定位置和相对位置之间设置元素的位置?

[英]How can I set an element's position between fixed and relative while scrolling based on conditions?

<div id="wrapper">
 <div id="left-panel"></div>
 <div id="long-right-panel></div>
</div>
<footer></footer>

Upon scrolling, I am dealing with a problem when the #wrapper top position is <= 0 and when the footer top position subtracted from the #left-panel bottom position is >=0, I'd like the #left-panel to have the style position of fixed. 滚动时,当#wrapper顶部位置<= 0并且从#left-panel底部位置减去footer顶部位置> = 0时,我正在处理一个问题,我希望#left-panel具有固定的样式位置。 Else it should have position of relative. 否则它应该具有相对位置。

I'm running into a problem where once the above conditions are met, the #left-panel flips between a position of relative and fixed. 我遇到一个问题,一旦满足以上条件,#left-panel就会在相对位置和固定位置之间切换。

Here's some code for clarification: 这是一些代码以供说明:

// creates event listener
window.addEventListener('scroll', handleScroll);

// get DOM elements outside of scroll event
  const wrapperRect = document.getElementById('wrapper').getBoundingClientRect();

  const leftPanel = document.getElementById('left-panel');
  const leftPanelRect = leftPanel.getBoundingClientRect();

  const rightPanel = document.getElementById('long-right-panel');
  const rightPanelRect = rightPanel.getBoundingClientRect();

  const footerRect = document.querySelector('footer').getBoundingClientRect();

function handleScroll () {
  /* if the #wrapper has scrolled past the top of the viewport and the space between the top of the footer and the bottom of the #left-panel is greater than 0, set #left-panel to position fixed */
  if (wrapperRect.top <= 0 && (footerRect.top - leftPanelRect.bottom) > 0) {
    leftPanel.setAttribute("style", "position: fixed; top: 3rem;");
    rightPanel.setAttribute("style", "margin-left: 45%;");
  }
  /* else set the #left-panel position to relative */
  else {
    leftPanel.setAttribute("style", "position: relative;");
    rightPanel.setAttribute("style", "");
  }
}

The code works except, I need some sort of flag or means of breaking out of it because as it stands, when the conditions are true, its fixed, but when they're false, the #left-panel jumps back to its original position and the #wrapper top is < 0, and the space between the footerRect.top and leftPanelRect.bottom is > 0 and changes it to fixed ... then scrolling changes back to relative ... this causes jumps and flickering. 该代码有效,除了,我需要某种标志或打破它的方法,因为就目前情况而言,当条件为真时,它固定了,但是当它们为假时, #left-panel跳回到其原始位置#wrapper top <0,并且footerRect.topleftPanelRect.bottom之间的空间> 0并将其更改为Fixed ...然后滚动更改为相对值...这将导致跳转和闪烁。

Any advice on how to fix? 有关如何修复的任何建议?

Your code actually works fine, I tested it with latest Chrome on Windows 8.1. 您的代码实际上运行良好,我在Windows 8.1上使用最新的Chrome对其进行了测试。 But if you mean that page jumps when you scroll 1st time, try to add 但是,如果您是说第一次滚动时页面会跳转,请尝试添加

window.addEventListener('load', handleScroll);

on top of the script - to check conditions and set styles on page load: 在脚本之上-检查条件并在页面加载时设置样式:

<style>
#wrapper {
  height: 200vh;
  width: 100%;
}

#left-panel {
  background-color: #f90;
  height: 200px;
  width: 45%;
}

#long-right-panel {
  background-color: #f09;
  height: 500px;
  margin-top: 3rem;
  width: 55%;

}

#footer {
  background-color: #9f9;
  height: 100px;
  width: 100%;
}
</style>

<div id="wrapper">
  <div id="left-panel"></div>
  <div id="long-right-panel"></div>
</div>
<footer id="footer"></footer>

<script>
// creates event listener
window.addEventListener('load', handleScroll);
window.addEventListener('scroll', handleScroll);

// get DOM elements outside of scroll event
  const wrapperRect = document.getElementById('wrapper').getBoundingClientRect();

  const leftPanel = document.getElementById('left-panel');
  const leftPanelRect = leftPanel.getBoundingClientRect();

  const rightPanel = document.getElementById('long-right-panel');
  const rightPanelRect = rightPanel.getBoundingClientRect();

  const footerRect = document.querySelector('footer').getBoundingClientRect();

function handleScroll () {
  /* if the #wrapper has scrolled past the top of the viewport
  and the space between the top of the footer and the bottom of the #left-panel
  is greater than 0, set #left-panel to position fixed */
  if (wrapperRect.top <= 0 && (footerRect.top - leftPanelRect.bottom) > 0) {
    leftPanel.setAttribute("style", "position: fixed; top: 3rem;");
    rightPanel.setAttribute("style", "margin-left: 45%;");
  }
  /* else set the #left-panel position to relative */
  else {
    leftPanel.setAttribute("style", "position: relative;");
    rightPanel.setAttribute("style", "");
  }
}
</script>

https://codepen.io/svitch/pen/yzEzmz https://codepen.io/svitch/pen/yzEzmz

Usually sticky panel scripts have three conditions: 通常,粘性面板脚本具有三个条件:

  1. panel.top < wrapper.top panel.top <wrapper.top
  2. panel.top > wrapper.top && panel.bottom < wrapper.bottom panel.top> wrapper.top && panel.bottom <wrapper.bottom
  3. panel.bottom > wrapper.bottom panel.bottom> wrapper.bottom

In that case, your panel will stick when wrapper is going beyond the screen and unstick when panel is no longer needed. 在这种情况下,当包装纸超出屏幕范围时,面板将粘住,而不再需要面板时,面板将不粘。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM