Hacker News new | past | comments | ask | show | jobs | submit login
Headroom.js – hide your header on scroll (nillia.ms)
250 points by WickyNilliams on May 27, 2014 | hide | past | favorite | 93 comments

FYI, this UI pattern is called "Quick Return": http://www.androiduipatterns.com/2012/08/an-emerging-ui-patt...

I had been looking for this pattern's name after having seen Chrome on Android implementing it for their navbar. I find it useful on mobile where scrolling a long distance can be laborious.

I guess "quick return" is a remedy for "infinite scroll" making you lose top and bottom navigational elements, too.

I liked the ExtJS4 implementation most.

They kept the data in a div with hidden overflow so you could alway see header and footer (not that useful for mobile).

But they also deleted old nodes when they were far enough away from the visible space in the div.

Cool - do you (or anyone) have a favorite reference or catalog of UI patterns?

I've seen it being referred to as "scroll up bar".

Just get rid of the damn headers. Users don't want them. They are just misguided ways of trying to raise retention, but really what they do is make your site less pleasant to use, which then makes me not want to come back later.

Just get rid of the damn headers. Users don't want them.

Are there any stats that prove this? I see this repeated time and time again on HN but I'm yet to see evidence that (a meaningfully significant number of) users are turned off by headers like this, while I have seen evidence that it increases engagement rates. It's used in both Chrome on Android and Safari on iOS, so I don't think it's an alien concept at this point.

> Are there any stats that prove this?


You're basically looking at picture #3 from the left: http://i0.wp.com/www.stephenblower.co.uk/wp-content/uploads/...

Do you need "stats" to prove the absurdity of headers that disappear when you scroll?

Seeing as how they're a common (and, IMO, very pleasant) user interface idiom on mobile, I think it's very reasonable question to ask regarding the web.

You made a claim about "users". Data to support it would be nice.

I absolutely loathe fixed headers, but I think this script is pretty cool. The headers stay out of your way when you are reading, and when you actually want to use the navigation you don't have to scroll all the way to the top. I really see no downside, except "more JavaScript." (People who are complaining about JavaScript: you really aren't going to like the Web in 5 years)

Downside: more javascript (another file to load, to break, to parse, to wait on, etc)

Downside: unusual behaviour. Users fully understand how to scroll to the top of a page to find the header. This hack already requires them to scroll up to get to the header. Also, there's a decent chance that if you're trying to find the header that you're going to leave the page, so it doesn't matter if you lose your spot.

It's a cutesy feature, but it's cumbersome and pointless, and doesn't add any real usability (unless you count getting rid of fixed headers, which also don't add any real usability).

I don't like the web now... grumps

There are two kind of significant problems with headers that hide as you scroll, in my experience. 1) You can't easily get to the navigation when you do need it—have to scroll up some uncertain amount that varies by site (this unknown makes simply using scrollbars more reliable)—and 2) you get it when you don't need it, as in you're simply scrolling back to reread a portion of the text above.

In short, this element feels always somewhat out of user's control.

Much more usable on mobile would be putting such navigation in a kind of sidebar that many apps already employ (often accessible by swiping from the left edge of the screen), while on desktop a great solution is simple “top” links, strategically placed.

Plain fixed headers, possibly somewhat collapsing in height as you scroll, also seem better than vanishing headers from the point of control.

Unless there comes out some positive research on usability of this particular UI element, I personally am not convinced.

    > Plain fixed headers, possibly somewhat collapsing in height as you scroll, also seem better than vanishing headers from the point of control.
That's doable with this library btw. What happens in response to scrolling is entirely dependent on your CSS. So when scrolling down, have it apply a class which reduces the height, and when scrolling up, restore the height.

Also, it's worth noting, that whilst the obvious use-case for the lib is headers; it can be used on any element, to have it react to scroll direction and distance. For instance, I've used it to make a sidebar fixed after scrolling past a certain point on the page (classic sticky sidebar pattern). Also, I've used it to only show a "back to top" link when a user is > 50% down the page and scrolling up quickly - so unless you're deep in a page and scrolling towards the top, the link will never be visible/distracting.

It works well for these scenarios too!

Actually, it's not as bad as the headline implies. Header stays hidden once it disappears, giving you the entire screen to read, but if you scroll up a bit it appears again, so you can use it to navigate. It acts the same as iOS Safari header - once you get used to it, it's really nice.

Except that Safari uses it to hide important browser chrome. Websites use it to hide headers that really don't need to be there in the first place.

A completely static site also has this property. When I scroll to the top, I can see the top. When I scroll away from the top, I cannot see the top.

I've just stated a tautology, so I'm missing something.

EDIT I'm seriously wondering whether this whole thing is a joke I'm not getting. Is there a jQuery plug-in that lets me click on text to go to other pages, too?

The easiest way to think of it is a halfway house between fixed and static. You get the benefits of static (maximising vertical screen space) while keeping the benefits of a fixed header (primary navigation always close to hand).

Edit: it's not a joke, it's an established pattern found on both iOS and Android.

Slightly interesting backstory with android: this effect was originally added to the stock browser on android 3.0. I loved how the tiny enhancement gave me more screen real estate, so I decided to build a JS lib to emulate the effect. The pattern didn't make it into the original chrome for Android, but after I mentioned it to Paul Irish he made it happen there too :)

> When I scroll to the top, I can see the top.

Instead, when you begin to scroll to the top you can see the top. If you have an iphone, it's navbar behavior is identical to this.


on the iPhone you can just double tap the top of the screen to scroll to the top quickly.

And when I want to resume reading? What then?

Let's not be obtuse, yeah?

What then? You tap the bottom of the screen to bring up the chrome instead.

There's no snapback to where you were reading if you double-tap the top. Which sucks and makes for a bad UX if you only need the top bar for a moment (for a share button, for example).

I said tap the _bottom_ of the screen, not the top.

And I'm pretty sure you lost the plot, because this thread is about the header library in the OP, not the browser chrome. Your suggestion to double-tap to the top (with a menu that doesn't follow you) means I lose my place. And so it's not a good suggestion.

The context of this sub-thread is

    on the iPhone you can just double tap the top of the screen to scroll to the top quickly.
Which is all about browser chrome.

Dude. The iPhone was a comparison, not a concrete part of the discussion. Did you, like, read the posts before it in this subthread that are whining about how this thing is useless because you can "just" scroll to the top of the page to see the menu bar on the page? And, now, how tapping to the top isn't a good solution? There are enough upvotes on my posts here that I don't think this is that unclear.

I'm glad I'm not the only one; when I saw the headline I thought "this fix wouldn't be necessary if people just used static pages in the first place."

I've seen headers that stay on-screen while scrolling; even on huge displays they annoy me, so kudos to the author for the effort and putting it out there, but I can't help but feel like he just hit a windmill full tilt.

Edited to reduce inflammation.

The point is that you should not have to scroll all the way to the top to see the header. Tools like headroom.js add predictive behavior to your site to improve user experience. I personally really appreciate sites that have it.

that's assuming I want to do navigation just because I started to scrollup, which is a flawed assumption.

This. Moreover, is adding even more JavaScript really necessary? How about just make things simple, fast, and easy to read? As an user I'll always choose speed and good typography over clever transitions and smart menus.

serious question: do you use the web much with on your phone?

There's no "Home" key on your phone that instantly takes you to the top of the page. Scrolling and scrolling and scrolling is annoying.

The main critique I have for the OP is that is that it should be responsive -- and only work on tablets and mobile

> There's no "Home" key on your phone that instantly takes you to the top of the page.

There is, at least on iOS. You can tap the status bar and it will quickly jump to the top of the page.

> There's no "Home" key on your phone that instantly takes you to the top of the page

On iOS: tap on the system menu at the very top of the screen.

> The main critique I have for the OP is that is that it should be responsive -- and only work on tablets and mobile

All it does is add and remove classes. It can be as responsive or unresponsive as you like with @media rules.

precisely! or you can use matchMedia (or my lib enquire.js [0]) to selectively enable/disable the entire feature. This might be preferable than @media in your CSS, because it does away with scroll listeners where they're not needed.

[0] http://wicky.nillia.ms/enquire.js/

just curious, are saying you let them scroll out of view, or get rid of them altogether? if the latter, what type of site navigation is better?

Whoa! I'm very excited to be reading the text of the person put in charge of the universe! I'm getting chills just thinking that you might actually read this humble message.

He's not wrong.

I want them.

From the tagline, I thought this was a joke.. since "hide your header on scroll" implies default browser behaviour (i.e. position:static)

Great job! How about adding an option of showing the header when the users moves the cursor to the top of the window? Just like http://lyst.com are doing it.

Ah, thanks for pointing us there. That's pretty slick

I've previously submitted this link, but given the interest in the pattern with yesterday's article [0] I thought it appropriate to post again. Hopefully someone finds it useful. Happy to answer any and all questions

[0] https://news.ycombinator.com/item?id=7799687

Thanks for posting it...I think we've reached a point where there are so many good libraries on Github that even a 1,000+ star repo may be unknown to many of the people who would find it useful. This is something I would've tried to build on my own...but after seeing a repo with not only 3,000+ stars, which is more than the number of the library's bytes (in development), but also fewer than 5 open issues out of 60+...I'm happy to just use your solution. Nice work!

I agree. I am continually finding repos on github that are massively popular, yet I've never come across them.

Does anyone know any sites which are devoted to curating high-quality repos on github/elsewhere¹? Obviously high quality is a subjective metric, but some mix of popularity, file size, whether under active development, number of issues etc. should suffice. GitHub's explore feature is too time-sensitive to use for this purpose.

¹ I know there's unheap.com, but that's focussed specifically on jQuery plugins. I'm thinking something broader, any language, different parts of the stack etc

It's pretty nice. In my ipad the header only shows/hides if I scroll up/down AND stop touching the screen. Maybe that needs to be changed.

Unfortunately, this is a limitation of the scroll event on iOS. It does not given intermediate results - like it's debounced - only firing the scroll event when scrolling has stopped. This is a well-documented shortcoming of iOS. As Apple puts it [0], "One-finger panning doesn’t generate any events until the user stops panning—an onscroll event is generated when the page stops moving". There is no workaround at the moment.

[0] https://developer.apple.com/library/safari/documentation/app...

wiresurfer, don't understand why you were down voted into oblivion, but now I can't reply to you. Anyway, massive thanks for that, really helpful starting point

Till the time its seen by the right pair of eyes :) Will try and see if I can fork a version and add the "inferred " touchend hack to it. Have a good day.

while reading the source for implementation, as a non-primary JS developer, I can't help but think that the actual functionality could be implemented in around 10 lines of code if we remove all js oo-ization and customization code.. actually I need the minimum lines of code to implement this inside to paste in my project.. any help would be appreciated..

It started out a lot smaller! But as with most code, it starts out nice and pretty but get disfigured over time as corner cases and bugs are unearthed. There is also some necessary ceremony when dealing with scroll events to ensure good perf, otherwise you end up with stuttery scrolling which will annoy users to no end.

However, my plan has always been to trim the fat for the next release. I won't drop any features, but I'll definitely drop bytes! Feel free to fork and strip out any code you don't need though

I haven't tried it out, but this is how you make it work with bootstrap 3


Thankyou so much for that.

I had got as far as including animate.css in trying to get things working and I was just about to write here about how it didn't bl00%y work!!! All is working now, thanks for your well-spotted tip.

When I scroll away from the top of the page it makes the header disappear, then reappear when I scroll back up to the top of the page.

Isn't that what scrolling does? :)

This is what scrolling does. But this option is fancier and IMHO pointlessly visually distracting.

I really enjoy this feature because it gives users who read long posts (especially on mobile) quick access to the navigation bar when they need it, but without the screen-hogging characteristic of older position:absolute nav-bars. With regards to the visual distraction, I find that I almost never scroll up unless I'm done reading. Continuously scrolling down feels natural, and in this case, the header will stay hidden regardless.

Kind of odd that if you scroll slowly the header never disappears.

That's intentional actually :) The library allows you to supply a tolerance value, to reduce sensitivity of the effect. On the project site, I have it set to 5px (i.e. you must scroll > 5px for the effect to trigger). You can try out the various options in the interactive playground [0]

[0] http://wicky.nillia.ms/headroom.js/playroom/

See http://ux.stackexchange.com/questions/57990/how-usable-are-b... for more.

> I admit, it's quite genius. And I bet that if Apple could, they would have patented it.

I really, really like this behavior on mobile, especially on sites that dynamically load new content as I scroll down. I honestly don't understand the harsh criticism I'm seeing in the comments here, because this really is a super functional way of giving the user easy access to navigation controls without having to scroll all the way to the top of a page. That said, I suppose I can understand criticism if this were being used in cases where there generally wasn't a lot of content to scroll through. I guess my point is, like all design decisions, it completely depends on the use case as to whether or not this is useful or functional.

Great, so having previously suffered a rash of sites that permanently took up valuable vertical screen space with fixed headers, they now will all have headers that disappear whenever you scroll down and appear when you scroll up, with slightly buggy behavior on iOS. Has anyone considered what non-technical users will think of this UX idiom?

The effect is exacerbated on mobile devices whose browser chrome follows this very same idiom (for arguably better reasons - at least it's not buggy). So you now have two "competing" user interface effects.

Whether or not you are a fan of disappearing/reappearing headers, this is clearly a well-thought-out bit of code that will be useful to someone. The docs also appear clear and concise.

I like that it is not a jQuery plugin by default, but does provide the option. Even better (for me) is an Angular directive ready for immediate integration.

Well done and keep up the good work!

This is my preferred way of developing JS stuff. Build an object that you can use in pure JS, then integrations with other frameworks are nothing more than simple wrappers around that object. Check the code for the jQuery plugin [0], it's tiny!

By the way, I'm not an angular user, the directive was added through a PR. If you hit any problems or have any suggestions to improve it, please get in touch on github!

[0] https://github.com/WickyNilliams/headroom.js/blob/master/src...

What's the point of this?

To only engage the header when you're scrolling up? Identical to the way Safari on iOS handles it.

And this is good because?

I don't get the point of this, you get pretty much the same thing by doing nothing. Fix the menu to the top of the page, when you scroll down it goes away, scroll back up and there it is. Almost no one is going to care that they'll need to scroll back to the top, I'm sure of it.

Because apparently we've run out of hard problems to solve in computing (as demonstrated by the amount of useless stuff we create) and need to think of the next UX trend that will give our users 0.0001% more satisfaction and increase productivity by 0.000009%.

</rant mode="full">

Once upon a time, there was a town that had a severe rat problem. They imported a large number of cats, and soon the rats were gone.

Now the town had a cat problem. They imported a large number of dogs, and soon the rats were gone. But now they had a dog problem.

The town imported a large number of lions...

It would be nice to have it where after scrolling up it can disappear after a certain amount of time. Very useful for scrolling back up to re-read something, versus scrolling up for navigational elements.

Facebook should implement something like this for their mobile site. When I have scrolled too deep into the newsfeed, I find that refreshing the page is a better option than trying to scroll back up.

I really like this but I wish the documentation included recommended DOM structure / css styles... it's not as plug and play as the docs suggest

I don't like fixed headers at all and I dislike even more fixed headers that hide on scroll... it's too distracting and useless.

A couple of years ago, when fixed headers became "cool", I'd write scripts for Greasemonkey just to get rid of them. Today I'm too lazy for that :D.

But nice project.

Didn't work in iOS Chrome or Safari (the header remains fixed at the top regardless of scroll behavior).

Cool effect for desktop but if you can get it working as a responsive solution I think it would be a lot more useful to people!

See my other response (https://news.ycombinator.com/item?id=7805748). This is a shortcoming of iOS, it works perfectly on other platforms.

IIRC, you reduce the tolerance value (an options you can pass to headroom) it will work on iOS also, it just isn't quite as sensitive as it should be. I'm waiting for my development iPhone to charge so I can confirm this. I'll report back :)

Ah. I'm not super familiar with that "bug" - is it that "touchmove" events don't get fired for single-finger scrolling (panning)?

Perhaps you could make it work (albeit less gracefully) in iOS by reconciling the header visibility state once "touchend" finally gets fired though? Assuming "touchstart" gets fired as you'd expect, you can do a bit of manual calculation to determine if the y-position changed enough to warrant header hide/show.

To be honest, when i first developed the library I didn't have an iOS device I could test with, so just went with the simplest solution (that is, not do anything :D). Also, I'd always kind of viewed it as a progressive enhancement - if it doesn't work, it's still a fully functional header.

However, now that I have an iOS device (which is still charging!), I should spend some time seeing if I can get it to work better there. I'll look at various touch events as you suggest. Currently it only listens to the scroll event

Doesn't work for me on Android 4.2.

Edit: version 4.2 Android Browser. I scrolled a good enough distance down the page.

Maybe you need a polyfill or something? Those Android browsers are the new IE.

Correct, a number of polyfills are needed for older browsers - requestAnimationFrame, Function.prototype.bind and classList. This is detailed in the "browser support" section of the website

Just tested on iPhone and I can happily report that reducing the tolerance improves the situation. Though it still worked with a 5px tolerance. Also, note that there is an offset applied on the documentation, so the effect never kicks in until you've scrolled down > 200px

Completely hiding the main navigation bar - is this a UX problem?. Now I have to scroll back again to top just for seeing the navigation bar.

Minor tweak will be to allow swiping from top to show it or when user moves mouse to top.

Did you even try it? The header reappears when you start scrolling up - no need to scroll back to the top.

Disa-pp-pp-pp-ointed by the lack of Max Headroom references on the linked site.

Didn't test it as much in other browsers, but seemed to be buggy w/ Safari 7.0.1 on OS X - wasn't seeing the header appear again while scrolling up.

Here is an example with bootstrap 3 http://firestartr.co/

I hate the design of disappearing headers.

This is why I love open source. Amazing job, congratulations.

Why an entire js dependency for what can be accomplished with 10 lines of jquery?

Any example of that?

Isn't jQuery a huge dependency?

Sure, but it provides more features than headroom.js.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact