CSSOM View Module

Editor’s Draft,

More details about this document
This version:
https://drafts.csswg.org/cssom-view/
Latest published version:
https://www.w3.org/TR/cssom-view-1/
Previous Versions:
Feedback:
CSSWG Issues Repository
Inline In Spec
Editors:
(Apple Inc)
(Mozilla)
Former Editors:
(Opera Software AS)
Glenn Adams (Cox Communications, Inc.)
Anne van Kesteren (Opera Software ASA)
Suggest an Edit for this Spec:
GitHub Editor
Legacy issues list:
Bugzilla

Abstract

The APIs introduced by this specification provide authors with a way to inspect and manipulate the visual view of a document. This includes getting the position of element layout boxes, obtaining the width of the viewport through script, and also scrolling an element.

CSS is a language for describing the rendering of structured documents (such as HTML and XML) on screen, on paper, etc.

Status of this document

This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress.

Please send feedback by filing issues in GitHub (preferred), including the spec code “cssom-view” in the title, like this: “[cssom-view] …summary of comment…”. All issues and comments are archived. Alternately, feedback can be sent to the (archived) public mailing list [email protected].

This document is governed by the 18 August 2025 W3C Process Document.

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:

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
top edge
The top edge of the initial containing block.
right edge
The right-most edge of the right edge of the initial containing block and the right margin edge of all of the viewport’s descendants' boxes.
bottom edge
The bottom-most edge of the bottom edge of the initial containing block and the bottom margin edge of all of the viewport’s descendants' boxes.
left edge
The left edge of the initial containing block.
top edge
The element’s top padding edge.
right edge
The right-most edge of the element’s right padding edge and the right margin edge of all of the element’s descendants' boxes, excluding boxes that have an ancestor of the element as their containing block.
bottom edge
The bottom-most edge of the element’s bottom padding edge and the bottom margin edge of all of the element’s descendants' boxes, excluding boxes that have an ancestor of the element as their containing block.
left edge
The element’s left padding edge.
leftward and downward
top edge
The top edge of the initial containing block.
right edge
The right edge of the initial containing block.
bottom edge
The bottom-most edge of the bottom edge of the initial containing block and the bottom margin edge of all of the viewport’s descendants' boxes.
left edge
The left-most edge of the left edge of the initial containing block and the left margin edge of all of the viewport’s descendants' boxes.
top edge
The element’s top padding edge.
right edge
The element’s right padding edge.
bottom edge
The bottom-most edge of the element’s bottom padding edge and the bottom margin edge of all of the element’s descendants' boxes, excluding boxes that have an ancestor of the element as their containing block.
left edge
The left-most edge of the element’s left padding edge and the left margin edge of all of the element’s descendants' boxes, excluding boxes that have an ancestor of the element as their containing block.
leftward and upward
top edge
The top-most edge of the top edge of the initial containing block and the top margin edge of all of the viewport’s descendants' boxes.
right edge
The right edge of the initial containing block.
bottom edge
The bottom edge of the initial containing block.
left edge
The left-most edge of the left edge of the initial containing block and the left margin edge of all of the viewport’s descendants' boxes.
top edge
The top-most edge of the element’s top padding edge and the top margin edge of all of the element’s descendants' boxes, excluding boxes that have an ancestor of the element as their containing block.
right edge
The element’s right padding edge.
bottom edge
The element’s bottom padding edge.
left edge
The left-most edge of the element’s left padding edge and the left margin edge of all of the element’s descendants' boxes, excluding boxes that have an ancestor of the element as their containing block.
rightward and upward
top edge
The top-most edge of the top edge of the initial containing block and the top margin edge of all of the viewport’s descendants' boxes.
right edge
The right-most edge of the right edge of the initial containing block and the right margin edge of all of the viewport’s descendants' boxes.
bottom edge
The bottom edge of the initial containing block.
left edge
The left edge of the initial containing block.
top edge
The top-most edge of the element’s top padding edge and the top margin edge of all of the element’s descendants' boxes, excluding boxes that have an ancestor of the element as their containing block.
right edge
The right-most edge of the element’s right padding edge and the right margin edge of all of the element’s descendants' boxes, excluding boxes that have an ancestor of the element as their containing block.
bottom edge
The element’s bottom padding edge.
left edge
The element’s left padding edge.

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.

Document Layout Viewport Visual Viewport

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 Web-exposed available screen area is one of the following:

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:

  1. Abort any ongoing smooth scroll for box.
  2. 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
    ...then perform a smooth scroll of box to position. Once the position has finished updating, emit the scrollend event. Otherwise, perform an instant scroll of box to position. After an instant scroll emit the scrollend event.

    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.

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:

  1. Let doc be the viewport’s associated Document.

  2. Let vv be the VisualViewport whose associated document is doc.

  3. Let maxX be the difference between viewport’s scrolling box’s width and the value of vv’s width attribute.

  4. Let maxY be the difference between viewport’s scrolling box’s height and the value of vv’s height attribute.

  5. Let dx be the horizontal component of position - the value vv’s pageLeft attribute

  6. Let dy be the vertical component of position - the value of vv’s pageTop attribute

  7. Let visual x be the value of vv’s offsetLeft attribute.

  8. Let visual y be the value of vv’s offsetTop attribute.

  9. Let visual dx be min(maxX, max(0, visual x + dx)) - visual x.

  10. Let visual dy be min(maxY, max(0, visual y + dy)) - visual y.

  11. Let layout dx be dx - visual dx

  12. Let layout dy be dy - visual dy

  13. Let element be doc’s root element if there is one, null otherwise.

  14. 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.

  15. 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.

The user pinch-zooms into the document and ticks their mouse wheel, requesting the user agent scroll the document down by 50px. Because the document is pinch-zoomed in, the visual viewport has 20px of room to scroll. The user agent distributes the scroll by scrolling the visual viewport down by 20px and the layout viewport by 30px.
The user is viewing a document in a mobile user agent. The document focuses an offscreen text input element, showing a virtual keyboard which shrinks the visual viewport. The user agent must now bring the element into view in the visual viewport. The user agent scrolls the layout viewport so that the element is visible within it, then the visual viewport so that the element is visible to the user.

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:

  1. Let viewport be the viewport that is associated with document.
  2. Let position be the scroll position viewport would have by aligning the beginning edges of the scrolling area with the beginning edges of viewport.
  3. If position is the same as viewport’s current scroll position, and viewport does not have an ongoing smooth scroll, abort these steps.
  4. 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]

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 behavior = "auto";
};
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 context
    undefined moveTo(long x, long y);
    undefined moveBy(long x, long y);
    undefined resizeTo(long width, long height);
    undefined resizeBy(long x, long y);

    // viewport
    [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 y);

    // client
    [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