Hacker News new | past | comments | ask | show | jobs | submit login
H2 {position: sticky} [video] (air.mozilla.org)
242 points by izietto on Sept 12, 2013 | hide | past | web | favorite | 88 comments

Sticky table headers and columns: yes, yes, yes. That is very important for usability, and currently hard to do properly. If I could just add a layout attribute to a THEAD or COLGROUP, my life would be significantly easier.

We've spent a lot of time implementing this ourselves for a data table containing lab analysis values. It's a big requirement from our customers. You can imagine it's pretty important to be able to match rows and columns (sample types and dates) correctly when you're looking at these values.

The planning meeting about this was pretty funny.

Boss: "So, we'll just make the headers fixed, should be easy, right?"

Developer: "Heh-heh... Yeah, we could probably get that working decently in just a couple of weeks. We'll have to test it in all the browsers, of course, and do performance tests with big data sets. It's possible that we might not be able to get it to work well enough on all platforms, so we should have a backup plan."

Boss: "Sigh. This would be so much easier in Visual Basic..."

The boss is right though. This (and a lot of other things) is much easier in almost every other GUI lib I worked with. Some things like documents (flowing text with images etc) are easier in HTML, but that is what it was made for.

It's a little sad how basic presentation of tabular data is so tricky. That should be an essential part of a document-oriented technology. I guess a good solution would be a little too complex.

I've never understood why the text/csv mime-type is not recognised by browsers: you should be able to embed a CSV into a HTML page using the <object> elements, much like an image. Then the browser could handle things like fixed headers etc.

It's not too hard to embed it yourself; here's a quick proposal I did when the idea of embedding CSV in a custom element was being discussed on the WHATWG list: http://ephemera.continuation.org/csv.html

The issue of fixed headers is a styling issue, not an issue of what embedding types are supported; and that is solved by the "position: sticky" CSS attribute that this link discusses. There has been an experimental WebKit implementation of this for a while, this now adds an experimental Gecko implementation. Hopefully this will be standardized soon and available in non-experimental form.

The thing is though. That really the semantic markup is already there in the table. So I don't see why the browser in this case can't just help you out a little. You could click the table, and the whole thing pop out in a 'table viewer'. Or the browser could use a tool tip, and ghost the headers on scroll or something.

If I want a fixed header on a table. Couldn't I just fix the body height on the tbody, and use an overflow: scroll, to achieve the same effect? or am I missing something?

Forgive me as I'm still unsure as to what position:sticky actually means. Is it to keep the headings on screen?

Setting an absolute position on the THEAD works (except, I think, in old IE), but only with fixed column widths. The usual hack involves using JavaScript to keep the columns in sync.

The header cells end up being layouted separately from the body cells, and so their widths are not constrained together.

Actually, I'm not sure if sticky positioning is different in this regard... This property might not solve the problem we ran into.

In any case, a sticky header is different from an absolute header, because it doesn't require a separate scrolling container. You just scroll the page, and the header follows along, until the table scrolls out of the viewport.

Would make a nifty niche browser extension I imagine.

I'm wondering if, from UX perspective, in most cases it would be sufficient to draw the headers based on the mouse position. If the user hovers the mouse over a row in the able that causes the headers to pop-over one (or more) rows above the mouse position in a tool-tip like fashion (correctly aligned with the columns, of course).

That won't work so well on a tablet

Hmm, perhaps in some applications. In my example, it's nice to be able to scroll down to the interval of interest, and then just sit back and look at the data, not having to make sure the mouse cursor is in the right place.

This type of broken experience compared with what is possible in native applications is what makes me always take native projects over web ones, when given the choice.

It's not a broken experience.

It's attempting to make something perform in a way it was not designed, nor intended, for. Just because a Honda Civic can't compete in an F1 race doesn't mean the Civic is broken.

It's a table, for the intent of displaying tabular data. Headers are an essential component of reading a table. If the headers do not remain visible after scrolling down, the table is not displaying useful information.

It is a broken experience, and a defect in the HTML concept of a "table".

Honestly, we have to stop defending these terrible web technologies we're saddled with. We use them because they're the only universal-standard client application engine.

Not because they're good.

I don't think they're all that bad either... I mean if you're using IE then sure you can say they are terrible. But in the other browsers - they're actually pretty good. There is room for improvement - but for what we get it's pretty incredible. And you can implement headers that follow you in a table - it just requires writing some code, which you can say is bad.. but then if you go off and write in a native application I"m sure you'll be writing a lot more code than I will in my web app... the issues usually boil down to the client e.g. IE or the lack of native extensions in WebCore preventing the web app from performing better... yeah.. that's my two cents...

So, an always visible table header is a requirement for correct viewing of tabular data. That means every book ever printed, or long pages for that matter, that had tabular data presents a broken experience.

I would think that people who relied on books before computers came along would disagree.

HTML provides for a means to view tabular data and performs that function in a minimal and acceptable manner. People moving the goal posts on the requirements does not mean the current implementation is "broken" nor "defective". It simply does not perform an extra feature that people would like to have today.

I also don't believe I was defending anything, I was simply disagreeing with an unfair criticism against a technology because it wouldn't do what it wasn't designed to do based on current expectations.

The simple fact that HTML/CSS/Javascript allows for it to be extended and expanded shows it is not a defective means of displaying information. It means that there's the occasional lag in updating the specs to meet people's current expectations. Blame the people not keeping the spec up to date with current expectations and not the spec.

Once position:sticky is in common use I suppose we'll wait until the next new expectation of functionality appears that means something is "broken".

HTML/CSS/Javascript is good in many ways, but I agree it is not perfect and it never will be.

If I were reading a book where I could look at tabular data split across multiple pages and not see the headers at the top of each page, I would throw it out. When looking at multiple screen-fulls of tabular data, the expectation remains.

I was making applications in VB5 in the late '90s that solved this problem. Expecting it 15ish years later in a platform that includes tabular data as a core feature is not unreasonable.

HTML+CSS+Javascript is a poor general-purpose application development platform and an okay document engine. It is only made usable by the herculean combined effort of the entire 21st century software industry.

I knew someone would toss out the multiple pages with tables example. In terms of HTML that's called multiple tables. I agree that it's not efficient.

Nor did I say that such a feature was unreasonable, I'm just saying that people are complaining about a lack of feature that wasn't built in before the expectations of that feature. People want it and there have been people seriously attempting to implement a solution. But that kind of thing takes time and the problem is it isn't happening in a time table that makes enough people happy. So they complain and toss out unfair criticisms.

Your last bit proves my point, people are attempting to use these technologies in ways they were not designed to do and yet complain about them not being able to do it. You might as well hate your car because it doesn't fly.

Well, native apps are pretty much always better than html5 apps. The only main reason to make html5 apps is to reduce developing costs by a significant amount. I don't think anyone disagrees with that.

> I don't think anyone disagrees with that.

Actually I think most in HN disagree with that. In HN taking the native side is a sure way to get downvotes.

This will be really awesome. For anyone who hasn't tried to implement a Sticky element before, it's actually not as trivial as you might think. (And when I was looking for an existing implementation, they didn't support the "constrain" effect that is explained in the video.

To do it correctly, you need to track the up to 4 different element positions.

You've got your actual sticky element, then you've got the parent of the element to ensure it's within the view port. Then you've got the scroll container as well. Plus, you might have a constrain/target node, to ensure that the sticky element doesn't extend passed an artificial bounding box.

Overall, doing all of these domGeometry/position calculations on each window.onscroll event leads to extremely inefficient JS. I ended up removing the Sticky altogether because on iOS it would basically make my application unusable.

Here was my implementation[1]. It was considerably harder to created than I expected it would be... coding advice/tips welcome.

[1] : https://gist.github.com/Kalyse/6534936 (My personal Sticky implementation using Dojo).

My two cents. You'll never be able to match the scroll smoothly listening for scroll events. Use requestAnimationFrame and listen for changes in window.scrollTop.

Listen for changes? Or poll for changes?

Wouldn't your way consume a lot of unnecessary CPU?

Not exactly poll. Use scroll events to start your polling; after the second time your loop function doesn't find a change in the scrollTop, stop requesting frames.

Even without this guard, with just the `old !== getScrollTop()` it doesn't eat so much CPU neither.

Amen to it being harder to _get right_ than first appears...

I've been working on a floating/sticky scroll solution over the last couple of days and decided to go with fixed positioning to try and lessen the CPU load. Dealing with all the edge cases and trying to keep the code as sane as possible has been a complete bitch. Off loading all that to the browser would be a godsend.

It's still a work in progress but this is what I have so far: http://pastebin.com/PWCCERXk

A tidied up and finished off version is here, in case it's useful to anyone: https://gist.github.com/corford/6697919

I believe the problem with iOS (unless my info is outdated) is that it doesn't listen to the scroll event until it's completed. so sticky stuff won't move until the user has finished scrolling and lifted their finger from the screen.

I ran into that problem with a project not too long ago. It wasn't for something sticky though; a modal with video would dock itself to the bottom of the page on scroll to allow for content viewing but having the modal still visible.

On iPads that docking wouldn't happen until after the scroll had completed instead of at the start of the scroll. I'm not sure if this happens on the latest iOS versions or not though. But it was fun explaining to project managers what was going on during QA.

To mitigate this, simply bind to the "touchmove" and "touchstart" events as well.

Wouldn't that bind the functionality to user interaction beyond just scrolling?

Analytics shows us that this minor issue with iPads is of little concern. But at least I now have a suggestion for a solution if someone decides it's a big enough deal. Thanks for the tip.

Sort of. If you use an overflow:scroll element it does fire during scrolling. While the user's finger is down. You get no events for the momentum after that (which, irritatingly, I'm pretty sure is to stop people reverse engineering it) until it finally stops.

All round, very very irritating.

Ill get on the "plugging my positioning plugin train" - Here is my plugin for floating the table's header:


I am a both sad and happy that it may be obsolete soon. Maybe I can add feature detection for this and short-circuit 1000 lines of logic if sticky position exists.

Superb demo pages! I can see a lot of thought has gone into this. Love the comparisons with other plugins. Well done.

Great job guys, it only took 11 years (plus however long it takes to get this into IE/Chrome/Opera…) to finally solve the problem of table headers in CSS: http://lists.w3.org/Archives/Public/www-style/2002May/0153.h...

It's already implemented in Chrome (behind a flag, but it is there), and thereby soon in Opera. Perhaps even Safari. As for IE, yeah, you are going to have to resort to alternative solutions.

Then again, if implemented properly, the lack of sticky positioning should not break the usability, only enhance it whenever present.

Chrome (really Blink)'s implementation was inherited from Safari's implementation from before Blink forked from WebKit.

Can someone explain what 'Position: sticky' is please?

As I'm having difficulty accessing the video:

(I still seem to have lots of issues trying to watch videos in the browser. Even embedded Vimeo never works for me (Chrome/Debian/Linux), seems flash video is the only thing that consistantly works).

  {position: sticky}
It looks like it pins an element in a fixed position when it normal position has scrolled off the screen as long as it's parent container is visible on screen. It displaying it inline as normal when its position is visible onscreen.

It can be used to make sticky-headers like iOS lists have: e.g. showing the letter of the alphabet at the top of the screen when scrolling through an address book .

It will be really useful for keeping the row titles visible in a long scrolling table.

I've seen this kind of behaviour on a few sites. I thought it was achieved by having the position fixed on the element, as soon as JS detected that the element was moving out of the document window.

There's a time and a place for this sort of thing. I personally get a little annoyed with fixed headers as it can break text paging. Text gets hidden under the header. When you hit page-down you get another page worth of text but the fixed element obscures the text.

Can position: sticky help with something like that?

i think the correct fix for this is for the browser to realise that some of the height is obscured by position:fixed elements, and only scroll the rest of the height on a page-down keypress. a javascript version of the same wouldn't be possible, so yes, this can help. whether it's implemented like that yet i'm not sure, perhaps open a bug with webkit / gecko if not.

Firefox already does this and has for some time.

Really? Not for me, and I' m on Nightly. Perhaps we are talking about different things.


If you would like to watch the video, right click download this link: https://vid.ly/9u6k6d?content=video&format=webm

That should download the file directly, and you can watch it in a native player.

Thanks. How I hate embedded video! I wish authors would at least give an alternative download for their resources. Beats having to dig around in the source.

That one is a little too large a video a file size for my tariff, will have to watch later.

(I stated Chrome. But never have much luck in Firefox either. Anyhow, nevermind.)

As always, its a good idea if used correctly. Often, sticky headers are used and cover half the screen on small devices. Use it only if it actually helps usability!

I hope this improves performance when scrolling on iOS etc. It's currently almost impossible to get that right using javascript, because it's all hardware accelerated and scroll events don't fire reliably.

It does! In fact, this is the reason sticky positioning exists. See the original proposal at http://lists.w3.org/Archives/Public/www-style/2012Jun/0627.h...:

Many web sites have elements that alternate between being in-flow and being position:fixed, depending on the user's scroll position. This is often done for elements in a sidebar that the page author desires to be always available as the user scrolls, but which slot into a space on the page when scrolled to the top. It can also be done for table headers which remain visible after the top of the table has been scrolled off- screen.

Lots of sites, such as news.google.com (the "Top Stories" sidebar) and yelp.com (the search results map), use scroll event listeners in JavaScript to achive this effect. However, browsers are increasingly moving towards scrolling implementations that make use of hardware acceleration to improve performance, for example by leveraging the GPU, and doing scrolling on a thread other than the main UI thread.

In this situation, browsers may use fast scrolling but fire scroll events asynchronously, which will result in rendering glitches on pages that update element positions from JavaScript via scroll events. Alternatively, the browser may fall into a slow scrolling mode when scroll events are listened for; this impacts the perceived quality of the browser's scrolling. To address this problem, common scrolling behaviors like this should be exposed declaratively, through CSS.

I am not sure I like how CSS gets bloated with special case behaviors like this. Sticky headers seem to me like animated gifs - something that is hugely popular for several years and then goes away silently because it is more eye candy than useful.

That would be a fair argument if people weren't already building slower and massively more hacky solutions in Javascript. So clearly there is a demand for this 'special case' because people are already building workarounds. Sadly those workarounds will never be a smooth as browser-supported CSS property. Thus I think it makes a lot of sense to include this at the browser level.

And while you're right that, like any CSS property or HTML tag, there's the possibility of abuse, this particular property does have some genuine usability gains (table headings being a great example). So it seems silly to discourage the addition of sticky based on a vague fear of CSS becoming bloated and the potential of few evil sites over using it.

Sticky has more uses than just headers, for instance sidebars and other sorts of control panels can make use of it to improve usability as well. It's a usability feature, not a fad design feature.

You mean like in the bootstrap documentation, where with a small enough viewport you cannot access bottom of the menu?

That's a failure of the implementation, not a failure of the concept. Having dealt with implementing things like that in the past, I can't offer an excuse other than laziness for those implementations. However, it doesn't take away from the concept.

I agree. The CSS standard seems like a giant hack job. Which I suppose is generally the case for non turing languages that have to stay relevant in a changing world.

Since it's already a giant hack job, and it still doesn't do what we want with all its plethora of existing hacks, you may as well add one more hack. It's not like there's some conceptual purity of CSS that's worth saving - it's piss-poor at doing its job of laying out complete pages. We suffer it because of the universality of HTML+CSS across every platform.

Having an always-visible "current section" header while scrolling a large document seems quite useful to me...

Table-based layout was useful and frequently easier too and we still abandoned it. I still believe this is behavioral markup and should be done in JS.

mind explaining what you mean by behavioral markup?

CSS that tries to be a declarative approach to describing behavior. This is wrong in my opinion like HTML tags for styling were wrong. I think this is wrong because behavior is so incredibly complex that you end up defining rules for everything - and in the end, using a imperative language is much simpler.

I know it's different, but the argument here http://dealloc.me/2011/06/24/d3-is-not-a-graphing-library.ht... applies in a similar way.

Are you also then against CSS transitions?

In fact, yes.

I'm surprised no one has said anything about the intern. Decent presentation and solid work. Good on him.

This has been available on iOS since iOS 6. I'm surprised more people don't know about it!

It's neat and useful but having text sometimes scroll under other text is going to be disorienting for some.

Personally, though I like that it will be an option, I don't want it in my pages. For documentation it just gets in the way of other text to read. Headers are a marker and starting context- they don't need to continue to be displayed.

This seems like a very good idea, provided that the implementation makes sense. The current approach of using javascript to watch for scroll-offset is a bit clunky.

I'd like to see this for footers; have the footer at the bottom of the browser if the content is too small, or the bottom of the webpage if the content is large enough for the user to scroll. After skimming the video, I'm not sure if this would be possible with "position: sticky".

I understand this works for sticky headers. Footers, too?

e.g. You have a table and you want the header row(s) to be fixed, but _also_ footer row(s) with totals.

Thank you CSS, another way to keep ads and "social buttons" always in front of me. I want a browser addon that hides all position:fixed and position:sticky elements unconditionally, never seen a site that wouldn't be improved by that.

I guess it would be nice to add sticky attribute for "smart hide" of sticky things, like show them when you scroll up a bit, but hide when you scroll down, just as recent Chrome started doing.

I utterly loathe this feature in Android Chrome. My constant instinct is to pull down the status bar like you pull down the notifications and quick-menu. Scrolling up to see it screws me up.

This is especially huge for mobile web where the scroll event isn't fired until after scroll finishes and utilizing touch events leads to a pretty hacky and choppy solution. Bravo.

It'd be awesome if this is possible for a horizontal setup too!

It is. The intern said that in the video.

Ohh I see. Guess I missed it. :)

That was a very good presentation.

They don't seem to be interested in feedback on that site though.

{position: sticky} will definitely be a great feature to have.

If everyone is using hacks like Bootstrap it makes sense to incorporate more of it into CSS.

Will this support horizontal scrolling also, e.g. freeze a table column?

yes, he says so in the video.

How about some usable centering of blocks instead?

Great feature. Also landed on webkit.

`position: sticky` was working in Chrome(ium) a while ago but somehow the removed it.

This is awesome, great work!

Congratulation! Turbo Vision had this only 25 years ago, JS is catching up :-)

correct me if I'm wrong, but isn't the point of this that its CSS and not JS?

It's not JS.

This is just awesome!

Registration is open for Startup School 2019. Classes start July 22nd.

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