Не удалось реализовать липкую навигационную панель

#javascript #html #css

Вопрос:

Я использую некоторый код из проекта codepen для работы над липкой боковой панелью с purejs. Когда высота боковой панели увеличивается до 100 вч в css из моего собственного проекта, функциональность боковой панели прекращается, даже если это тот же код, что и в ручке. Может ли кто-нибудь дать краткое объяснение кода?

Это и есть код:

 var wrapper = document.getElementById("wrapper"),
  main = document.getElementById("main"),
  sidebar = document.getElementById("sc");
window.onscroll = function() {
  document.getElementById('sc').setAttribute("style", "display:block;width:"   document.getElementById("sidebar").offsetWidth   "px");
  document.getElementById('sc').style.width = document.getElementById("sidebar").offsetWidth;
  //if sidebar smaller than main
  if (sidebar.offsetHeight < main.offsetHeight) {
    //if sidebar smaller than screen - stick to top rather than bottom
    if (sidebar.offsetHeight < window.innerHeight) {
      if ((wrapper.getBoundingClientRect().bottom < (window.innerHeight)) amp;amp;
        ((wrapper.getBoundingClientRect().bottom < sidebar.offsetHeight))
      ) {
        wrapper.classList.remove("fix-top-VP");
        wrapper.classList.add("flex-bottom");
      } else if (wrapper.getBoundingClientRect().top < 0) {
        wrapper.classList.add("fix-top-VP");
        wrapper.classList.remove("flex-bottom");
      } else {
        wrapper.classList.remove("fix-top-VP");
        wrapper.classList.remove("flex-bottom");
      }
    }
    //if wrapper taller than sidebar - stick to bottom
    else if (sidebar.offsetHeight < wrapper.offsetHeight) {
      if (wrapper.getBoundingClientRect().bottom < (window.innerHeight)) {
        wrapper.classList.remove("fix-bottom-VP");
        wrapper.classList.add("flex-bottom");
      } else if (wrapper.getBoundingClientRect().bottom > (sidebar.offsetHeight   window.innerHeight)) {
        wrapper.classList.remove("fix-bottom-VP");
        wrapper.classList.remove("flex-bottom");
      } else {
        wrapper.classList.add("fix-bottom-VP");
        wrapper.classList.remove("flex-bottom");
      }
    }
  }

} 
 body * {
  box-sizing: border-box;
}

#header,
#footer {
  width: 100%;
  height: 200px;
  background-color: #eee;
  text-align: center;
}

body,
#main,
#wrapper,
#sc {
  padding: 15px;
}

#main {
  background-color: #F88300;
  width: 60%;
  height: 180vh;
}

#sidebar {
  position: relative;
  width: 25%;
}

#sc {
  background-color: #FFD600;
  height: 80vh;
}

#wrapper {
  display: flex;
  justify-content: space-between;
}

#wrapper.fix-bottom-VP #sc,
#wrapper.fix-top-VP #sc {
  position: fixed;
}

#wrapper.fix-bottom-VP #sc {
  bottom: 15px;
}

#wrapper.fix-top-VP #sc {
  top: 15px;
}

#wrapper.flex-bottom {
  align-items: flex-end;
} 
 <div id="header">
  <h1>Lightweight, Intelligent Sticky Sidebar, NO libraries</h1>
</div>
<div id="wrapper">
  <div id="main">
    Main content
  </div>
  <div id="sidebar">
    <div id="sc">
      Sticky sidebar
    </div>
  </div>
</div>
<div id="footer"></div> 

Кодовый набор

Я открыт для лучшей реализации той же идеи там.

Комментарии:

1. Не можете ли вы воспользоваться: css-tricks.com/position-sticky-2

2. Привет, Марк, решил ли один из приведенных ниже ответов вашу проблему? Если это так, пожалуйста, примите один из них, поставив зеленую галочку. Это позволяет тем, кто отвечает, узнать, что ваша проблема решена. Если нет, пожалуйста, расскажите подробнее о том, какие проблемы у вас продолжают возникать.

Ответ №1:

Вы можете достичь этого, обновив свой JavaScript следующим кодом

   var header = document.getElementById("header"),
        sticky = header.offsetTop,
        wrapper = document.getElementById("wrapper"), 
        main = document.getElementById("main"), 
        sidebar = document.getElementById("sc");

    window.onscroll = function() {

        if (window.pageYOffset > sticky) {
          header.classList.add("sticky");
        } else {
          header.classList.remove("sticky");
        }

      document.getElementById('sc').setAttribute("style","display:block;width:"   document.getElementById("sidebar").offsetWidth "px");
      document.getElementById('sc').style.width = document.getElementById("sidebar").offsetWidth; 

      
      //if sidebar smaller than main
      if (sidebar.offsetHeight < main.offsetHeight) {
        //if sidebar smaller than screen - stick to top rather than bottom
        if (sidebar.offsetHeight < window.innerHeight) {
          if ((wrapper.getBoundingClientRect().bottom < (window.innerHeight))
              amp;amp; ((wrapper.getBoundingClientRect().bottom < sidebar.offsetHeight))
             ) {
            wrapper.classList.remove("fix-top-VP");
            wrapper.classList.add("flex-bottom");
          }
          else if (wrapper.getBoundingClientRect().top < 0 ) {
            wrapper.classList.add("fix-top-VP");
            wrapper.classList.remove("flex-bottom");
          }
          else {
            wrapper.classList.remove("fix-top-VP");
            wrapper.classList.remove("flex-bottom");
          }
        }
        //if wrapper taller than sidebar - stick to bottom
        else if (sidebar.offsetHeight < wrapper.offsetHeight) {
          if (wrapper.getBoundingClientRect().bottom < (window.innerHeight)) {
            wrapper.classList.remove("fix-bottom-VP");
            wrapper.classList.add("flex-bottom");
          }
          else if (wrapper.getBoundingClientRect().bottom > (sidebar.offsetHeight   window.innerHeight)) {
            wrapper.classList.remove("fix-bottom-VP");
            wrapper.classList.remove("flex-bottom");
          }
          else {
            wrapper.classList.add("fix-bottom-VP");
            wrapper.classList.remove("flex-bottom");
          }
        }
      }
}
 

и и для вашего CSS следующий код

 .sticky {
  position: fixed;
  top: 0;
  width: 100%;
  z-index: 1;
}
 

Ответ №2:

Вы можете использовать position:sticky и элементы html5, такие как header , footer , main и aside .

 * {
  box-sizing: border-box;
}

body {
  display: flex;
  flex-direction: column;
  font-family: sans-serif;
}

header,
footer {
  background-color: #369;
  color: #eee;
  display: flex;
  justify-content: center;
}

#flex-row {
  display: flex;
  flex-direction: row;
}

header, footer, main, aside {
  padding: 15px;
}

main, aside {
  font-size: 20px;
}

main {
  background-color: #ed3;
  height: 180vh;
  flex-grow: 3;
}

aside {
  background-color: #fe5;
  height: 100vh;
  flex-grow: 1;
  position: sticky;
  top: 0;
} 
 <body>
  <header>
    <h1>Sticky Sidebar - best practice</h1>
  </header>
  <div id="flex-row">
    <main>
      Main content
    </main>
    <aside>
      Sticky sidebar
    </aside>
  </div>
  <footer>
    <h1>Footer</h1>
  </footer>
</body>