Как я могу установить положение элемента между фиксированным и относительным при прокрутке в зависимости от условий?

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

При прокрутке я сталкиваюсь с проблемой, когда #wrapper верхняя позиция <= 0 и когда footer верхняя позиция вычитается из #left-panel нижняя позиция>=0, я бы хотел #left-panel иметь фиксированную позицию стиля. Иначе оно должно иметь положение родственника.

Я сталкиваюсь с проблемой, когда после выполнения вышеуказанных условий # левая панель переключается между позицией относительной и фиксированной.

Вот код для пояснения:

// 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", "");
  }
}

Код работает, за исключением того, что мне нужен какой-то флаг или средство для его устранения, потому что в том виде, в каком он есть, когда условия истинны, они исправлены, но когда они ложны, #left-panel возвращается в исходное положение и #wrapper верх < 0, а пространство между footerRect.top а также leftPanelRect.bottom is > 0 и изменяет его на фиксированный... затем прокрутка изменяется обратно на относительную... это вызывает скачки и мерцание.

Любой совет, как исправить?

1 ответ

Ваш код на самом деле работает нормально, я протестировал его с последним Chrome на Windows 8.1. Но если вы имеете в виду, что страница переходит при первой прокрутке, попробуйте добавить

window.addEventListener('load', handleScroll);

поверх скрипта - чтобы проверить условия и установить стили при загрузке страницы:

<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

Обычно скрипты липкой панели имеют три условия:

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

В этом случае ваша панель будет зависать, когда обертка выходит за пределы экрана, и отклеиваться, когда панель больше не нужна.

Другие вопросы по тегам