1

I am currently creating a personal website and I want a full height header when the website is loaded. This header should animate its height when the user scrolls down and the content below the header should move synchronously to the animation of the header. And the header should be fixed positioned at the end. I got everything working, beside the fixed position. It is flickering when the animation is finished.

I created a fiddle, so you will understand what I mean more easy.

http://jsfiddle.net/30j5njrw/10/`

Thanks in advance for any help

Regards

Edit: I tried several things so far, like adding position fixed from the beginning to the header, or trying to position the header content via jQuery on scroll...but I never got the result I wish.

Edit2: If someone knows a site with a similar effect, please share it.

Edit3: Since no one got my problem so far, i will try to describe it more detailed.

I have a header and a content area. The header is set to full height of the viewport when the page loads. The header uses static css positioning at this point, so the content area is correctly positioned below the header outside of the viewport.

If I scroll down, the header shrinks and some css of the header content is animated. The content area now must move up with the arrow under the header and the header should be fixed when the animation is finished.

All your examples so far just don't care about the flow of the content below the header.

Edit4:

haxxxton answered the question and the solution looks even better than I actually wanted it. So I will reward him with the bounty when the 24 hours are over.

Edit5

Actually haxxxtons answer didn't fix my problem. I was so amazed that I have overseen some problems. The arrow must be part of the content section, since there will be more content sections below on the final site. I came up with another solution, but I got stuck either. Now I don't think that this is even possible to do. Here is an updated version of my fiddle:

http://jsfiddle.net/30j5njrw/14/

The arrow is still not moving properly since I can't do preventDefault() on the scroll event. I need to do preventDefault() during the scroll event when the height of the header is not 165px. According to different sources found on google, it is not possible to do preventDefault() on the scroll event. I might try now to play with padding of content area during the scroll event to make it look like it's not scrolling. But I don't think that the effect i want is actually possible.

Edit6:

It works to set the padding of the content area to the pixels of the scroll offset. See new fiddle:

Fiddle update

But there is still a problem. When you scroll really fast it is flickering somehow and positioning of the footer is strange. But I don't know if you can scroll that fast with any other input device than the magic touchpads of MacBooks so I might ignore this problem, if I don't finde a solution in a few hours.

Abenil
  • 1,048
  • 3
  • 12
  • 26

2 Answers2

4

This is because when the user scrolls down at the first instance (to trigger your animation) you are letting them continue scrolling, and then applying the position:fixed; to your header.. which is making it 'jump' down the page.

The solution, is actually something you have tried already; to start with the header already position:fixed, and then animate from there.

By applying fixed to the header to begin with, the other elements wont appear to 'snap' later.

I found that adding the 'arrow' element into the header stops the noticeable snapping (and i assume you intended this to be there all the time).

JSFIDDLE DEMO


CSS

body {
    text-align: center;
}
.clear {
    clear: both;
}
h1 {
    margin-top: 4px;
}
h1 p {
    font-size: 18px;
    margin: 5px 0 10px 0;
}
h2 {
    margin-bottom: 50px;
}
h1, h2, h3, h4 {
    text-align: center;
}
.white, .white * {
    background-color: #ffffff;
    border-color: #2d2d2d;
    color: #2d2d2d;
}
.dark, .dark * {
    background-color: #2d2d2d;
    border-color: #ffffff;
    color: #ffffff;
}
#top {
    top: 0;
    text-align: center;
    width: 100%;
    position:fixed;
    overflow: visible !important;
    z-index: 1000;
}
#top .arrow{
    border-left: 30px solid transparent;
    border-right: 30px solid transparent;
    border-top-width: 20px;
    border-top-style: solid;
    border-top-color:white;
    height: 20px;
    margin: 0 0 0 -30px;
    width: 60px;
    position:absolute;
    top:100%;
    left:50%;
    background-color:transparent;
}
#top p.slogan {
    font-family:'Poiret One', cursive;
    margin-top: 50px;
    font-size: 20px;
}
#top a {
    display: block;
    font-family:'Poiret One', cursive;
    font-size: 20px;
    text-align: center;
    width: 117px;
}
#top a:hover {
    color: #767676;
    text-decoration: none;
}
#top nav {
    float: right;
    left: -50%;
    margin-top: 35px;
    position: relative;
    text-align: left;
}
#top ul {
    left: 50%;
    margin: 0 auto;
    padding: 0;
    position: relative;
}
#top li {
    float: left;
    margin: 0 5px;
    position: relative;
    width: 100px;
}
#contact {
    padding-top:215px;
    height: 1300px;
}

JS

$( document ).ready(function() {
    changeHeaderHeight();
    var lastScrollTop = 0;
    var isAnimationFinished = true;
    var isScrolled = $(window).scroll(function() {
        var scrollTop = $(this).scrollTop();
        if (isAnimationFinished == true) {
            isAnimationFinished = false;
            topHeight = $('#top').height() - scrollTop;
            $('#top h1').animate({
                fontSize: '14px'
            },500);
            $('#top h1 p').fadeOut();
            $('#top p.slogan').fadeOut();
            $('#top').animate({
                height: 165 + 'px'
            },1000);
            $('#main-navigation').animate({
                marginTop: 5 + 'px',
            },1000);
            $('#main-navigation a').animate({
                width: '97px',
                fontSize: '16px',
            },1000);
            $('#main-navigation li').animate({
                width: '97px'
            },1000);
        }
        lastScrollTop = scrollTop;
    });
    $.when(isScrolled).then(function() {
        if ($('#top').height() == 165) {
            isAnimationFinished = true;

        }
    });



});
$(window).resize(function() {
    changeHeaderHeight();
});
function changeHeaderHeight() {
    var viewportHeight = $(window).height();
    $('header#top').height(viewportHeight);
}

HTML

<body data-spy="scroll" data-target="#main-navigation">
  <header id="top" class="white">
    <h1>
      Title
      <p>
        ...slogan goes here
      </p>
    </h1>
    <nav id="main-navigation">
      <ul data-spy="affix" data-offset-top="155" class="nav">
        <li>
          <a href="#news" title="News">
            News
          </a>
        </li>
        <li>
          <a href="#agency" title="Agentur">
            Agentur
          </a>
        </li>
        <li>
          <a href="#services" title="Leistungen">
            Leistungen
          </a>
        </li>
        <li>
          <a href="#portfolio" title="News">
            Portfolio
          </a>
        </li>
        <li>
          <a href="#contact" title="News">
            Kontakt
          </a>
        </li>
      </ul>
    </nav>
    <div class="clear"></div>
    <p class="slogan">
      Blabla
    </p>
    <p class="slogan">
      More Blabla
    </p>
    <div class="arrow">
    </div>
  </header>
  <section id="contact" class="dark">
    <header>
      <h2>
        Contact
      </h2>
    </header>
  </section>
  <footer class="white">
    <a class="scroll-top" href="#top">
      Logo
    </a>
  </footer>
</body>
haxxxton
  • 6,422
  • 3
  • 27
  • 57
  • While I was writing my third edit, another idea came to my mind, which appeared satisfying when I just tried it. I just animated the margin-top of the content below and added position fixed from the beginning. But your solution looks smoother. Thanks for your awesome help. You will get the bounty in 23 hours. – Abenil Sep 15 '14 at 01:52
  • Sorry I was so amazed that I have overseen some problems with your solution. The arrow should not be part of the header, since there will be more content areas below the on in the example and those contain an arrow either. So it is still not fixing my problem...more about that in my fifth edit. – Abenil Sep 15 '14 at 02:35
  • @Abenil so the intention is that when the person scrolls.. the arrow and content scroll up with the header.. and then allow the user to scroll? or you want to allow the user to be able to scroll down regardless of current header animation position? in terms of design.. is there a reason you dont want the arrows as part of the header? you can still align it so that when you click your menu items that the page scrolls to and aligns the arrow with the title of the section title – haxxxton Sep 15 '14 at 04:32
  • 1
    I want to block scrolling till the header is shrunken, after that the user can scroll the content areas. Those areas are zebra style, means area a is black, area b is white and c is black again. Every area has an arrow on top, this why I don't want it to be in the header. I got it working in my last fiddle. Since you were the only one addressing my problem I rewared you the bounty and accepted your answer. – Abenil Sep 17 '14 at 03:22
0

Here is another stack overflow question that asks something similar: jQuery - Sticky header that shrinks when scrolling down

The accepted answer has this code:

$(function(){
  $('#header_nav').data('size','big');
});

$(window).scroll(function(){
  if($(document).scrollTop() > 0)
{
    if($('#header_nav').data('size') == 'big')
    {
        $('#header_nav').data('size','small');
        $('#header_nav').stop().animate({
            height:'40px'
        },600);
    }
}
else
  {
    if($('#header_nav').data('size') == 'small')
      {
        $('#header_nav').data('size','big');
        $('#header_nav').stop().animate({
            height:'100px'
        },600);
      }  
  }
});

With this JS Fiddle example. http://jsfiddle.net/jezzipin/JJ8Jc/

Community
  • 1
  • 1
nahtnam
  • 2,659
  • 1
  • 18
  • 31
  • this is something different, since the header is not full height on page load. I found all those solutions too, but these do not apply to the problem. – Abenil Sep 15 '14 at 01:05
  • This is not a good answer. You added nothing to the refered post... if you think that the question had been already answered, you should flag as duplicate or posted as comment. – LcSalazar Sep 15 '14 at 14:37