The APIs introduced by this document provide authors with a way to determine and interact with the properties of the visual viewport.

TODO

Introduction

Some user agents have split their viewport into two conceptual viewports, colloquially known as the visual and layout viewports. This separation is useful in enabling a user agent (UA) with a small screen to allow the user to zoom in on parts of the page without causing the page to respond, for example, by obscuring the user's view with position: fixed elements. As another example, mobile UAs often provide an on-screen keyboard (OSK) for user input. Without the visual/layout split, a position: fixed element would be pushed up when the OSK is shown, obscuring the user's view. Informally, the layout viewport is what the web page uses when laying out its UI while the visual viewport is the box on the page that the user can currently see, accounting for transient UI features like pinch-zoom and the OSK.

The existing APIs provided by UAs are ambiguous about which viewport they're relative to. For example, document.scrollingElement.scrollLeft returns the scroll position of the visual viewport while document.scrollingElement.clientWidth returns the width of the layout viewport. getBoundingClientRect returns the rect relative to the layout viewport while positioning non-fixed elements relative to the layout viewport is difficult. This makes building UI that responds to scrolls across mobile and desktop UAs difficult. Worse still, there's no way for the developer to be notified when the visual viewport changes. For example, the only way to know when the user has zoomed is to poll or listen to touch events and continually check window.innerWidth.

The Visual Viewport API is designed to provide an explicit mechanism for developers to query and potentially modify the properties of the visual viewport. It also introduces events that allow the page to listen for changes in the visual viewport, allowing UX that explicitly wants to react to these changes to do so. For example, the page could keep a small text-formatting bar above the OSK.

Description

Extensions to the Window interface

This document extends the Window interface defined by [[!HTML]].

            partial interface Window {
              [SameObject, Replaceable] readonly attribute VisualViewport visualViewport;
            };
          
visualViewport
Returns the VisualViewport object associated with this Window.

The VisualViewport interface

A VisualViewport object represents the visual viewport for a given window. Each window on a page will have a unique VisualViewport object representing the properties associated with that window.

            interface VisualViewport : EventTarget {
              readonly attribute double offsetLeft;
              readonly attribute double offsetTop;

              readonly attribute double pageLeft;
              readonly attribute double pageTop;

              readonly attribute double width;
              readonly attribute double height;

              readonly attribute double scale;

              attribute EventHandler onresize;
              attribute EventHandler onscroll;
            };
          
offsetLeft
Returns the offset of the left edge of the visual viewport from the left edge of the layout viewport in CSS pixels.
offsetTop
Returns the offset of the top edge of the visual viewport from the top edge of the layout viewport in CSS pixels.
pageLeft
Returns the x-coordinate, relative to the initial containing block origin, of the left edge of the visual viewport in CSS pixels.
pageTop
Returns the y-coordinate, relative to the initial containing block origin, of the top edge of the visual viewport in CSS pixels.
width
Returns the width of the visual viewport in CSS pixels. This value excludes the width of any rendered classic scrollbar that is fixed to the visual viewport.
A scrollbar that is fixed to the visual viewport is one that does not change size or location as the visual viewport is zoomed and panned. Because this value is in CSS pixels, when excluding the scrollbar width the UA must account for how large the scrollbar is in CSS pixels. That is, the amount excluded is lessened if the viewport is zoomed in and the scrollbars don't change size to the user.
height
Returns the height of the visual viewport in CSS pixels. This value excludes the height of any rendered classic scrollbar that is fixed to the visual viewport.
Because both the width and height attributes are expressed in CSS pixels, increasing either page-zoom or pinch-zoom will cause these values to shrink.
scale
Returns the pinch-zoom scaling factor applied to the visual viewport. It can be computed using the following algorithm:
  1. If there is no output device, return 1 and abort these steps.

  2. Let CSS pixel size be the size of a CSS reference pixel at the current page zoom and pinch zoom scales.

  3. Let device pixel size be the size of a device pixel of the output device.

  4. Let device independent pixel size be the product of device pixel size and the devicePixelRatio

  5. Return the result of dividing the CSS pixel size by the device independent pixel size.

Although it is referred to as the pinch-zoom scaling factor, it can be affected through means other than pinch-zooming. e.g. When the UA centers and zooms in a focused edit box.
onresize
Event handler attribute for the resize event.
onscroll
Event handler attribute for the scroll event.

Events

Resizing the viewport

The user agent must fire an Event named resize at the VisualViewport object if any of its height, width, or scale attributes change (e.g. in response to user interaction, scrollbars appearing/disappearing). The resize event must not bubble and must not be cancellable.

These events follow the procedure defined in section 12.1 of the CSSOM View module.

Scrolling

The user agent must fire an Event named scroll at the VisualViewport object if either of its offsetTop or offsetLeft attributes change (e.g in response to user interaction, by an API, or by the resize of the visual viewport). The scroll event must not bubble and must not be cancellable.

These events follow the procedure defined in section 12.2 of the CSSOM View module.