How can I auto scroll to the next possible div and update the top nav control with it?

Viewed 66


I would like to create a navigation that scrolls to the specific part and also auto-updates when scrolling up/down.
It should also auto-scroll to the next possible div when scrolling. (this is not that important)

However, it should update on scroll when passing/on the corresponding div. (using jquery or plain js)

I have used this as the backend code for the navigation:

function ShowLanding() {
    window.scrollTo(0,0);
}

function ShowContact() {
    document.getElementById("contact").scrollIntoView();
}

function ShowAbout() {
    document.getElementById("about").scrollIntoView();
}

//nav update code

var nav = $('nav');
  var line = $('<div />').addClass('line');
  
  line.appendTo(nav);
  
  var active = nav.find('.active');
  var pos = 0;
  var wid = 0;
  
  if (active.length) {
    pos = active.position().left;
    wid = active.width();
    line.css({
      left: pos,
      width: wid });
  
  }
  
  nav.find('ul li a').click(function (e) {
    e.preventDefault();
    if (!$(this).parent().hasClass('active') && !nav.hasClass('animate')) {
  
      nav.addClass('animate');
  
      var _this = $(this);
  
      nav.find('ul li').removeClass('active');
  
      var position = _this.parent().position();
      var width = _this.parent().width();
  
      if (position.left >= pos) {
        line.animate({
          width: position.left - pos + width },
        300, function () {
          line.animate({
            width: width,
            left: position.left },
          150, function () {
            nav.removeClass('animate');
          });
          _this.parent().addClass('active');
        });
      } else {
        line.animate({
          left: position.left,
          width: pos - position.left + wid },
        300, function () {
          line.animate({
            width: width },
          150, function () {
            nav.removeClass('animate');
          });
          _this.parent().addClass('active');
        });
      }
  
      pos = position.left;
      wid = width;
    }
  });

The CSS:

nav {
  position: relative;
  padding-bottom: 12px;
  padding-top: 20px;
  padding-right: 20px;
}

nav .line {
  height: 2px;
  position: absolute;
  bottom: 0;
  margin: 10px 0 0 0;
  background: #ff4242;
}

nav ul {
  padding: 0;
  margin: 0;
  list-style: none;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
}

nav ul li {
  margin: 0 40px 0 0;
  opacity: .4;
  -webkit-transition: all 0.4s ease;
  transition: all 0.4s ease;
}

nav ul li:hover {
  opacity: .7;
}

nav ul li.active {
  opacity: 1;
}

nav ul li:last-child {
  margin-right: 0;
}

nav ul li a {
  text-decoration: none;
  color: #fff;
  text-transform: uppercase;
  display: block;
  font-weight: 600;
  letter-spacing: .2em;
  font-size: 14px;
}

And the HTML:

<nav>
              <ul>
                <li class="active"><a href="javascript:void(0);" onclick="ShowLanding();">HOME</a></li>
                <li><a href="javascript:void(0);" onclick="ShowAbout();">ABOUT</a></li>
                <li><a href="javascript:void(0);" onclick="ShowContact();">CONTACT</a></li>
              </ul>
            </nav>

Result it produces

2 Answers

You mean something like this?

nav {
  position: relative;
  padding-bottom: 12px;
  padding-top: 20px;
  padding-right: 20px;
  padding-left: 20px;
  background-color:darkgray;
  position:fixed;
  top:0;
  right:0;
  left:0;
}

nav .line {
  height: 2px;
  position: absolute;
  bottom: 0;
  margin: 10px 0 0 0;
  background: #ff4242;
}

nav ul {
  padding: 0;
  margin: 0;
  list-style: none;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  
}

nav ul li {
  margin: 0 40px 0 0;
  opacity: .4;
  -webkit-transition: all 0.4s ease;
  transition: all 0.4s ease;
}

nav ul li:hover {
  opacity: .7;
}

nav ul li.active {
  opacity: 1;
}

nav ul li:last-child {
  margin-right: 0;
}

nav ul li a {
  text-decoration: none;
  color: #fff;
  text-transform: uppercase;
  display: block;
  font-weight: 600;
  letter-spacing: .2em;
  font-size: 14px;
}

.home, .about, .contact {
  height:800px;
  text-align:center;
  padding-top:50px;
  color:#000;
  font-size:50px;
  }

.home {background-color:lightblue;}
.about {background-color:lightgreen;}
.contact {background-color:yellow;}
<html>
  <script src="https://code.jquery.com/jquery-3.5.0.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
  $(document).ready(function(){   
  
            var scroll_pos = 0;
            $(document).scroll(function() { 
                scroll_pos = $(this).scrollTop();
                if(scroll_pos > 0 ) {
                   $("li#home").css('background-color', 'blue');
                } else {
                    $("li#home").css('background-color', '');
                }
              if(scroll_pos > 800) {
                   $("li#about").css('background-color', 'blue');
                    $("li#home").css('background-color', '');
                } else {
                    $("li#about").css('background-color', '');
                }
              if(scroll_pos > 1600) {
                 $("li#contact").css('background-color', 'blue');
                  $("li#about").css('background-color', '');
                } else {
                    $("li#contact").css('background-color', '');
                }
                
            });
            });
</script>
  
  <body>
<nav>
    <ul>
       <li id="home"><a href="#" >HOME</a></li>
       <li id="about"><a href="#" >ABOUT</a></li>
       <li id="contact"><a href="#" >CONTACT</a></li>
    </ul>
</nav>
<div class="home">THIS IS HOME </div>
<div class="about">THIS IS ABOUT</div> 
<div class="contact">THIS IS CONTACT</div> 
    </body>
</html>  

Instead of writing this functionality on your own you could use a scrollspy plugin like Simple Scrollspy. You can check out the code on this Github repo.

Related