jQuery: Animate container width after fixating to top of page depending on window scroll position

597 views Asked by At

Jeez, this is probably so ridiculous but I've been fiddling for several hours and can't seem to figure out how to do this.

Let's start with some CSS:

#wrapper {
    margin: 0 auto;
    padding: 0 20px;
    width: 960px;
}

#wrapper .block {
    width: 920px;
    height: 690px;
}

#wrapper .container {
    background-color: #000;
    width: 920px;
    height: 80px;
}

#wrapper .container div {
    margin: 20px auto 0;
    width: 510px;
    height: 35px;
}

Pretty simple. This container sits under a block, and nests another little container within it (which probably doesn't matter, but I included it just in case it's an omen), and it's all inside a big ol' page wrapper. So basically, after a certain point of scrolling down the page, I want .container to become fixated to the top of the page and expand to the width of the window. I also want .container to revert to its original state should said point be crossed again in the opposite direction.

I've accomplished the fixation with jQuery:

$(function() {
    $(window).scroll(function() {
        if ($(this).scrollTop() >= 690) $('.container').css({
            'position' : 'fixed',
            'top' : '0',
            'left' : '50%',
            'margin-left' : '-460px'
        });
        if ($(this).scrollTop() < 690) $('.container').removeAttr('style');
    });
});

For the life of me, though, I can't figure out how to expand and retract the width of .container with said logic, whilst keeping everything centered and without any "glitches" or delays. The effect, then, is that the width of the container expands from the center/ends of its original width to the width of the page after the scroll position on the page passes (or is at) 690px, and reverts back when the scroll position is before said value.

On a basic level, this is what I understand:

$(function() {
    $('window').scroll(function() {
        if ($(this).scrollTop() >= 690) $('.container').animate({'width' : '100%'});
        if ($(this).scrollTop() < 690) $('.container').animate({'width' : '920px'});
    });
});

My issue is that I can't seem to get these two concepts to work together seamlessly. I did think about possibly using some sort of hack by making an empty div that sits behind the container and becomes animated once those scroll position conditions are met, but I can't get something as seemingly simple as that to work either.

For convenience's sake, I also went ahead and made a quick visual representation of what I'm aiming for, in case I was faulty in my explanation:

Example of jQuery expansion/retraction effect with fixation conditions

Is there something I should edit/add/remove in my CSS or jQuery, or both? Should I consider saying to hell with it and try to accomplish the same effect with CSS3 transitions? Or would that make things more complicated? I'm going insane thinking that something that seems so simple could be so difficult, and I'll probably flip my lid if there turns out to be an incredibly simple solution that I overlooked, hahaha.

Any help/feedback/whatever would be greatly appreciated. Thanks!

Update

Some HTML:

<div id="wrapper">
    <div class="block">Some content</div>
    <div class="container">
        <div>A few navigation links</div>
    </div>
    <div class="main">Main content</div>
</div>

(P.S. - I know the semantics are rubbish, haha. This is purely experimental, though. Thanks.)

1

There are 1 answers

1
guest271314 On

Try adding () to .scrollTop() .

Note, Not entirely certain about expected results of css applied ?

$(function () {
    $(window).scroll(function () {
        if ($(this).scrollTop() >= 300) {
          $(".container")
           .stop(true)
           .css("position", "fixed")
            .animate({
              "top": "0",
              "left": "50%",
              "margin-left": "-460px"
          }, 100);
        };
        if ($(this).scrollTop() < 300) {
          $(".container").stop(true)
            .css({
              "position": "relative",
              "margin-left": "0px",
              "left": "0"
          });
        };
    });
});
#wrapper {
    background-color: #ddd;
    margin: 0 auto;
    padding: 0 20px;
    width: 960px;
}
#wrapper .block {
    background-color: #aaa;
    width: 920px;
    height: 300px;
    display: inline-block;
}
#wrapper .container {
    background-color: #000;
    width: 920px;
    height: 80px;
    display: inline-block;
}
#wrapper .container div {
    background-color: #444;
    margin: 20px auto 0;
    width: 510px;
    height: 35px;
    transition: all 100ms ease;
}
#wrapper .main {
    background-color: #eee;
    width: 920px;
    height: 700px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div id="wrapper">
    <div class="block">Some content</div>
    <div class="container">
        <div>A few navigation links</div>
    </div>
    <div class="main">Main content</div>
</div>

jsfiddle http://jsfiddle.net/eby5ygLy/2/