Honzis Novák
Honzis Novák

Reputation: 269

Highlight navbar li a color based which div is on the screen

JSFIDDLE: https://jsfiddle.net/sjhpmzuk/1/

I have a one page scroll website. I've created demo for you (up), so you can understand better. What I want is that, when I scroll through the page, I want to automatically change a color of navigation.

For example, when I will come to this page, .red is on the top, so I want to li:nth-of-type(1) a{color:yellow}. When I scroll through the page, blue will be in point of our interest, so li:nth-of-type(2) a{color:yellow} etc. with all of other fictional divs to footer div (in my example .green), which will work same way.

I found, that BootStrap can do this somehow, but it is too complicated and long code for me. Could please somebody show me how to do it with my example? :)

Thanks for your time!

Upvotes: 3

Views: 408

Answers (1)

Gleb Kemarsky
Gleb Kemarsky

Reputation: 10418

First solution. By Bootsrap's components and javascript.

  1. Navbar, Fixed to top
  2. ScrollSpy

https://jsfiddle.net/glebkema/24tddf46/

@import url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css');

@media (min-width: 768px) {
  .navbar-nav {
    float: none;
    text-align: center;
  }
  .navbar-nav>li {
    float: none;
    display: inline-block;
  }
}

.navbar-inverse .navbar-nav > .active:nth-of-type(1) > a,
.navbar-inverse .navbar-nav > .active:nth-of-type(1) > a:hover,
.navbar-inverse .navbar-nav > .active:nth-of-type(1) > a:focus {
  color: red;
}

.navbar-inverse .navbar-nav > .active:nth-of-type(2) > a,
.navbar-inverse .navbar-nav > .active:nth-of-type(2) > a:hover,
.navbar-inverse .navbar-nav > .active:nth-of-type(2) > a:focus {
  color: blue;
}

.navbar-inverse .navbar-nav > .active:nth-of-type(3) > a,
.navbar-inverse .navbar-nav > .active:nth-of-type(3) > a:hover,
.navbar-inverse .navbar-nav > .active:nth-of-type(3) > a:focus {
  color: green;
}

#red,
#blue,
#green {
  width: 100%;
  height: 1000px;
}
#red   { background: red; }
#blue  { background: blue; }
#green { background: green; }
<body data-spy="scroll" data-target="#navbar" data-offset="60">
  <nav id="navid" class="navbar navbar-inverse navbar-fixed-top">
    <div class="container">
      <div class="navbar-header">
        <button type="button" class="navbar-toggle collapsed" aria-controls="navbar" aria-expanded="false" data-target="#navbar" data-toggle="collapse">
          <span class="sr-only">Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
      </div>
      <div id="navbar" class="navbar-collapse collapse">
        <ul class="nav navbar-nav">
          <li><a href="#red">red</a></li>
          <li><a href="#blue">blue</a></li>
          <li><a href="#green">green</a></li>
        </ul>
      </div>
    </div>
  </nav>
  <div id="red"></div>
  <div id="blue"></div>
  <div id="green"></div>
  
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>  
</body>


Second solution. By CSS and jQuery.

https://jsfiddle.net/glebkema/kbggfwhk/

$(document).ready(function() {
  var selectWindow = $(window);
  var selectBody   = $('body,html');
  var selectRed    = $('#red');
  var selectBlue   = $('#blue');
  var selectGreen  = $('#green');

  var NAVBAR = '.sticky-header';
  var menuRed   = $(NAVBAR + '>ul>li:nth-of-type(1)');
  var menuBlue  = $(NAVBAR + '>ul>li:nth-of-type(2)');
  var menuGreen = $(NAVBAR + '>ul>li:nth-of-type(3)');

  var OFFSET = $(NAVBAR).outerHeight();
  var scrollRed   =   selectRed.offset().top - OFFSET;
  var scrollBlue  =  selectBlue.offset().top - OFFSET;
  var scrollGreen = selectGreen.offset().top - OFFSET;
  
    menuRed.click(function(){ scrollTo(scrollRed)   });
   menuBlue.click(function(){ scrollTo(scrollBlue)  });
  menuGreen.click(function(){ scrollTo(scrollGreen) });

  selectWindow.scroll(function() {
    var currentY = $(this).scrollTop();
    if (currentY >= scrollGreen) { checkActive(menuGreen); } else 
    if (currentY >= scrollBlue)  { checkActive(menuBlue);  } else 
    if (currentY >= scrollRed)   { checkActive(menuRed);   };
  });

  function scrollTo(scrollTopNew) {
    selectBody.stop().animate({scrollTop: scrollTopNew}, 1000);
  }
  
  function checkActive(e) {
    if( !e.hasClass('active') ) {
      $(NAVBAR + '>ul>li.active').removeClass('active');
      e.addClass('active');
    }
  }
}); //jQuery
body {
  margin: 0;
  padding: 0;
}

.sticky-header {
  background-color: #393939;
  height: 50px;
  position: fixed;
  width: 100%;
}

.sticky-header ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  text-align: center;
}

.sticky-header li {
  display: inline-block;
}
.sticky-header li a {
  color: white;
  display: inline-block;
  font-size: 20px;
  line-height: 50px; /* = height of .sticky-header */
  padding: 0 15px;
  text-decoration: none;
}
.sticky-header li a:hover { 
  background-color: #555;
}
.sticky-header > ul > li:nth-of-type(1).active a { color: red; }
.sticky-header > ul > li:nth-of-type(2).active a { color: blue; }
.sticky-header > ul > li:nth-of-type(3).active a { color: green; }

#red,
#blue,
#green {
  height: 1000px;
  width: 100%;
}
#red   { background: red; }
#blue  { background: blue; }
#green { background: green; }
<div class="sticky-header">
  <ul>
    <li class="active"><a href="#">red</a></li>
    <li><a href="#">blue</a></li>
    <li><a href="#">green</a></li>
  </ul>
</div>
<div id="red"></div>
<div id="blue"></div>
<div id="green"></div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>

Upvotes: 3

Related Questions