Chrome breaks visual viewport — again

A few weeks back the most exciting viewport news of the past few years broke: Chrome 61 supports a new visual viewport API. Although this new API is an excellent idea, and even includes a zoom event in disguise, the Chrome team decided that its existence warrants breaking old and trusty properties.

I disagree with that course of action, particularly because a better course is readily available: create a new layout viewport API similar to the visual one. Details below.

If you need a quick viewport reminder, see the (desktop only) visualisation page where you can play around and rediscover how the visual and layout viewports work. The new version contains notes about JavaScript properties in the various browsers. Or see Jake Archibald’s visualisation, which has the advantage of somewhat working on mobile devices.

Today’s problem is window.innerWidth/Height. This gives the dimensions of the visual viewport in ALL browsers. In Chrome 61, however, it gives the dimensions of the layout viewport instead of the visual viewport. This is a deliberate change, not a bug, and I think it’s a mistake.

So if you use window.innerWidth/Height in any of your sites, it may break in Chrome 61/Android.

And if you scratch your head and feel you’ve heard all this before, you’re right. We had exactly the same situation in early 2016 (see the discussion here), and that ended with Chrome rolling back the change. Let’s hope they do the same now.

The new API

Jake’s article contains all the relevant information about the new visual viewport API. Summarising briefly:

width and height
The visual viewport’s current width and height
pageLeft and pageTop
The visual viewport’s current offset relative to the document.
offsetLeft and offsetTop
The visual viewport’s current offset relative to the layout viewport.
The visual viewport’s current zoom level relative to the layout viewport.

See my (desktop only) visualisation page for the first three items. Don’t forget to select Chrome 61+ as your browser.

Also, the API contains a scroll and resize event for the visual viewport (though there are still a few bugs in Chrome’s implementation; see here and here). The resize event has me really, REALLY excited because resizing the visual viewport means zooming in or out, and that means this resize event is a zoom event. I forget how many years ago it was that I floated this idea, and I’m very happy that a browser vendor is now testing it.

Thus the visualViewport API is an excellent idea that I support fully. Other browsers: please implement at your earliest convenience.

Google’s idea

Unfortunately, the API is not the whole story.

While the visual viewport merits a new API, Google feels the layout viewport does not: we can use the old, confusing properties that we have been using for years.

Now I am the first one to admit that the current hodgepodge of properties is confusing. Why does window.innerWidth/Height give the visual viewport dimensions, while document.documentElement.clientWidth/Height gives the layout viewport dimensions? Essentially, that’s a historical coincidence that I’ll explain later, if anyone is interested.

Two viewports, two APIs

Given this sad state of affairs, the idea of a new API that starts with a clean slate is a good one. Unfortunately, once we get beyond the specifics of the new API, I feel that Google is making serious mistakes.

To me, the most logical next step would be the creation of a layoutViewport API that mirrors the visualViewport one. Thus, in the future, visualViewport.width would give the current width of the visual viewport, while layoutViewport.width would do the same for the layout viewport.

That, however, is not what’s happening. The idea is that the layout viewport data will continue to come from the old, confusing jumble of properties we’ve been using for the last seven years.

In itself, this is a meh decision. If you want to clarify the two viewports for web developers, creating a separate API for each would be the way to go.

Breaking backward compatibility

But it doesn’t stop here: the Chrome team decided to redefine all old properties relative to the layout viewport, even if they denote the visual viewport in all other browsers.

I’m specifically thinking of window.innerWidth/Height here, which has been exposing the dimensions of the visual viewport in ALL browsers since 2011 or so. (window.scrollX/Y and window.pageX/YOffset are also affected: they used to be relative to the visual viewport, but are now also relative to the layout viewport.)

So if you use window.innerWidth/Height in any of your sites, it may break in Chrome 61/Android.

Layout viewport problems

I feel that the Chrome team is ignoring the layout viewport API (and is breaking backward compatibility) for no good reason here. The brief discussion mainly highlights the handling of old, non-mobile-optimised sites, and the fact that it’s hard to define exactly what the layout viewport is.

It is true that viewports are ill-defined. W3C’s only attempt at speccing them was an unreadable disaster that failed to address important points — for instance, the existence of the visual viewport.

Still, the solution ought to be not messing up random bits of the a system that, while confusing, is supported by all browsers, but by creating a proper specification for the viewports. The visual viewport API is an excellent first step in this direction — it should be followed by a layout viewport API, and then by a full viewports specification. I already highlighted the main points of such a specification two years ago.

What to do?

Thus, I call upon Google to stop its messing with ancient and reliable JavaScript properties, reverse the definition change of window.innerWidth/Height, and create a layout viewport API as a second step toward a full viewports specification.

If you care about this issue, I urge you to star the bug report I submitted. Even better: if you have examples of scripts that use the visual viewport, leave a polite comment describing what you do and how it would break. Google is a data-driven company: if you provide it with data it will eventually cough up the correct solution.

Anyway, I hope I made clear that suddenly changing something that has been working for a while now is a bad idea. I hope the Chrome team reverts the change to window.innerWidth/Height.

This is the blog of Peter-Paul Koch, web developer, consultant, and trainer. You can also follow him on Twitter.
Atom RSS