jQuery addClass in scroll

Asked

Viewed 700 times

2

I got the code down and I’m trying to get the elements li stay with the class active depending on the scroll (effect Parallax), everything works fine (click functions for scroll) except that. If you know some better way to do this share please.

HTML:

<div id="wrapper">

    <nav>
        <ul>
            <li>
                section1
            </li>
            <li>
                section2
            </li>
            <li>
                section3
            </li>
            <li>
                section4
            </li>
        </ul>
    </nav>

    <div id ="section1">
        <p>vccvfcwec</p>
    </div>

    <div id ="section2">
        <p>vccvfcwec</p>
    </div>

    <div id ="section3">
        <p>vccvfcwec</p>
    </div>

    <div id ="section4">
        <p>vccvfcwec</p>
    </div>

</div>

jQuery:

$('ul li:eq(0)').click(function() {
    $('html, body').animate({
        scrollTop: $("#section4").offset().top
    }, 1500);
});
$('ul li:eq(1)').click(function() {
    $('html, body').stop().animate({
        scrollTop: $("#section3").offset().top
    }, 1500);
});
$('ul li:eq(2)').click(function() {
    $('html, body').stop().animate({
        scrollTop: $("#section2").offset().top
    }, 1500);
});
$('ul li:eq(3)').click(function() {
    $('html, body').stop().animate({
        scrollTop: $("#section1").offset().top
    }, 1500);
});

var section1Height = $('#section1').height();
var section2Height = $('#section2').height();
var section3Height = $('#section3').height();
var section4Height = $('#section4').height();

$(window).scroll(function() {
    var winTop = $(window).scrollTop();

    if(winTop > section1Height && winTop <= section2Height){
        $('ul li:eq(0)').addClass('active').not().removeClass('active');
    }
    else if(winTop > section2Height && winTop <= section3Height){
        $('ul li:eq(1)').addClass('active').not().removeClass('active');
    } 
    else if(winTop > section3Height && winTop <= section4Height){
        $('ul li:eq(2)').addClass('active').not().removeClass('active');
    }
    else if(winTop > section4Height){
        $('ul li:eq(3)').addClass('active').not().removeClass('active');
    }
});

CSS:

    .active {
    color:#fff !important;
}

#wrapper {
    width: 100%;
    max-width: 1024px;
    margin: 0 auto;
}
#section1{
    width: 100%;
    height: 2000px;
    position: relative;
    background-color: yellow;
}
#section2 {
    width: 100%;
    position: relative;
    height: 2500px;
    background-color:red;
}
#section3{
    width: 100%;
    position: relative;
    height: 1500px;
    background-color: green;
}
#section4{
    width: 100%;
    position: relative;
    height: 1500px;
    background-color: blue;
}
nav ul {
    border: 1px solid;
    margin: 0;
    background-color: #222;
    height: 80px;
    margin: 0 0 90px;
    width: 100%;
    max-width: 1024px;
    position: fixed;
    z-index: 1;
}
nav ul li {
    list-style: none;
    margin: 30px 20px 30px 20px;
    display: inline;
    cursor: pointer;
    float: right;
}
nav ul li {
    color: #B5B5B5;
    text-decoration: none;
}

1 answer

1


If I understand your problem well, each section should have its text in yellow when the scroll arrives, that is when that section is +/- in the middle of the screen. Here’s an example that works on jsFiddle but has to be adapted to your incomplete code here in the question.

My idea is:

  • cache all sections whose ID starts with "Section" and who are descendants of #wrapper
  • go through this choice and save several objects with their height and a reference to the object itself.
  • within the for go through all the elements. The first one you have posicao greater than the wintop makes the cycle stop and fetch the corresponding li to give it a class

Code

function animarScroll(altura) {
    $('html, body').stop().animate({
        scrollTop: altura
    }, 1500);
}

var ecra = $(document).height();
var seccoes = $('#wrapper div[id^=section]');
var lis = document.querySelectorAll('#wrapper li');
var alturas = seccoes.map(function (i) {
    return {
        elemento: lis[i],
        posicao: $(this).position().top + $(this).outerHeight(true)
    }
});

$('ul li').each(function (i, el) {

    $(el).click(function () {
        var posicaoSeccao = alturas[alturas.length - i].posicao;
        animarScroll(posicaoSeccao)
    });
});

$(window).scroll(function () {
    var winTop = $(window).scrollTop();
    for (var i = 0; i < alturas.length; i++) {
        var este = alturas[i];
        if (este.posicao > winTop) {
            $(lis).removeClass('active');
            $(alturas[i].elemento).addClass('active');
            break;
        }
    }
});

Example

  • @Miguel, you can put your entire CSS, or the content of div? As it is (all empty) nor need scroll...

  • First of all, thank you @Rgio. I implemented the code the way you wrote it, is it supposed to modify something to implement in my code? is not working and I think it is because of the selector "$('#wrapper div[id =Section]')" because it is thus putting the tags 'p' with the class 'active' instead of the 'li' corresponding to the section we are in. Blame yourself for the inconvenience, but you could help me here sff. CSS is up

  • Sorry @Sergio but what is getting the class 'active' even in your example is what is inside the tag 'p' (text) and not the corresponding 'li', what I wanted is that the element 'li' corresponding to the section where we are was with the class

  • Exactly @

  • Muito Obrogado @Sergio, that’s right

  • sorry, I noticed now that it is 'active' too soon, ex: section 2 is 'active' still in section 1 (section amerela), just walk a little with scroll that the class is assigned to section 2, when it should be in section 1.

  • Perfect, Obgado

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.