How to Make My Navbar Change CSS Class Upon Scrolling Past an Anchor Point

How do I make my navbar change CSS class upon scrolling past an anchor point?

If you're using Twitter Bootstrap this can be achieved with the 'Affix' plugin

It's pretty straight forward to set up, here is the documentation

Make a div become visible after scrolling past an anchor point in another div?

One method is to use the scroll event to detect when a certain region is scrolled into view, and then update the navigation bar based on this.

Here is a working example, the only missing piece is your images, but since I didn't have those handy I faked it with some text instead.

Link to JS Fiddle: http://jsfiddle.net/cxyg93h8/4/

Every time the scroll event is fired the code checks each "tab" (content/panel/whatever) to see if it is the top-most tab in view (in the current visible area of the scrollable container). If so, it assigns a CSS class to the corresponding hyperlink to indicate that it is selected.

document.onscroll = function (event) {    var elements = document.getElementsByClassName("tab");    for (var i = 0, len = elements.length; i < len; i++) {        var scrollTop = (document.documentElement && document.documentElement.scrollTop) ||           document.body.scrollTop;        if (elements[i].offsetTop >= scrollTop) {            // found top-most tab in view            // remove previous "selected" class            var selectedElements = document.getElementsByClassName("selected");            if (selectedElements.length === 1) {                selectedElements[0].className = "";            }            // assign new "selected" class            var tab = document.getElementById("tab" + (i + 1).toString() + "Selector");            if (tab) {                tab.parentElement.className = "selected";            }            break;        }    }};
    .nav-bar {        position: fixed;        left: 10px;        top: 16px;        width: 140px;        margin: 0;        border: 0;        padding: 0;    }    .nav-bar ul {        width: 100%;        list-style: none;        margin: 0;        border: 0;        padding: 0;    }    .nav-bar li {        list-style: none;        margin: 2px 0;        border: 1px solid #999;        padding: 10px 20px;        background-color: #ccc;    }    .tabs {        margin: 0 0 0 140px;        padding: 0;        border: 0;        overflow: auto;    }    .tab {        margin: 10px;        border: 1px solid #ccc;        padding: 10px;        width: 400px;    }    .nav-bar .selected {        background-color: Red;    }
<div class='nav-bar'>    <ul>        <li class="selected"><a id='tab1Selector' href="#tab1">Tab 1</a>
</li> <li><a id='tab2Selector' href="#tab2">Tab 2</a>
</li> <li><a id='tab3Selector' href="#tab3">Tab 3</a>
</li> <li><a id='tab4Selector' href="#tab4">Tab 4</a>
</li> <li><a id='tab5Selector' href="#tab5">Tab 5</a>
</li> </ul></div><div class="tabs"> <a name="tab1"></a> <div class="tab"> Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah </div> <a name="tab2"></a> <div class="tab"> Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah </div> <a name="tab3"></a> <div class="tab"> Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah </div> <a name="tab4"></a> <div class="tab"> Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah </div> <a name="tab5"></a> <div class="tab"> Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah </div> </div>

Add class to anchor link when scrolling past anchor div - jquery

I would suggest finding the total height of each section. I am assuming there are no breaks in between each section as well. Then use jQuery to determine the window position. When the window position hits a certain value, make the class switch. Hopefully this can be done only with scrolling, so when you click on a link, it will scroll and the previously described function can run and change the classes for you.

Here is some pseudo-code

$(document).ready(function(){
var section1Height = $('#section1').height();
var section2Height = $('#section2').height();
var section3Height = $('#section3').height();

$(window).scroll(function() {
var winTop = $(window).scrollTop();
if(winTop >= section1Height && winTop <= section2Height){
$('#section1').addClass("newClass").not().removeClass("newClass");
} else if(winTop >= section2Height && winTop <= section3Height){
$('#section2').addClass("newClass").not().removeClass("newClass");
} else if(winTop >= section3Height){
$('#section3').addClass("newClass").not().removeClass("newClass");
}
});
});

Again, this is just a quick example. With more details on your part, I can give a more detailed answer.

Making a menu class active when scrolled past

EDIT: Understood the actual issue:

$(window).scroll(function(){
var scrollTop = $(document).scrollTop();
var anchors = $('body').find('h1');

for (var i = 0; i < anchors.length; i++){
if (scrollTop > $(anchors[i]).offset().top - 50 && scrollTop < $(anchors[i]).offset().top + $(anchors[i]).height() - 50) {
$('nav ul li a[href="#' + $(anchors[i]).attr('id') + '"]').addClass('active');
} else {
$('nav ul li a[href="#' + $(anchors[i]).attr('id') + '"]').removeClass('active');
}
}
});

Same technique; checking if each of your h1 elements are both below the elements top position and above the elements bottom position. If true, get the id of the element and select the corrosponding navigation item and add active class to it.

Updated fiddle: http://jsfiddle.net/yrz54fqm/1/

Old answer

Following code should give you the result you're looking for

$(window).scroll(function(){
var scrollTop = $(document).scrollTop();
var anchors = $('body').find('.anchor');

for (var i = 0; i < anchors.length; i++){
if (scrollTop > $(anchors[i]).offset().top - 50 && scrollTop < $(anchors[i]).offset().top + $(anchors[i]).height() - 50) {
$(anchors[i]).addClass('active');
} else {
$(anchors[i]).removeClass('active');
}
}
});

You need to listen for the scroll event on the window, and check if each of your elements are both below the elements top position and above the elements bottom position.

Replace the var anchors = $('body').find('.anchor'); on line 3 with whatever the anchor class names are in your situation. Here's a fiddle with HTML and CSS aswell: http://jsfiddle.net/yrz54fqm/

Hope it helps :)

Sticky an animated navbar once scrolled past a certain point

Your CSS selector .animate-top is the one causing the problem here. The main issue is that its setting the inner div of your nav to relative. Just change your css selector to the following and it should fix your issue:

.animate-top {
position: fixed;
top:0;
animation: animatetop 0.4s
}

Working example here: https://jsfiddle.net/7ze2fukk/

Hope this helps. Cheers.

Change the fixed navbar's classes depending on the background of the page section it hovers

I'm thinking i'd be easier to properly exploit Bootstrap scrollspy's "activate.bs.scrollspy" event rather than "breaking its rules" and simply override the default href navigation with javascript code.

So i'd suggest you add back the id's to the divs and the matching framgment hrefs to the anchors, let Bootstrap give you the target in the "activate.bs.scrollspy" event via the obj.relatedTarget property, toggle the classes as needed and optionally remove the "activated" class from the nav items so it doesn't appear like the sections are related. If you have additional sections, try using hidden anchors or a hidden nav altogether.

Of course, the cleanest way would be in my opinion to ditch the scrollspy and use window.scrollY and $(window).on('scroll', ...).

Check out the snippet:

$(window).on('activate.bs.scrollspy', function (e, obj) {    if ((window.innerHeight + window.pageYOffset) >= document.body.offsetHeight) {        return;    }
var isBGLight = $(obj.relatedTarget).hasClass('bg-light'); $('.navbar').toggleClass('navbar-dark bg-dark', isBGLight) .toggleClass('navbar-light bg-light', !isBGLight);
//Optional: Remove the active class from the anchor so it doesn't look like the nav is linked to the sections $('.navbar-nav a[href="' + obj.relatedTarget + '"]').removeClass('active');});
//Here we do the actual navigation$('.navbar-nav a').click(function(e) { //Prevent anchor's default behaviour of briefly jumping to the given section before navigating to another page e.preventDefault(); //Substring to eliminate the leading "#" window.location.href = $(e.target).attr('href').substring(1) + '.html';})
.page-section {  padding: 70px 10px}
.page-section.bg-dark * { color: #fff;}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script><script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<body data-spy="scroll" data-target=".navbar" data-offset="15"> <nav class="navbar navbar-expand-sm bg-dark navbar-dark fixed-top"> <a class="navbar-brand" href="#">Logo</a> <ul class="navbar-nav ml-auto"> <li class="nav-item"> <!--Notice I changed the hrefs to point to the div ids--> <a class="nav-link" href="#about">About Us</a> </li> <li class="nav-item"> <a class="nav-link" href="#services">Services</a> </li> <li class="nav-item"> <a class="nav-link" href="#contact">Contact</a> </li> </ul> </nav>
<!--Notice I added the id's to let Bootstrap do it's job--> <div id="about" class="container-fluid bg-light page-section"> <h1>Section 1</h1> <p>Try to scroll this section and look at the navigation bar while scrolling! Try to scroll this section and look at the navigation bar while scrolling!</p> <p>Try to scroll this section and look at the navigation bar while scrolling! Try to scroll this section and look at the navigation bar while scrolling!</p> </div> <div id="services" class="container-fluid bg-dark page-section"> <h1>Section 2</h1> <p>Try to scroll this section and look at the navigation bar while scrolling! Try to scroll this section and look at the navigation bar while scrolling!</p> <p>Try to scroll this section and look at the navigation bar while scrolling! Try to scroll this section and look at the navigation bar while scrolling!</p> </div> <div id="contact" class="container-fluid bg-light page-section"> <h1>Section 3</h1> <p>Try to scroll this section and look at the navigation bar while scrolling! Try to scroll this section and look at the navigation bar while scrolling!</p> <p>Try to scroll this section and look at the navigation bar while scrolling! Try to scroll this section and look at the navigation bar while scrolling!</p> </div></body>

Div anchors scrolling too far

To fix this with CSS you can add a padding to the Elements you want to jump to:

Example

Alternatively, you could add a border:

div{   height: 650px;   background:#ccc;   /*the magic happens here*/  border-top:42px solid #fff;}ul{  top: 0;   width: 100%;   height:20px;   position: fixed;   background: deeppink;   margin:0;  padding:10px; }li{  float:left;  list-style:none;  padding-left:10px;}div:first-of-type{   margin-top:0; }
<!-- content to be placed inside <body>…</body> --><ul>  <li><a href="#s1">link 1</a>  <li><a href="#s2">link 2</a>  <li><a href="#s3">link 3</a>  <li><a href="#s4">link 4</a></ul><div id="s1" class="first">1</div><div id="s2">2</div><div id="s3">3</div><div id="s4">4</div>

How do I recalculate the section's height on scroll for a fixed navigation that changes class past certain anchors?

Just try adding all your size variables into your scroll event handler:

$(window).on('scroll', function() {
var afterhero = $('#hero-section').offset().top + $('#hero-section').height();
var afterwork = afterhero + $('#work-section').height();
var afterabout = afterwebsites + $('#about-section').height();
stop = Math.round($(window).scrollTop());
if (stop > afterabout) {
$('header').removeClass('teal');
$('header').addClass('white');
} else if (stop > afterwork) {
$('header').addClass('teal');
} else if (stop > afterhero) {
$('header').removeClass('teal');
$('header').addClass('white');
} else {
$('header').removeClass('teal');
$('header').removeClass('white');
}
});

Now afterhero, afterwork and afterabout should all be recalculated on a page scroll.



Related Topics



Leave a reply



Submit