Cover photo
Nat Duca
Works at Google


I'd like to soapbox about the need for rationality in the web platform, using position:sticky as a guinea-pig to explain my perspective.

The thing that bugs me about position:sticky is that is entangled with the magical nature of scrolling on the web. Per spec, the browser can scroll the page up and down without telling JS: you get a scroll event, but it happens after the scroll has actually happened.


Here's the thing: this ability in browsers is super important, because scrolling is super duper important to get right for users. Without it, going to and scrolling is a really horrible user experience. On mobile, that poor site janks for a half second while it loads. I NEED MY SPORTS SCORES TO SCROLL AT 60FPS. The browser works around this by making scroll asynchronous. A simpler example is this: : on mobile browsers, this scrolls smoothly, even though in devtools you'll see that the page is a cataclysm of jank.

Unfortunately, we've painted ourselves into a corner here, with regard to position:sticky and all other scroll coupled effects. If you try to polyfill sticky positioning, you get jitter. Typically, the user's scroll is immediately handled by the browser, drawn to the screen as fast as possible so it feels responsive. THEN the browser tells JS about it. The polyfill thus hears about the onscroll too late: it valiantly tries to update the sticky position, but the page has been sent to the screen with the movement already applied, so the user perceives a little jump in the next frame as the polyfill's reaction finally makes it onscreen. Designers get cranky, and you don't get to go to space.

Because of this, we have a promulgation of urgent-for-some spec needs: anytime a user wants a scroll-coupled effect, they need need new spec. That gets scary quickly, because lets face it, there's a ton of cool stuff you an do in response to scroll. We articulated this concern once for snap points, here: 

Sticky positioning is in this space too. A common misconception is that position:sticky is an easily speccable, ready to go, kind of thing. In reality, there many many many variations on position:sticky-ish behavior out there for every simple use case, so speccing it is all about compromises and generalization. Even if we implement a common form of position:sticky, there will be corner cases we don't implement. Want your element to sing a sea shanty and then shrink to scale(0) as it falls offscreen? Sorry, please wait for Level 2 version, tentatively titled "position: even-more-sticky."

So, what to do?

As some might recall, +Dimitri Glazkov wrote a great essay on our need for a rational web platform a while back (!topic/blink-dev/4jBAnIVwrt0). In it, he points out that we must first and foremost "explain the magic" behind our browser.

I submit that much of the sticky positioning debacle is fallout from the browser being magical about scroll. First and foremost, in this space, we need to explain the magic to the page: that way when the magic isn't quite right, you can get around it to do things your way.

What form should this particular fix to the magic take? Not sure, yet! Maybe we need to explain browser-side scrolling using some new APIs. Or maybe we need to allow content to opt-out of this magic. +Rick Byers has some much more formed ideas on how this might be done.

Important for me is embracing the idea of layering and accidental magic, recognizing that the lack of layering can take a basic feature request and turn it into a much bigger problem.

Consider: if we had a web that had an opt-out for magical scrolling, then we'd have plenty of content out there today doing position:sticky effects. Sure, there'd be the odd incurably janky page out there that wanted sticky, too. And there'd be people asking for sticky effects to be easier to author.

Both are great feature requests. With the immediate "I CANT IMPLEMENT THIS" fires resolved, we can then work through those goals at a normal and healthy web platform pace.

So, here's to identifying layers in the web platform, and fixing the bugs that cause layering to go wonky. And, here's to picking a subset of the most commonly occurring cases on the web and making those easy (
Mike Fotinakis's profile photoMalte Ubl's profile photoJon Rimmer's profile photoErik Isaksen's profile photo
Unless the spec has changed, position: sticky would not necessarily solve the table example. It unfortunately described changing an element that is absolute on the page to stuck to the top of the viewport, so it's only page / viewport-related, instead of to the top of any scroll container , making the proposal extremely shortsighted IMO.
Add a comment...

Nat Duca

Shared publicly  - 
The Runtime Performance Checklist

A consolidation of the big hitters that will kill your fps.

Have you checked them all off?
Add a comment...

Nat Duca

Shared publicly  - 
Thanks to +Paul Lewis, now has an RSS feed. Good way to follow along if you're trying to keep up with the ever-changing world of silky smooth web design.
Mauro Seno's profile photoKashif Ansari's profile photo
Add a comment...

Nat Duca

Shared publicly  - 
The best way to avoid the dreaded 300ms click delay is to disable double-tap zoom.

Much has been written about the evil 300ms delay in dispatching click events on touch-based browsers (eg.  There are some good libraries for dealing with this (notably, but they have drawbacks such as:
- They can significantly hurt scrolling performance (
- They disable touch adjustment (the process of 'fuzzing' the position of a touch to a nearby target to make it easier to hit small targets)
- There are number of edge cases that are hard to get right in all browsers that can lead to bugs and confusion.

It's much better to avoid the problem entirely if possible.  Most modern browsers have a mitigation that many developers aren't aware of - disabling the double-tap gesture.  When double-tap is disabled, clicks can be processed immediately.

On Chrome Android and Firefox this involves using the "viewport" meta tag to disable zooming (with user-scalable=no or initial-scale=1,maximum-scale=1) - see  Here's a simple test that measures the click delay with and without this optimization:

In IE the situation is even better, you can selectively disable double-tap support on individual elements with touch-action (  For example, apply 'touch-action: manipulation' to buttons and links to enable fast clicks without disabling pinches that happen to start on them.  Unfortunately we were not able to get this detail of touch-action into the W3C standard version (, so Chrome and Firefox may not get this anytime soon.

Note that we never added double-tap support to the desktop version of Chrome at all because we didn't want to introduce a click delay there (but on a large screen the 'zoom to fit' operation isn't very useful anyway).

Luckily FastClick mostly knows about all this and will disable itself when it's not needed (, so for the most part you can use this library and not have to be aware of the details.

Of course it may still be surprising to users if double tap triggers a click instead of zooming, but that's a fundamental UX tradeoff that must be made in any solution to the click delay problem (and delaying most operations by 300ms is also REALLY bad for the user experience).

So bottom line: if you've implemented your own fast-click solution, make sure you're taking all the above solutions into account (or better yet just switch to using FastClick).

We're working on a number of other approaches on the Chrome team to help address the click delay problem.  Stay tuned!

#clickdelay   #touchevents   #touch  
Erwin Coumans's profile photoNat Duca's profile photo
Hmm not sure why that is.... Sometimes ui designers disable pinch for stylistic concerns...
Add a comment...

Nat Duca

Shared publicly  - 
Good stuff.
A Developer's Guide to Rendering Performance

Where I run through how pixels get to the screen, what tools Chrome provides for you to profile your projects, and how to pronounce GIF correctly.

Educational, yo.
Add a comment...

Nat Duca

Shared publicly  - 
The one where I ruminate of layers, platforms, cabbages, and kings.

cross-posting from blink-dev
Add a comment...

Nat Duca

Shared publicly  - 
Wise words follow...
Scrolling at 60fps

For a while people recommended to use a "noHover" class during scrolling to avoids paints that kill 60fps. Turns out that doesn't actually work because adding the noHover class causes a full style recalc which will likely completely annihilate your frame rate.

Today I saw this article, which tries to use pointer events instead to avoid the problems
… and, indeed, it achieves great frame rates. Unfortunately it is even more broken, since it will block all clicks on your site within half a second after you stop scrolling. That might be quiet a few clicks. Fortunately we have found a way to avoid those problem:

The key insight is to use a cover div on which you toggle pointer events (or you just move it in and out of view using translate during scrolling). Then, when the user clicks the coverDiv during scrolling you can use document.elementFromPoint to get the real target:

var doc =;
var copy = doc.createEvent('MouseEvents');
copy.initEvent(e.type, true, true);
var realTarget = doc.elementFromPoint(e.clientX, e.clientY);

Unfortunately there is one problem with this approach:
It doesn't work across iframes – it could be made to work in same origin iframes, but it can't be made to work with cross origin iframes. So, i.e. a click on the +1 button or a like button on your site may still be "eaten"

… which is why people should not use such hacks and instead ask browser vendors, to simply not paint during scrolling if they think that painting during scrolling is bad – which incidentally I did do :)
Add a comment...

Nat Duca

Shared publicly  - 
High performance animations


TL;DR Most modern browsers can animate these four properties cheaply. If you animate anything else chances are you'll bust your frame budget and miss out on 60fps.

Sergio Ramirez's profile photo
Add a comment...

Nat Duca

Shared publicly  - 
Android's WebView is now powered by Chrome

The latest release of Android (KitKat) now uses a Chromium based WebView for embedded web content across the system.  The new Chromium based WebView lets you take advantage of many of the latest features inside Chrome for your applications and content, including first class support for Chrome DevTools.

Check out our docs about the latest changes to WebView 
Add a comment...

Nat Duca

Shared publicly  - 
<rant>Beware of Applecare: as I learned from the lovely Palo Alto Apple Store today, quoting, at "even a small drop of water contact," Apple can decline service on everything. In a world where laptops and things like trackpads get little drops of water on them as a course of life, this renders AppleCare nullable virtually without thought on the part of Apple. Save yourself $249.</rant>
Joel Webber's profile photoNat Duca's profile photo
That's pretty nuts. You'd think their much vaunted customer service would allow for a little more leeway for obviously stupid cases like that.

Good luck with the spacebar. I know what a PITA it can be to have one that's slightly wonky.
Add a comment...
Do you like my hat?
Making Chrome run at 60 fps, or bust.
  • Google