1. Background
Many of the features defined in this specification have been supported by browsers for a long period of time. The goal of this specification is to define these features in such a way that they can be implemented by all browsers in an interoperable manner. The specification also defines a some new features which allow for scroll customization.
2. Terminology
Terminology used in this specification is from DOM, CSSOM and HTML. [DOM] [CSSOM] [HTML]
An element body (which will be the body
element) is
potentially scrollable if all of the following conditions are true:
-
body has an associated box.
-
body’s parent element’s computed value of the overflow-x or overflow-y properties is neither visible nor clip.
-
body’s computed value of the overflow-x or overflow-y properties is neither visible nor clip.
Note: A body
element that is potentially scrollable might not have a scrolling box.
For instance, it could have a used value of overflow being auto but not have its content overflowing its content area.
A scrolling box of a viewport or element has two overflow directions, which are the block-end and inline-end directions for that viewport or element. Note that the initial scroll position might not be aligned with the scrolling area origin depending on the content-distribution properties, see CSS Box Alignment 3 § 5.3 Alignment Overflow and Scroll Containers.
The term scrolling area refers to a box of a viewport or an element that has the following edges, depending on the viewport’s or element’s scrolling box’s overflow directions.
If the overflow directions are… | For a viewport | For an element |
---|---|---|
rightward and downward |
|
|
leftward and downward |
|
|
leftward and upward |
|
|
rightward and upward |
|
|
The origin of a scrolling area is the origin of the initial containing block if the scrolling area is a viewport, and otherwise the top left padding edge of the element when the element has its default scroll position. The x-coordinate increases rightwards, and the y-coordinate increases downwards.
The beginning edges of a particular set of edges of a box or element are the following edges:
- If the overflow directions are rightward and downward
- The top and left edges.
- If the overflow directions are leftward and downward
- The top and right edges.
- If the overflow directions are leftward and upward
- The bottom and right edges.
- If the overflow directions are rightward and upward
- The bottom and left edges.
The ending edges of a particular set of edges of a box or element are the following edges:
- If the overflow directions are rightward and downward
- The bottom and right edges.
- If the overflow directions are leftward and downward
- The bottom and left edges.
- If the overflow directions are leftward and upward
- The top and left edges.
- If the overflow directions are rightward and upward
- The top and right edges.
The visual viewport is a kind of viewport whose scrolling area is another viewport, called the layout viewport.
In addition to scrolling, the visual viewport may also apply a scale transform to its layout viewport. This transform is applied to the canvas of the layout viewport and does not affect its internal coordinate space.
Note: The scale transform of the visual viewport is often referred to as "pinch-zoom". Conceptually, this transform changes the size of the CSS reference pixel but changes the size of the layout viewport proportionally so that it does not cause reflow of the page’s contents.
The magnitude of the scale transform is known as the visual viewport’s scale factor.
This animation shows an example of a zoomed in visual viewport being "panned" around (for example, by a user performing a touch drag). The page is scaled so that the layout viewport is larger than the visual viewport.
A scroll delta is applied to the visual viewport first. When the visual viewport is at its extent, scroll delta will be applied to the layout viewport. This behavior is implemented by the perform a scroll steps.
The VisualViewport
object has an associated document, which is a Document
object.
It is the associated document of the owner Window
of VisualViewport
. The layout viewport
is the owner Window
’s viewport.
For the purpose of the requirements in this specification, elements that have a computed value of the display property that is table-column or table-column-group must be considered to have an associated box (the column or column group, respectively).
The term SVG layout box refers to a box generated by an SVG element
which does not correspond to a CSS-defined display type.
(Such as the box generated by a rect
element.)
The term transforms refers to SVG transforms and CSS transforms. [SVG11] [CSS-TRANSFORMS-1]
When a method or an attribute is said to call another method or attribute, the user agent must invoke its internal API for that attribute or method so that e.g. the author can’t change the behavior by overriding attributes or methods with custom properties or functions in ECMAScript.
Unless otherwise stated, all string comparisons use is.
2.1. CSS pixels
All coordinates and dimensions for the APIs defined in this specification are in CSS pixels, unless otherwise specified. [CSS-VALUES]
Note: This does not apply to e.g. matchMedia()
as the units are explicitly given there.
2.2. Zooming
There are two kinds of zoom, page zoom which affects the size of the initial viewport, and the visual viewport scale factor which acts like a magnifying glass and does not affect the initial viewport or actual viewport. [CSS-DEVICE-ADAPT]
Note: The "scale factor" is often referred to as "pinch-zoom"; however, it can be affected through means other than pinch-zooming. e.g. The user agent may zooms in on a focused input element to make it legible.
2.3. Web-exposed screen information
User agents may choose to hide information about the screen of the output device, in order to protect the user’s privacy. In order to do so in a consistent manner across APIs, this specification defines the following terms, each having a width and a height, the origin being the top left corner, and the x- and y-coordinates increase rightwards and downwards, respectively.
The Web-exposed screen area is one of the following:
-
The area of the output device, in CSS pixels.
-
The area of the viewport, in CSS pixels.
The Web-exposed available screen area is one of the following:
-
The available area of the rendering surface of the output device, in CSS pixels.
-
The area of the output device, in CSS pixels.
-
The area of the viewport, in CSS pixels.
3. Common Infrastructure
This specification depends on the WHATWG Infra standard. [INFRA]
3.1. Scrolling
When a user agent is to perform a scroll of a scrolling box box,
to a given position position,
an associated element or pseudo-element element and optionally a scroll behavior behavior
(which is "auto
" if omitted),
the following steps must be run:
- Abort any ongoing smooth scroll for box.
-
If the user agent honors the scroll-behavior property and one of the following are true:
- behavior is "
auto
" and element is not null and its computed value of the scroll-behavior property is smooth - behavior is
smooth
Note:
behavior: "instant"
always performs an instant scroll by this algorithm.Note: If the scroll position did not change as a result of the user interaction or programmatic invocation, where no translations were applied as a result, then no scrollend event fires because no scrolling occurred.
- behavior is "
When a user agent is to perform a scroll of a viewport to a given position position and optionally a scroll behavior behavior
(which is "auto
" if omitted) it must perform a coordinated viewport scroll by following these steps:
-
Let doc be the viewport’s associated
Document
. -
Let vv be the
VisualViewport
whose associated document is doc. -
Let maxX be the difference between viewport’s scrolling box’s width and the value of vv’s width attribute.
-
Let maxY be the difference between viewport’s scrolling box’s height and the value of vv’s height attribute.
-
Let dx be the horizontal component of position - the value vv’s pageLeft attribute
-
Let dy be the vertical component of position - the value of vv’s pageTop attribute
-
Let visual x be the value of vv’s offsetLeft attribute.
-
Let visual y be the value of vv’s offsetTop attribute.
-
Let visual dx be min(maxX, max(0, visual x + dx)) - visual x.
-
Let visual dy be min(maxY, max(0, visual y + dy)) - visual y.
-
Let layout dx be dx - visual dx
-
Let layout dy be dy - visual dy
-
Let element be doc’s root element if there is one, null otherwise.
-
Perform a scroll of the viewport’s scrolling box to its current scroll position + (layout dx, layout dy) with element as the associated element, and behavior as the scroll behavior.
-
Perform a scroll of vv’s scrolling box to its current scroll position + (visual dx, visual dy) with element as the associated element, and behavior as the scroll behavior.
Note: Conceptually, the visual viewport is scrolled until it "bumps up" against the layout viewport edge and then "pushes" the layout viewport by applying the scroll delta to the layout viewport. However, the scrolls in the steps above are computed ahead of time and applied in the opposite order so that the layout viewport is scrolled before the visual viewport. This is done for historical reasons to ensure consistent scroll event ordering. See the example above for a visual depiction.
Scroll is completed when the scroll position has no more pending updates or translations and the user has completed their gesture. Scroll position updates include smooth or instant mouse wheel scrolling, keyboard scrolling, scroll-snap events, or other APIs and gestures which cause the scroll position to update and possibly interpolate. User gestures like touch panning or trackpad scrolling aren’t complete until pointers or keys have released.
When a user agent is to perform a smooth scroll of a scrolling box box to position, it must update the scroll position of box in a user-agent-defined fashion over a user-agent-defined amount of time. When the scroll is completed, the scroll position of box must be position. The scroll can also be aborted, either by an algorithm or by the user.
When a user agent is to perform an instant scroll of a scrolling box box to position, it must update the scroll position of box to position.
To scroll to the beginning of the document for a document document, follow these steps:
- Let viewport be the viewport that is associated with document.
- Let position be the scroll position viewport would have by aligning the beginning edges of the scrolling area with the beginning edges of viewport.
- If position is the same as viewport’s current scroll position, and viewport does not have an ongoing smooth scroll, abort these steps.
- Perform a scroll of viewport to position, and document’s root element as the associated element, if there is one, or null otherwise.
Note: This algorithm is used when navigating to the #top
fragment identifier, as defined in HTML. [HTML]
Tests
- interrupt-hidden-smooth-scroll.html (live test) (source)
- long_scroll_composited.html (live test) (source)
- scroll-back-to-initial-position.html (live test) (source)
- scrolling-no-browsing-context.html (live test) (source)
- scrolling-quirks-vs-nonquirks.html (live test) (source)
- smooth-scroll-in-load-event.html (live test) (source)
- smooth-scroll-nonstop.html (live test) (source)
3.2. WebIDL values
When asked to normalize non-finite values for a value x,
if x is one of the three special floating point literal values
(Infinity
, -Infinity
or NaN
),
then x must be changed to the value 0
. [WEBIDL]
4. Extensions to the Window
Interface
enum {
ScrollBehavior ,
"auto" ,
"instant" };
"smooth" dictionary {
ScrollOptions ScrollBehavior = "auto"; };
behavior dictionary :
ScrollToOptions ScrollOptions {unrestricted double ;
left unrestricted double ; };
top partial interface Window { [NewObject ]MediaQueryList matchMedia (CSSOMString ); [
query SameObject ,Replaceable ]readonly attribute Screen screen ; [SameObject ,Replaceable ]readonly attribute VisualViewport ?visualViewport ; // browsing contextundefined moveTo (long ,
x long );
y undefined moveBy (long ,
x long );
y undefined resizeTo (long ,
width long );
height undefined resizeBy (long ,
x long ); // viewport [
y Replaceable ]readonly attribute long innerWidth ; [Replaceable ]readonly attribute long innerHeight ; // viewport scrolling [Replaceable ]readonly attribute double scrollX ; [Replaceable ]readonly attribute double pageXOffset ; [Replaceable ]readonly attribute double scrollY ; [Replaceable ]readonly attribute double pageYOffset ;undefined scroll (optional ScrollToOptions = {});
options undefined scroll (unrestricted double ,
x unrestricted double );
y undefined scrollTo (optional ScrollToOptions = {});
options undefined scrollTo (unrestricted double ,
x unrestricted double );
y undefined scrollBy (optional ScrollToOptions = {});
options undefined scrollBy (unrestricted double ,
x unrestricted double ); // client [
y Replaceable ]readonly attribute long screenX ; [Replaceable ]readonly attribute long screenLeft ; [Replaceable ]readonly attribute long screenY ; [Replaceable ]readonly attribute long screenTop ; [Replaceable ]readonly attribute long outerWidth ; [Replaceable ]readonly attribute long outerHeight ; [Replaceable ]readonly attribute double devicePixelRatio ; };
When the matchMedia(query)
method is invoked these steps must be run:
- Let parsed media query list be the result of parsing query.
- Return a new
MediaQueryList
object, with this’s associatedDocument
as the document, with parsed media query list as its associated media query list.
The screen
attribute must return the Screen
object
associated with the Window
object.
Note: Accessing screen
through a WindowProxy
object might yield different
results when the Document
is navigated.
If the associated document is fully active, the visualViewport
attribute must return the VisualViewport
object associated with the Window
object’s associated
document. Otherwise, it must return null.
Note: the VisualViewport object is only returned and useful for a window whose Document is currently being presented. If a reference is retained to a VisualViewport whose associated Document is not being currently presented, the values in that VisualViewport must not reveal any information about the browsing context.
Tests
The moveTo(x, y)
method must follow these steps:
-
Optionally, return.
-
Let target be this’s relevant global object’s browsing context.
-
If target is not an auxiliary browsing context that was created by a script (as opposed to by an action of the user), then return.
-
Optionally, clamp x and y in a user-agent-defined manner so that the window does not move outside the available space.
-
Move target’s window such that the window’s top left corner is at coordinates (x, y) relative to the top left corner of the output device, measured in CSS pixels of target. The positive axes are rightward and downward.
The moveBy(x, y)
method must follow these steps:
-
Optionally, return.
-
Let target be this’s relevant global object’s browsing context.
-
If target is not an auxiliary browsing context that was created by a script (as opposed to by an action of the user), then return.
-
Optionally, clamp x and y in a user-agent-defined manner so that the window does not move outside the available space.
-
Move target’s window x CSS pixels of target rightward and y CSS pixels of target downward.
The resizeTo(width, height)
method must follow these steps:
-
Optionally, return.
-
Let target be this’s relevant global object’s browsing context.
-
If target is not an auxiliary browsing context that was created by a script (as opposed to by an action of the user), then return.
-
Optionally, clamp width and height in a user-agent-defined manner so that the window does not get too small or bigger than the available space.
-
Resize target’s window by moving its right and bottom edges such that the distance between the left and right edges of the viewport are width CSS pixels of target and the distance between the top and bottom edges of the viewport are height CSS pixels of target.
-
Optionally, move target’s window in a user-agent-defined manner so that it does not grow outside the available space.
The resizeBy(x, y)
method must follow these steps:
-
Optionally, return.
-
Let target be this’s relevant global object’s browsing context.
-
If target is not an auxiliary browsing context that was created by a script (as opposed to by an action of the user), then return.
-
Optionally, clamp x and y in a user-agent-defined manner so that the window does not get too small or bigger than the available space.
-
Resize target’s window by moving its right edge x CSS pixels of target rightward and its bottom edge y CSS pixels of target downward.
-
Optionally, move target’s window in a user-agent-defined manner so that it does not grow outside the available space.
The innerWidth
attribute must return the viewport width including the size of a rendered
scroll bar (if any), or zero if there is no viewport.
The innerHeight
attribute must return the viewport height including the size of a rendered
scroll bar (if any), or zero if there is no viewport.
The scrollX
attribute must return the x-coordinate,
relative to the initial containing block origin,
of the left of the viewport,
or zero if there is no viewport.
The pageXOffset
attribute must return the value returned by the scrollX
attribute.
The scrollY
attribute must return the y-coordinate,
relative to the initial containing block origin,
of the top of the viewport,
or zero if there is no viewport.
The pageYOffset
attribute must return the value returned by the scrollY
attribute.
When the scroll()
method is invoked these
steps must be run:
-
If invoked with one argument, follow these substeps:
-
Let options be the argument.
-
Let x be the value of the
left
dictionary member of options, if present, or the viewport’s current scroll position on the x axis otherwise. -
Let y be the value of the
top
dictionary member of options, if present, or the viewport’s current scroll position on the y axis otherwise.
-
-
If invoked with two arguments, follow these substeps:
-
Let options be null converted to a
ScrollToOptions
dictionary. [WEBIDL] -
Let x and y be the arguments, respectively.
-
-
Normalize non-finite values for x and y.
-
If there is no viewport, abort these steps.
-
Let viewport width be the width of the viewport excluding the width of the scroll bar, if any.
-
Let viewport height be the height of the viewport excluding the height of the scroll bar, if any.
-
- If the viewport has rightward overflow direction
- Let x be max(0, min(x, viewport scrolling area width - viewport width)).
- If the viewport has leftward overflow direction
- Let x be min(0, max(x, viewport width - viewport scrolling area width)).
-
- If the viewport has downward overflow direction
- Let y be max(0, min(y, viewport scrolling area height - viewport height)).
- If the viewport has upward overflow direction
- Let y be min(0, max(y, viewport height - viewport scrolling area height)).
-
Let position be the scroll position the viewport would have by aligning the x-coordinate x of the viewport scrolling area with the left of the viewport and aligning the y-coordinate y of the viewport scrolling area with the top of the viewport.
-
If position is the same as the viewport’s current scroll position, and the viewport does not have an ongoing smooth scroll, abort these steps.
-
Let document be the viewport’s associated
Document
. -
Perform a scroll of the viewport to position, document’s root element as the associated element, if there is one, or null otherwise, and the scroll behavior being the value of the