<pre class='metadata'>
Title: CSSOM View Module
ED: https://drafts.csswg.org/cssom-view/
TR: https://www.w3.org/TR/cssom-view-1/
Previous Version: https://www.w3.org/TR/2016/WD-cssom-view-1-20160317/
Previous Version: https://www.w3.org/TR/2013/WD-cssom-view-20131217/
Previous Version: https://www.w3.org/TR/2011/WD-cssom-view-20110804/
Previous Version: https://www.w3.org/TR/2009/WD-cssom-view-20090804/
Previous Version: https://www.w3.org/TR/2008/WD-cssom-view-20080222/
Previous Version: https://www.w3.org/TR/2000/REC-DOM-Level-2-Style-20001113/
Group: CSSWG
Status: ED
Work Status: Revising
Shortname: cssom-view
Level: 1
Editor: NOBODY, OOPS!
Former Editor: Simon Pieters, Opera Software AS http://www.opera.com, simonp@opera.com
Former Editor: Glenn Adams, Cox Communications&#44; Inc. http://www.cox.com, glenn.adams@cos.com, http://www.w3.org/wiki/User:Gadams
Former Editor: Anne van Kesteren, Opera Software ASA http://www.opera.com, annevk@annevk.nl, https://annevankesteren.nl/
!Legacy issues list: <a href="https://www.w3.org/Bugs/Public/buglist.cgi?product=CSS&amp;component=CSSOM%20View&amp;resolution=---">Bugzilla</a>
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.
Ignored Terms: open(), EventTarget, EventListener, Event, EventInit, Element, Range, Node, Text
Ignored Vars: rect, point, quad
Include Can I Use Panels: true
Can I Use URL: https://drafts.csswg.org/cssom-view/
Can I Use URL: https://www.w3.org/TR/cssom-view-1/
</pre>

<pre class='anchors'>
urlPrefix: https://html.spec.whatwg.org/multipage/
    urlPrefix: infrastructure.html
        type: dfn; text: html elements
    urlPrefix: browsers.html
        type: interface; text: WindowProxy
        type: dfn
            text: browsing context
            text: auxiliary browsing context
            text: familiar with
            text: associated Document; url: concept-document-window
            text: same origin
            text: active document
    urlPrefix: webappapis.html
        type: dfn
            text: responsible browsing context
            text: incumbent settings object
            text: event handlers
            text: event handler event type
            text: event handler IDL attributes
    urlPrefix: infrastructure.html
        type: dfn
            text: split a string on commas
            text: skip whitespace
            text: collect a sequence of characters
            text: space character
            text: converted to ascii lowercase
            text: rules for parsing integers
urlPrefix: https://drafts.csswg.org/cssom/
    type: dfn
        text: parse a media query list
        text: serialize a media query list
urlPrefix: https://dom.spec.whatwg.org/#
    type: dfn
        text: context object
urlPrefix: https://dom.spec.whatwg.org/#concept-
    type: dfn
        text: event
        text: event listener
        text: quirks mode; url: document-quirks
        text: fire an event; url: event-fire
        text: node document
urlPrefix: https://dom.spec.whatwg.org/
    type: attribute;
        for: Event; urlPrefix: #dom-event-
            text: type
            text: isTrusted
        for: Range; urlPrefix: #dom-range-
            text: startContainer
            text: startOffset
    type: dfn; text: dispatch flag
urlPrefix: https://www.w3.org/TR/CSS21/visuren.html
    type: dfn; text: anonymous block box; url: #anonymous-block-level
urlPrefix: http://heycam.github.io/webidl/
    type: interface; urlPrefix: #idl-
        text: double
        text: long
    type: dfn; text: converted to an IDL value; url: dfn-convert-ecmascript-to-idl-value
url: https://www.w3.org/TR/DOM-Level-3-Events/#interface-MouseEvent; type: interface; text: MouseEvent
url: https://drafts.csswg.org/mediaqueries-4/#mf-colors; type: dfn; text: color media query
</pre>

<pre class='link-defaults'>
spec:css-display-3; type:value; for:display; text:table
spec:css-position-3; type:property; text:position
spec:dom; type:interface; text:Document
spec:html; type:dfn; text:case-sensitive
</pre>

<script src=https://resources.whatwg.org/file-issue.js async data-file-issue-url="https://github.com/w3c/csswg-drafts/issues/new?title=%5Bcssom-view%5D%20"></script>

<h2 id=background>Background</h2>

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
couple of new features that will hopefully be useful to authors. (If they
are not you can bug us!)



<h2 id=terminology>Terminology</h2>

Terminology used in this specification is from
DOM,
CSSOM and
HTML.
[[!DOM]]
[[!CSSOM]]
[[!HTML]]

<dfn>The HTML <code>body</code> element</dfn> is the first
<code>body</code>
<a>HTML element</a> child of the root
<a>HTML element</a> <code>html</code>.

<dfn>Content edge</dfn>, <dfn>padding edge</dfn>, <dfn>border edge</dfn>, <dfn>margin edge</dfn>, and <dfn>viewport</dfn> are defined by CSS.
<!-- These *should* just link to CSS2.1, but it doesn't have actual anchors to link to, because it's THE WORST. -->

Elements and <a>viewports</a> have an associated <dfn export>scrolling box</dfn> if has a scrolling mechanism<!--XXX xref--> or it overflows
its content area<!--XXX xref--> and the used value of the 'overflow-x' or 'overflow-y' property is ''overflow/hidden''. [[!CSS3-BOX]]

An element <var>body</var> (which will be <a>the HTML <code>body</code> element</a>) is
<dfn>potentially scrollable</dfn> if all of the following conditions are true:

* <var>body</var> has an associated <a>CSS layout box</a>.
* <var>body</var>'s <a>parent element</a>'s computed value of the 'overflow-x' or 'overflow-y' properties is neither ''overflow/visible'' nor ''overflow/clip''.
* <var>body</var>'s computed value of the 'overflow-x' or 'overflow-y' properties is neither ''overflow/visible'' nor ''overflow/clip''.

Note: A <{body}> element that is <a>potentially scrollable</a> might not have a <a>scrolling box</a>.
For instance, it could have a used value of 'overflow' being ''overflow/auto'' but not have its content overflowing its content area.

A <a>scrolling box</a> of a <a>viewport</a> or element has two <dfn>overflow directions</dfn>, which are the <a>block-end</a> and <a>inline-end</a> directions for that viewport or element.

The term <dfn>scrolling area</dfn> refers to a box of a <a>viewport</a> or an element that has the following edges, depending on the
<a>viewport’s</a> or element's <a>scrolling box’s</a> <a>overflow directions</a>.

<table class="complex data">
 <thead>
  <tr>
   <th>If the <a>overflow directions</a> are&hellip;
   <th>For a <a>viewport</a>
   <th>For an element
 <tbody>
  <tr>
   <td>rightward and downward
   <td class=long>
    <dl>
     <dt>top edge
     <dd>The top edge of the <a>initial containing block</a>.
     <dt>right edge
     <dd>The right-most edge of the right edge of the <a>initial containing block</a> and the right
     <a>margin edge</a> of all of the <a>viewport’s</a> descendants' boxes.
     <dt>bottom edge
     <dd>The bottom-most edge of the bottom edge of the <a>initial containing block</a> and the
     bottom <a>margin edge</a> of all of the <a>viewport’s</a> descendants' boxes.
     <dt>left edge
     <dd>The left edge of the <a>initial containing block</a>.
    </dl>
   <td class=long>
    <dl>
     <dt>top edge
     <dd>The element's top <a>padding edge</a>.
     <dt>right edge
     <dd>The right-most edge of the element's right <a>padding edge</a> and the right <a>margin
     edge</a> of all of the element's descendants' boxes,
     excluding boxes that have an ancestor of the element as their containing block.
     <dt>bottom edge
     <dd>The bottom-most edge of the element's bottom <a>padding edge</a> and the bottom <a>margin
     edge</a> of all of the element's descendants'
     boxes, excluding boxes that have an ancestor of the element as their containing block.
     <dt>left edge
     <dd>The element's left <a>padding edge</a>.
    </dl>
  <tr>
   <td>leftward and downward
   <td class=long>
    <dl>
     <dt>top edge
     <dd>The top edge of the <a>initial containing block</a>.
     <dt>right edge
     <dd>The right edge of the <a>initial containing block</a>.
     <dt>bottom edge
     <dd>The bottom-most edge of the bottom edge of the <a>initial containing block</a> and the
     bottom <a>margin edge</a> of all of the <a>viewport’s</a> descendants' boxes.
     <dt>left edge
     <dd>The left-most edge of the left edge of the <a>initial containing block</a> and the left
     <a>margin edge</a> of all of the <a>viewport’s</a> descendants' boxes.
    </dl>
   <td class=long>
    <dl>
     <dt>top edge
     <dd>The element's top <a>padding edge</a>.
     <dt>right edge
     <dd>The element's right <a>padding edge</a>.
     <dt>bottom edge
     <dd>The bottom-most edge of the element's bottom <a>padding edge</a> and the bottom <a>margin
     edge</a> of all of the element's descendants' boxes, excluding boxes that have an ancestor of
     the element as their containing block.
     <dt>left edge
     <dd>The left-most edge of the element's left <a>padding edge</a> and the left <a>margin
     edge</a> of all of the element's descendants' boxes, excluding boxes that have an ancestor of
     the element as their containing block.
    </dl>
  <tr>
   <td>leftward and upward
   <td class=long>
    <dl>
     <dt>top edge
     <dd>The top-most edge of the top edge of the <a>initial containing block</a> and the top
     <a>margin edge</a> of all of the <a>viewport’s</a> descendants' boxes.
     <dt>right edge
     <dd>The right edge of the <a>initial containing block</a>.
     <dt>bottom edge
     <dd>The bottom edge of the <a>initial containing block</a>.
     <dt>left edge
     <dd>The left-most edge of the left edge of the <a>initial containing block</a> and the left
     <a>margin edge</a> of all of the <a>viewport’s</a> descendants' boxes.
    </dl>
   <td class=long>
    <dl>
     <dt>top edge
     <dd>The top-most edge of the element's top <a>padding edge</a> and the top <a>margin edge</a>
     of all of the element's descendants' boxes, excluding boxes that have an ancestor of the
     element as their containing block.
     <dt>right edge
     <dd>The element's right <a>padding edge</a>.
     <dt>bottom edge
     <dd>The element's bottom <a>padding edge</a>.
     <dt>left edge
     <dd>The left-most edge of the element's left <a>padding edge</a> and the left <a>margin
     edge</a> of all of the element's descendants' boxes, excluding boxes that have an ancestor of
     the element as their containing block.
    </dl>
  <tr>
   <td>rightward and upward
   <td class=long>
    <dl>
     <dt>top edge
     <dd>The top-most edge of the top edge of the <a>initial containing block</a> and the top
     <a>margin edge</a> of all of the <a>viewport’s</a> descendants' boxes.
     <dt>right edge
     <dd>The right-most edge of the right edge of the <a>initial containing block</a> and the right
     <a>margin edge</a> of all of the <a>viewport’s</a> descendants' boxes.
     <dt>bottom edge
     <dd>The bottom edge of the <a>initial containing block</a>.
     <dt>left edge
     <dd>The left edge of the <a>initial containing block</a>.
    </dl>
   <td class=long>
    <dl>
     <dt>top edge
     <dd>The top-most edge of the element's top <a>padding edge</a> and the top <a>margin edge</a>
     of all of the element's descendants' boxes, excluding boxes that have an ancestor of the
     element as their containing block.
     <dt>right edge
     <dd>The right-most edge of the element's right <a>padding edge</a> and the right <a>margin
     edge</a> of all of the element's descendants' boxes, excluding boxes that have an ancestor of
     the element as their containing block.
     <dt>bottom edge
     <dd>The element's bottom <a>padding edge</a>.
     <dt>left edge
     <dd>The element's left <a>padding edge</a>.
    </dl>
</table>

The <dfn lt="scrolling area origin">origin</dfn> of a <a>scrolling area</a> is
the origin of the <a>initial containing block</a> if the <a>scrolling area</a> is a <a>viewport</a>,
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 <dfn>beginning edges</dfn> of a particular set of edges of a box or element are the following edges:

<dl class=switch>
 <dt>If the <a>overflow directions</a> are rightward and downward
 <dd>The top and left edges.
 <dt>If the <a>overflow directions</a> are leftward and downward
 <dd>The top and right edges.
 <dt>If the <a>overflow directions</a> are leftward and upward
 <dd>The bottom and right edges.
 <dt>If the <a>overflow directions</a> are rightward and upward
 <dd>The bottom and left edges.
</dl>

The <dfn>ending edges</dfn> of a particular set of edges of a box or element are the following edges:

<dl class=switch>
 <dt>If the <a>overflow directions</a> are rightward and downward
 <dd>The bottom and right edges.
 <dt>If the <a>overflow directions</a> are leftward and downward
 <dd>The bottom and left edges.
 <dt>If the <a>overflow directions</a> are leftward and upward
 <dd>The top and left edges.
 <dt>If the <a>overflow directions</a> are rightward and upward
 <dd>The top and right edges.
</dl>

The term <dfn>CSS layout box</dfn> refers to the same term in CSS. 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 <a>CSS layout box</a> (the column or column group, respectively).

The term <dfn>SVG layout box</dfn> refers to the same term in SVG.

<p class=issue>The terms <a>CSS layout box</a> and <a>SVG layout box</a> are not currently defined by CSS or SVG.

The term <dfn>layout box</dfn> refers to either a <a>CSS layout box</a> or an <a>SVG layout box</a>.

The term <dfn>transforms</dfn> 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, string comparisons are done in a <a>case-sensitive</a> manner.


<h3 id=css-pixels>CSS pixels</h3>

All coordinates and dimensions for the APIs defined in this
specification are in <a lt=px value>CSS pixels</a>, unless otherwise specified. [[!CSS-VALUES]]

Note: This does not apply to e.g. {{matchMedia()}} as the units are explicitly given there.


<h3 id=zooming>Zooming</h3>

There are two kinds of zoom, <dfn>page zoom</dfn> which affects the size of the initial viewport<!-- XXX ref -->, and <dfn>pinch zoom</dfn> which acts like
a magnifying glass and does not affect the initial viewport<!-- XXX ref --> or actual viewport<!-- XXX ref -->. [[!CSS-DEVICE-ADAPT]]


<h3 id=web-exposed-screen-information>Web-exposed screen information</h3>

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

* The area of the output device, in <a lt=px value>CSS pixels</a>.
* The area of the <a>viewport</a>, in <a lt=px value>CSS pixels</a>.

The <dfn export>Web-exposed available screen area</dfn> is one of the following:

* The available area of the rendering surface of the output device, in <a lt=px value>CSS pixels</a>.
* The area of the output device, in <a lt=px value>CSS pixels</a>.
* The area of the <a>viewport</a>, in <a lt=px value>CSS pixels</a>.


<h2 id=common-infrastructure>Common Infrastructure</h2>

This specification depends on the WHATWG Infra standard. [[!INFRA]]


<h3 id=scrolling>Scrolling</h3>

When a user agent is to <dfn>perform a scroll</dfn> of a <a>scrolling box</a> <var>box</var>,
to a given position <var>position</var>,
an associated element <var>element</var> and optionally a scroll behavior <var>behavior</var>
(which is "<code>auto</code>" if omitted),
the following steps must be run:

<ol>
 <li><a lt="smooth scroll aborted">Abort</a> any ongoing <a>smooth scroll</a> for <var>box</var>.
 <li>If the user agent honors the 'scroll-behavior' property and one of the following are true:
  <ul>
   <li><var>behavior</var> is "<code>auto</code>" and <var>element</var> is not null and its computed value of the
   'scroll-behavior' property is ''smooth''
   <li><var>behavior</var> is <code>smooth</code>
  </ul>
  ...then perform a <a>smooth scroll</a> of <var>box</var> to <var>position</var>.
  Otherwise, perform an <a>instant scroll</a> of <var>box</var> to <var>position</var>.
</ol>

When a user agent is to perform a <dfn id=concept-smooth-scroll>smooth scroll</dfn> of a <a>scrolling box</a> <var>box</var> to <var>position</var>,
it must update the scroll position of <var>box</var> in a user-agent-defined fashion over a user-agent-defined amount of time. When the scroll is
<dfn lt="smooth scroll completed">completed</dfn>, the scroll position of <var>box</var> must be <var>position</var>. The scroll can also
be <dfn lt="smooth scroll aborted">aborted</dfn>, either by an algorithm or by the user. <!--fingerprint-->

When a user agent is to perform an <dfn id=concept-instant-scroll>instant scroll</dfn> of a <a>scrolling box</a> <var>box</var> to
<var>position</var>, it must update the scroll position of <var>box</var> to <var>position</var>.

To <dfn>scroll to the beginning of the document</dfn> for a document <var>document</var>, follow these steps:

<ol>
 <li>Let <var>viewport</var> be the <a>viewport</a> that is associated with <var>document</var>. <!-- This assumes that there is a viewport, since
 it is only invoked when navigating -->
 <li>Let <var>position</var> be the the scroll position <var>viewport</var> would have by aligning the <a>beginning edges</a> of the
 <a>scrolling area</a> with the <a>beginning edges</a> of <var>viewport</var>.
 <li>If <var>position</var> is the same as <var>viewport</var>'s current scroll position, and <var>viewport</var> does not have an ongoing
 <a>smooth scroll</a>, abort these steps.
 <li><a>Perform a scroll</a> of <var>viewport</var> to <var>position</var>,
 and <var>document</var>'s root element as the associated element, if there is one, or null otherwise.
</ol>

Note: This algorithm is used when navigating to the <code>#top</code> fragment identifier, as defined in HTML. [[!HTML]]


<h3 id=webidl-values>WebIDL values</h3>

When asked to <dfn>normalize non-finite values</dfn> for a value <var>x</var>,
if <var>x</var> is one of the three special floating point literal values
(<code>Infinity</code>, <code>-Infinity</code> or <code>NaN</code>),
then <var>x</var> must be changed to the value <code>0</code>. [[!WEBIDL]]


<h2 id=extensions-to-the-window-interface>Extensions to the {{Window}} Interface</h2>

<pre class=idl>
enum ScrollBehavior { "auto", "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;

    // browsing context
    void moveTo(long x, long y);
    void moveBy(long x, long y);
    void resizeTo(long x, long y);
    void 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;
    void scroll(optional ScrollToOptions options = {});
    void scroll(unrestricted double x, unrestricted double y);
    void scrollTo(optional ScrollToOptions options = {});
    void scrollTo(unrestricted double x, unrestricted double y);
    void scrollBy(optional ScrollToOptions options = {});
    void 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 double devicePixelRatio;
};
</pre>

When the <dfn method for=Window caniuse=matchmedia>matchMedia(<var>query</var>)</dfn> method is invoked these steps must be run:
<ol>
 <li>Let <var>parsed media query list</var> be the result of
 <a lt='parse a media query list'>parsing</a>
 <var>query</var>.
 <li>Return a new {{MediaQueryList}} object,
 with the <a>context object’s</a>
 <a>associated <code>Document</code></a>
 as the <a for=MediaQueryList>document</a>,
 with <var>parsed media query list</var> as its associated <a>media query list</a>.
</ol>

The <dfn attribute for=Window>screen</dfn> attribute must return the {{Screen}} object
associated with the {{Window}} object.

Note: Accessing {{Window/screen}} through a {{WindowProxy}} object might yield different
results when the {{Document}} is navigated.

The <dfn method for=Window>moveTo(<var>x</var>, <var>y</var>)</dfn> method must follow these steps:

1. Optionally, terminate these steps.
1. Let <var>target</var> be the <a>browsing context</a> of the <a>context object</a>.
1. Let <var>source</var> be the <a>responsible browsing context</a> of the <a>incumbent settings object</a>.
1. If <var>source</var> is not <a>allowed to resize and move</a> <var>target</var>, terminate these steps.
1. Optionally, clamp <var>x</var> and <var>y</var> in a user-agent-defined manner so that the window does not move outside the available space.
1. Move <var>target</var>’s window such that the window’s top left corner is at coordinates (<var>x</var>, <var>y</var>) relative to the top left corner of the output device, measured in <a lt=px value>CSS pixels</a> of <var>target</var>. The positive axes are rightward and downward.

The <dfn method for=Window>moveBy(<var>x</var>, <var>y</var>)</dfn> method must follow these steps:

1. Optionally, terminate these steps.
1. Let <var>target</var> be the <a>browsing context</a> of the <a>context object</a>.
1. Let <var>source</var> be the <a>responsible browsing context</a> of the <a>incumbent settings object</a>.
1. If <var>source</var> is not <a>allowed to resize and move</a> <var>target</var>, terminate these steps.
1. Optionally, clamp <var>x</var> and <var>y</var> in a user-agent-defined manner so that the window does not move outside the available space.
1. Move <var>target</var>'s window <var>x</var> <a lt=px value>CSS pixels</a> of <var>target</var> rightward and <var>y</var> <a lt=px value>CSS pixels</a> of <var>target</var> downward.


The <dfn method for=Window>resizeTo(<var>x</var>, <var>y</var>)</dfn> method must follow these steps:

1. Optionally, terminate these steps.
1. Let <var>target</var> be the <a>browsing context</a> of the <a>context object</a>.
1. Let <var>source</var> be the <a>responsible browsing context</a> of the <a>incumbent settings object</a>.
1. If <var>source</var> is not <a>allowed to resize and move</a> <var>target</var>, terminate these steps.
1. Optionally, clamp <var>x</var> and <var>y</var> in a user-agent-defined manner so that the window does not get too small or bigger than the available space.
1. Resize <var>target</var>'s window by moving its right and bottom edges such that the distance between the left and right edges of the viewport are <var>x</var> <a lt=px value>CSS pixels</a> of <var>target</var> and the distance between the top and bottom edges of the viewport are <var>y</var> <a lt=px value>CSS pixels</a> of <var>target</var>.
1. Optionally, move <var>target</var>'s window in a user-agent-defined manner so that it does not grow outside the available space.

The <dfn method for=Window>resizeBy(<var>x</var>, <var>y</var>)</dfn> method must follow these steps:

1. Optionally, terminate these steps.
1. Let <var>target</var> be the <a>browsing context</a> of the <a>context object</a>.
1. Let <var>source</var> be the <a>responsible browsing context</a> of the <a>incumbent settings object</a>.
1. If <var>source</var> is not <a>allowed to resize and move</a> <var>target</var>, terminate these steps.
1. Optionally, clamp <var>x</var> and <var>y</var> in a user-agent-defined manner so that the window does not get too small or bigger than the available space.
1. Resize <var>target</var>'s window by moving its right edge <var>x</var> <a lt=px value>CSS pixels</a> of <var>target</var> rightward and its bottom edge <var>y</var> <a lt=px value>CSS pixels</a> of <var>target</var> downward.
1. Optionally, move <var>target</var>'s window in a user-agent-defined manner so that it does not grow outside the available space.

A <a>browsing context</a> <var>A</var> is <dfn>allowed to resize and move</dfn> a <a>browsing context</a> <var>B</var> if all the following conditions are met:

* <var>B</var> is an <a>auxiliary browsing context</a> that was created by a script (as opposed to by an action of the user).
* <var>A</var> is <a>familiar with</a> <var>B</var>.

The <dfn attribute for=Window>innerWidth</dfn> attribute must return the <a>viewport</a> width including the size of a rendered
scroll bar (if any), or zero if there is no <a>viewport</a>. <!--fingerprint-->

<div class='example'>
    The following snippet shows how to obtain the width of the viewport:

    <pre>var viewportWidth = innerWidth</pre>
</div>

The  <dfn attribute for=Window>innerHeight</dfn> attribute must return the <a>viewport</a> height including the size of a rendered
scroll bar (if any), or zero if there is no <a>viewport</a>. <!--fingerprint-->

The <dfn attribute for=Window>scrollX</dfn> attribute attribute must return the x-coordinate,
relative to the <a>initial containing block</a> origin,
of the left of the <a>viewport</a>,
or zero if there is no <a>viewport</a>. <!--fingerprint-->

The <dfn attribute for=Window>pageXOffset</dfn> attribute must return the value returned by the {{scrollX}} attribute.

The <dfn attribute for=Window>scrollY</dfn> attribute attribute must return the y-coordinate,
relative to the <a>initial containing block</a> origin,
of the top of the <a>viewport</a>,
or zero if there is no <a>viewport</a>. <!--fingerprint-->

The <dfn attribute for=Window>pageYOffset</dfn> attribute must return the value returned by the {{scrollY}} attribute.

When the <dfn method for=Window lt="scroll(options)|scroll(x, y)">scroll()</dfn> method is invoked these
steps must be run:

1. If invoked with one argument, follow these substeps:
    1. Let <var>options</var> be the argument.
    1. Let <var>x</var> be the value of the {{ScrollToOptions/left}} dictionary member of <var>options</var>, if present,
        or the <a>viewport’s</a> current scroll position on the x axis otherwise.
    1. Let <var>y</var> be the value of the {{ScrollToOptions/top}} dictionary member of <var>options</var>, if present,
        or the <a>viewport’s</a> current scroll position on the y axis otherwise.
1. If invoked with two arguments, follow these substeps:
    1. Let <var>options</var> be null <a lt="converted to an IDL value">converted</a> to a {{ScrollToOptions}} dictionary. [[!WEBIDL]]
    1. Let <var>x</var> and <var>y</var> be the arguments, respectively.
1. <a>Normalize non-finite values</a> for <var>x</var> and <var>y</var>.
1. If there is no <a>viewport</a>, abort these steps.
1. Let <var>viewport width</var> be the width of the <a>viewport</a> excluding the width of the scroll bar, if any.
1. Let <var>viewport height</var> be the height of the <a>viewport</a> excluding the height of the scroll bar, if any.
1.
    <dl class=switch>
        <dt>If the <a>viewport</a> has rightward <a>overflow direction</a>
        <dd>Let <var>x</var> be max(0, min(<var>x</var>, <a>viewport</a> <a>scrolling area</a> width - <var>viewport width</var>)).

        <dt>If the <a>viewport</a> has leftward <a>overflow direction</a>
        <dd>Let <var>x</var> be min(0, max(<var>x</var>, <var>viewport width</var> - <a>viewport</a> <a>scrolling area</a> width)).
    </dl>
1.
    <dl class=switch>
        <dt>If the <a>viewport</a> has downward <a>overflow direction</a>
        <dd>Let <var>y</var> be max(0, min(<var>y</var>, <a>viewport</a> <a>scrolling area</a> height - <var>viewport height</var>)).

        <dt>If the <a>viewport</a> has upward <a>overflow direction</a>
        <dd>Let <var>y</var> be min(0, max(<var>y</var>, <var>viewport height</var> - <a>viewport</a> <a>scrolling area</a> height)).
    </dl>
1. Let <var>position</var> be the scroll position the <a>viewport</a> would have
    by aligning the x-coordinate <var>x</var> of the <a>viewport</a> <a>scrolling area</a>
    with the left of the <a>viewport</a>
    and aligning the y-coordinate <var>y</var> of the <a>viewport</a> <a>scrolling area</a>
    with the top of the <a>viewport</a>.
1. If <var>position</var> is the same as the <a>viewport’s</a> current scroll position,
    and the <a>viewport</a> does not have an ongoing <a>smooth scroll</a>, abort these steps.
1. Let <var>document</var> be the <a>viewport’s</a> associated {{Document}}.
1. <a>Perform a scroll</a> of the <a>viewport</a> to <var>position</var>,
    <var>document</var>'s root element as the associated element, if there is one, or null otherwise,
    and the scroll behavior being the value of the {{ScrollOptions/behavior}} dictionary member of <var>options</var>.

When the <dfn method for=Window lt="scrollTo(options)|scrollTo(x, y)">scrollTo()</dfn> method is invoked, the
user agent must act as if the {{Window/scroll()}} method was invoked with the same arguments.

When the <dfn method for=Window lt="scrollBy(options)|scrollBy(x, y)">scrollBy()</dfn> method is invoked, the
user agent must run these steps:

1. If invoked with two arguments, follow these substeps:
    1. Let <var>options</var> be null <a lt="converted to an IDL value">converted</a> to a {{ScrollToOptions}} dictionary. [[!WEBIDL]]
    1. Let <var>x</var> and <var>y</var> be the arguments, respectively.
    1. Let the {{ScrollToOptions/left}} dictionary member of <var>options</var> have the value <var>x</var>.
    1. Let the {{ScrollToOptions/top}} dictionary member of <var>options</var> have the value <var>y</var>.
1. <a>Normalize non-finite values</a> for the {{ScrollToOptions/left}} and {{ScrollToOptions/top}} dictionary members of <var>options</var>.
1. Add the value of {{scrollX}} to the {{ScrollToOptions/left}} dictionary member.
1. Add the value of {{scrollY}} to the {{ScrollToOptions/top}} dictionary member.
1. Act as if the {{Window/scroll()}} method was invoked with <var>options</var> as the only argument.

The <dfn attribute for=Window>screenX</dfn> and <dfn attribute for=Window>screenLeft</dfn> attributes must return the x-coordinate,
relative to the origin of the <a>Web-exposed screen area</a>, of the left of
the client window as number of <a lt=px value>CSS pixels</a>, or zero if there is no such
thing. <!--fingerprint-->

The <dfn attribute for=Window>screenY</dfn> and <dfn attribute for=Window>screenTop</dfn> attributes must return the y-coordinate,
relative to the origin of the screen of the <a>Web-exposed screen area</a>, of the top of
the client window as number of <a lt=px value>CSS pixels</a>, or zero if there is no such
thing. <!--fingerprint-->

The <dfn attribute for=Window>outerWidth</dfn> attribute must return the width of the
client window. If there is no client window this
attribute must return zero. <!--fingerprint-->

The <dfn attribute for=Window>outerHeight</dfn> attribute must return the height of the
client window. If there is no client window this
attribute must return zero. <!--fingerprint-->

The <dfn attribute for=Window caniuse=devicepixelratio>devicePixelRatio</dfn> attribute must return the result of the following <dfn export>determine the device pixel ratio</dfn> algorithm:

1. If there is no output device, return 1 and abort these steps.
1. Let <var>CSS pixel size</var> be the size of a <a lt=px value>CSS pixel</a> at the current <a>page zoom</a> scale factor and at a <a>pinch zoom</a> scale factor of 1.0.
1. Let <var>device pixel size</var> be the vertical size of a device pixel of the output device.
1. Return the result of dividing <var>CSS pixel size</var> by <var>device pixel size</var>.


<h3 id=the-features-argument-to-the-open()-method>The <var ignore>features</var> argument to the {{Window/open()}} method</h3>

HTML defines the {{Window/open()}} method. This section defines behavior for position and size given
in the <var ignore>features</var> argument. [[!HTML]]

To <dfn export>set up browsing context features</dfn> for a browsing context <var>target</var> given a
<a>map</a> <var>tokenizedFeatures</var>:

1. Let <var>x</var> be null.
1. Let <var>y</var> be null.
1. Let <var>width</var> be null.
1. Let <var>height</var> be null.
1. If <var>tokenizedFeatures</var>["<a for="supported open() feature name">left</a>"]
    <a for=map>exists</a>:
    1. Set <var>x</var> to the result of invoking the <a>rules for parsing integers</a> on
        <var>tokenizedFeatures</var>["<a for="supported open() feature name">left</a>"].
    1. If <var>x</var> is an error, set <var>x</var> to 0.
    1. Optionally, clamp <var>x</var> in a user-agent-defined manner so that the window does not
        move outside the <a>Web-exposed available screen area</a>.
    1. Optionally, move <var>target</var>'s window such that the window's left edge is at the
        horizontal coordinate <var>x</var> relative to the left edge of the <a>Web-exposed screen
        area</a>, measured in <a lt=px value>CSS pixels</a> of <var>target</var>. The positive axis is rightward.
1. If <var>tokenizedFeatures</var>["<a for="supported open() feature name">top</a>"]
    <a for=map>exists</a>:
    1. Set <var>y</var> to the result of invoking the <a>rules for parsing integers</a> on
        <var>tokenizedFeatures</var>["<a for="supported open() feature name">top</a>"].
    1. If <var>y</var> is an error, set <var>y</var> to 0.
    1. Optionally, clamp <var>y</var> in a user-agent-defined manner so that the window does not
        move outside the <a>Web-exposed available screen area</a>.
    1. Optionally, move <var>target</var>'s window such that the window's top edge is at the
        vertical coordinate <var>y</var> relative to the top edge of the <a>Web-exposed screen
        area</a>, measured in <a lt=px value>CSS pixels</a> of <var>target</var>. The positive axis is downward.
1. If <var>tokenizedFeatures</var>["<a for="supported open() feature name">width</a>"]
    <a for=map>exists</a>:
    1. Set <var>width</var> to the result of invoking the <a>rules for parsing integers</a> on
        <var>tokenizedFeatures</var>["<a for="supported open() feature name">width</a>"].
    1. If <var>width</var> is an error, set <var>width</var> to 0.
    1. If <var>width</var> is not 0:
        1. Optionally, clamp <var>width</var> in a user-agent-defined manner so that the window does
            not get too small or bigger than the <a>Web-exposed available screen area</a>.
        1. Optionally, size <var>target</var>'s window by moving its right edge such that the
            distance between the left and right edges of the viewport are <var>width</var>
            <a lt=px value>CSS pixels</a> of <var>target</var>.
        1. Optionally, move <var>target</var>'s window in a user-agent-defined manner so that it
            does not grow outside the <a>Web-exposed available screen area</a>.
1. If <var>tokenizedFeatures</var>["<a for="supported open() feature name">height</a>"]
    <a for=map>exists</a>:
    1. Set <var>height</var> to the result of invoking the <a>rules for parsing integers</a> on
        <var>tokenizedFeatures</var>["<a for="supported open() feature name">height</a>"].
    1. If <var>height</var> is an error, set <var>height</var> to 0.
    1. If <var>height</var> is not 0:
        1. Optionally, clamp <var>height</var> in a user-agent-defined manner so that the window
            does not get too small or bigger than the <a>Web-exposed available screen area</a>.
        1. Optionally, size <var>target</var>'s window by moving its bottom edge such that the
            distance between the top and bottom edges of the viewport are <var>height</var>
            <a lt=px value>CSS pixels</a> of <var>target</var>.
        1. Optionally, move <var>target</var>'s window in a user-agent-defined manner so that it
            does not grow outside the <a>Web-exposed available screen area</a>.

A <dfn export>supported <code>open()</code> feature name</dfn> is one of the following:

<dl dfn-for="supported open() feature name" export>
    <dt><dfn>width</dfn>
    <dd>The width of the viewport.

    <dt><dfn>height</dfn>
    <dd>The height of the viewport.

    <dt><dfn>left</dfn>
    <dd>The left position of the window.

    <dt><dfn>top</dfn>
    <dd>The top position of the window.
</dl>


<h3 id=the-mediaquerylist-interface>The {{MediaQueryList}} Interface</h3>

This section integrates with the <a spec=html>event loop</a> defined in HTML. [[!HTML]]

A {{MediaQueryList}} object has an associated <dfn>media query list</dfn>
and an associated <dfn for=MediaQueryList>document</dfn> set on creation.

A {{MediaQueryList}} object has an associated <dfn for=MediaQueryList>media</dfn> which is the
<a lt='serialize a media query list'>serialized</a> form of the associated <a>media query list</a>.

A {{MediaQueryList}} object has an associated <dfn for=MediaQueryList>matches state</dfn> which is
true if the associated <a>media query list</a> matches the state of the <a for=MediaQueryList>document</a>, and false otherwise.

<!--XXX update the matches state when flushing layout (offsetWidth et al), without firing a change event. -->

When asked to <dfn>evaluate media queries and report changes</dfn> for a {{Document}} <var>doc</var>, run these steps:

<ol>

 <li>

  For each {{MediaQueryList}} object <var>target</var> that has <var>doc</var> as its <a for=MediaQueryList>document</a>,
  in the order they were created, oldest first, run these substeps:

  <ol>

   <li>If <var>target</var>'s <a>matches state</a> has changed since the last time these steps were run,
   <a>fire an event</a> at <var>target</var>
   using the {{MediaQueryListEvent}} constructor,
   with its {{Event/type}} attribute initialized to <a event>change</a>,
   its {{Event/isTrusted}} attribute initialized to true,
   its {{MediaQueryList/media}} attribute initialized to <var>target</var>'s <a>media</a>,
   and its {{MediaQueryListEvent/matches}} attribute initialized to <var>target</var>'s <a>matches state</a>. <!--fingerprint-->

  </ol>

</ol>

<div class='example'>
    A simple piece of code that detects changes in the orientation of the viewport can be written as follows:

    <pre highlight=javascript>
    function handleOrientationChange(event) {
        if(event.matches) // landscape
            &hellip;
        else
            &hellip;
    }
    var mql = matchMedia("(orientation:landscape)");
    mql.onchange = handleOrientationChange;
    </pre>
</div>

<pre class=idl>
[Exposed=Window]
interface MediaQueryList : EventTarget {
  readonly attribute CSSOMString media;
  readonly attribute boolean matches;
  void addListener(EventListener? callback);
  void removeListener(EventListener? callback);
           attribute EventHandler onchange;
};
</pre>

The <dfn attribute for=MediaQueryList>media</dfn> attribute must return
the associated <a>media</a>.

The <dfn attribute for=MediaQueryList>matches</dfn> attribute must return
the associated <a>matches state</a>. <!--fingerprint-->

The <dfn method for=MediaQueryList>addListener(<var>callback</var>)</dfn> method,
when invoked, must run these steps:

1. <a spec=dom>Add an event listener</a> with the <a spec=dom>context object</a>
    and an <a spec=dom>event listener</a> whose
    <a spec=dom for="event listener">type</a> is <code>change</code>,
    and <a spec=dom for="event listener">callback</a> is |callback|.

The <dfn method for=MediaQueryList>removeListener(<var>callback</var>)</dfn> method,
when invoked, must run these steps:

1. If the <a spec=dom>context object</a>’s <a spec=dom for=EventTarget>event listener list</a>
    <a for=list>contains</a> an <a>event listener</a> whose
    <a spec=dom for="event listener">type</a> is <code>change</code>,
    <a spec=dom for="event listener">callback</a> is |callback|,
    and <a spec=dom for="event listener">capture</a> is false,
    then <a spec=dom>remove an event listener</a> with
    the <a spec=dom>context object</a> and that <a spec=dom>event listener</a>.

Note: This specification initially had a custom callback mechanism with {{addListener()}} and
{{removeListener()}}, and the callback was invoked with the associated media query list as argument.
Now the normal event mechanism is used instead.
For backwards compatibility, the {{addListener()}} and {{removeListener()}} methods
are basically aliases for {{addEventListener()}} and {{removeEventListener()}}, respectively,
and the <code>change</code> event masquerades as a {{MediaQueryList}}.

The following are the <a>event handlers</a>
(and their corresponding <a>event handler event types</a>) that must be supported,
as <a>event handler IDL attributes</a>, by all objects implementing the {{MediaQueryList}} interface:

<table class="complex data">
 <thead>
  <tr>
   <th><a>Event handler</a>
   <th><a>Event handler event type</a>
 <tbody>
  <tr>
   <td><dfn attribute for=MediaQueryList>onchange</dfn>
   <td><a event>change</a>
</table>

<pre class=idl>
[Exposed=Window,
 Constructor(CSSOMString type, optional MediaQueryListEventInit eventInitDict = {})]
interface MediaQueryListEvent : Event {
  readonly attribute CSSOMString media;
  readonly attribute boolean matches;
};

dictionary MediaQueryListEventInit : EventInit {
  CSSOMString media = "";
  boolean matches = false;
};
</pre>

The <dfn attribute for=MediaQueryListEvent>media</dfn> attribute must return the value it was initialized to.

The <dfn attribute for=MediaQueryListEvent>matches</dfn> attribute must return the value it was initialized to.


<h4 id=mediaquerylist-event-summary>Event summary</h4>

<i>This section is non-normative.</i>

<table class="complex data">
 <thead>
  <tr>
   <th>Event
   <th>Interface
   <th>Interesting targets
   <th>Description
 <tbody>
  <tr>
   <td><dfn event for=MediaQueryList>change</dfn>
   <td>{{Event}}
   <td>{{MediaQueryList}}
   <td>Fired at the {{MediaQueryList}} when the <a>matches state</a> changes.
</table>

<h3 id=the-screen-interface>The {{Screen}} Interface</h3>

As its name suggests, the {{Screen}} interface represents information about the screen of the output device.

<pre class=idl>
[Exposed=Window]
interface Screen {
  readonly attribute long availWidth;
  readonly attribute long availHeight;
  readonly attribute long width;
  readonly attribute long height;
  readonly attribute unsigned long colorDepth;
  readonly attribute unsigned long pixelDepth;
};
</pre>

The <dfn attribute for=Screen>availWidth</dfn> attribute must return the width of the <a>Web-exposed
available screen area</a>. <!--fingerprint-->

The <dfn attribute for=Screen>availHeight</dfn> attribute must return the height of the
<a>Web-exposed available screen area</a>. <!--fingerprint-->

The <dfn attribute for=Screen>width</dfn> attribute must return the width of the <a>Web-exposed
screen area</a>. <!--fingerprint-->

The <dfn attribute for=Screen>height</dfn> attribute must return the height of the <a>Web-exposed
screen area</a>. <!--fingerprint-->

The <dfn attribute for=Screen>colorDepth</dfn> and <dfn attribute
for=Screen>pixelDepth</dfn> attributes should return the number of bits
allocated to colors for a pixel in the output device, excluding the alpha
channel. If the user agent is not able to return the number of bits used by the
output device, it should return the closest estimation such as, for example, the
number of bits used by the frame buffer sent to the display or any internal
representation that would be the closest to the value the output device would
use. The user agent must return a value for these attributes at least equal to
the value of <a>color media query</a> multiplied by three. If the different
color components are not represented with the same number of bits, the returned
value may be greater than three times <a>color media query</a>. If the user
agent does not know the color depth or does not want to return it for privacy
considerations, it should return 24.

Note: The {{colorDepth}} and {{pixelDepth}} attributes return the same value for
compatibility reasons.

Note: Some non-conforming implementations are known to return 32 instead of 24.

<div class='example'>
  <code>colorDepth</code> can be used in the context of selecting SDR/HDR in
  addition with other information. For example, combined with color gamut.

  <pre highlight=javascript>
  if (screen.colorDepth >= 48   && window.matchMedia('(color-gamut: p3)').matches &&
      /* other checks */) {
    // Use HDR content.
  } else {
    // Use SDR content.
  }
  </pre>
</div>

<h2 id=extensions-to-the-document-interface>Extensions to the {{Document}} Interface</h2>

<pre class=idl>
partial interface Document {
  Element? elementFromPoint(double x, double y);
  sequence&lt;Element> elementsFromPoint(double x, double y);
  CaretPosition? caretPositionFromPoint(double x, double y);
  readonly attribute Element? scrollingElement;
};
</pre>

The <dfn method for=Document caniuse=element-from-point>elementFromPoint(<var>x</var>, <var>y</var>)</dfn> method must follow these steps:

1. If either argument is negative, <var>x</var> is greater than the <a>viewport</a> width excluding the size of a rendered scroll bar (if any), or
    <var>y</var> is greater than the <a>viewport</a> height excluding the size of a rendered scroll bar (if any), or there is no <a>viewport</a>
    associated with the document, return null and terminate these steps.
1. If there is a <a>layout box</a> in the <a>viewport</a> that would be a target for hit testing at coordinates <var>x</var>,<var>y</var>,
    when applying the <a>transforms</a> that apply to the descendants of the <a>viewport</a>, return the associated element and terminate these steps.
1. If the document has a root element, return the root element and terminate these steps.
1. Return null.

Note: The {{elementFromPoint()}} method does not necessarily return the top-most painted element. For
instance, an element can be excluded from being a target for hit testing by using the 'pointer-events' CSS property.

<p>
    The <dfn method for=Document>elementsFromPoint(<var>x</var>, <var>y</var>)</dfn> method must follow these steps:

1. Let <var>sequence</var> be a new empty sequence.
1. If either argument is negative, <var>x</var> is greater than the <a>viewport</a> width excluding the size of a rendered scroll bar (if any), or
    <var>y</var> is greater than the <a>viewport</a> height excluding the size of a rendered scroll bar (if any), or there is no <a>viewport</a>
    associated with the document, return <var>sequence</var> and terminate these steps.
1. For each <a>layout box</a> in the <a>viewport</a>, in paint order, starting with the topmost box, that would be a target for hit testing at
    coordinates <var>x</var>,<var>y</var> even if nothing would be overlapping it, when applying the <a>transforms</a> that apply to the descendants of the
    <a>viewport</a>, append the associated element to <var>sequence</var>.
1. If the document has a root element, and the last item in <var>sequence</var> is not the root element, append the root element to <var>sequence</var>.
1. Return <var>sequence</var>.

The <dfn method for=Document>caretPositionFromPoint(<var>x</var>, <var>y</var>)</dfn> method must return the
result of running these steps:

1. If there is no <a>viewport</a> associated with the document, return null.
1. If either argument is negative, <var>x</var> is greater
    than the <a>viewport</a> width excluding the size of a rendered
    scroll bar (if any), <var>y</var> is greater than the
    <a>viewport</a> height excluding the size of a rendered scroll bar
    (if any) return null.
1. If at the coordinates <var>x</var>,<var>y</var>
    in the <a>viewport</a> no text insertion point indicator would have
    been inserted when applying the <a>transforms</a> that apply to the descendants of the <a>viewport</a>, return null.
1. If at the coordinates <var>x</var>,<var>y</var>
    in the <a>viewport</a> a text insertion point indicator would have
    been inserted in a text entry widget which is also a replaced element, when applying the <a>transforms</a> that apply to the descendants of the
    <a>viewport</a>, return a <a>caret position</a> with its properties set as follows:

    <dl>
        <dt><a>caret node</a>
        <dd>The node corresponding to the text entry widget.

        <dt><a>caret offset</a>
        <dd>The amount of 16-bit units to the left of where the
        text insertion point indicator would have inserted.

        <dt><a>caret range</a>
        <dd>null
    </dl>
1. Otherwise, return a <a>caret position</a> where the
    <a>caret range</a> is a collapsed
    {{Range}} object for the position
    where the text insertion point indicator would have been inserted when applying the <a>transforms</a> that apply to the descendants of the
    <a>viewport</a>, and the other properties are set as follows:

    <dl>
        <dt><a>caret node</a>
        <dd>The {{Range/startContainer}}
            of the <a>caret range</a>.

        <dt><a>caret offset</a>
        <dd>The {{Range/startOffset}} of
            the <a>caret range</a>.
    </dl>

Note: The specifics of hit testing are out of scope of this
specification and therefore the exact details of
{{elementFromPoint()}} and {{caretPositionFromPoint()}}
are therefore too. Hit testing will hopefully be defined in a future
revision of CSS or HTML.

<p>The <dfn attribute for=Document>scrollingElement</dfn> attribute, on getting, must run these steps:

1. If the {{Document}} is in <a>quirks mode</a>, follow these substeps:
    1. If <a>the HTML <code>body</code> element</a> exists, and it is not <a>potentially scrollable</a>, return <a>the HTML <code>body</code> element</a> and abort these steps.
    1. Return null and abort these steps.
1. If there is a root element, return the root element and abort these steps.
1. Return null.

Note: For non-conforming user agents that always use the <a>quirks mode</a> behavior for {{Element/scrollTop}}
and {{Element/scrollLeft}}, the {{Document/scrollingElement}} attribute is expected to also always return
<a>the HTML <code>body</code> element</a> (or null if it does not exist).
This API exists so that Web developers can use it to get the right element to use for scrolling APIs,
without making assumptions about a particular user agent's behavior
or having to invoke a scroll to see which element scrolls the viewport.

Note: <a>The HTML <code>body</code> element</a> is different from HTML's <code>document.body</code>
in that the latter can return a <code>frameset</code> element.

<h3 id=the-caretposition-interface>The {{CaretPosition}} Interface</h3>

A <dfn>caret position</dfn> gives the position of a text insertion point indicator. It always has an associated
<dfn>caret node</dfn>, <dfn>caret offset</dfn>, and <dfn>caret range</dfn>. It is represented by a {{CaretPosition}} object.

<pre class=idl>
[Exposed=Window]
interface CaretPosition {
  readonly attribute Node offsetNode;
  readonly attribute unsigned long offset;
  [NewObject] DOMRect? getClientRect();
};
</pre>

The <dfn attribute for=CaretPosition>offsetNode</dfn> attribute must return the <a>caret node</a>.

The <dfn attribute for=CaretPosition>offset</dfn> attribute must return the <a>caret offset</a>.

The <dfn method for=CaretPosition>getClientRect()</dfn> method must follow these steps,
aborting on the first step that returns a value:

1. If <a>caret range</a> is not null:
    1. Let <var>list</var> be the result of invoking the {{Range/getClientRects()}} method on the range.
    1. If <var>list</var> is empty, return null.
    1. Return the {{DOMRect}} object in <var>list</var> at index 0.
1. If <a>caret node</a> is a text entry widget that is a replaced element,
    and that is in the document,
    return a {{DOMRect}} object for the caret in the widget
    as represented by the <a>caret offset</a> value.
    The <a>transforms</a> that apply to the element and its ancestors are applied.
1. Return null.

Note: This {{DOMRect}} object is not <a spec=html>live</a>.

<h2 id=extension-to-the-element-interface>Extensions to the {{Element}} Interface</h2>

<pre class=idl>
enum ScrollLogicalPosition { "start", "center", "end", "nearest" };
dictionary ScrollIntoViewOptions : ScrollOptions {
  ScrollLogicalPosition block = "start";
  ScrollLogicalPosition inline = "nearest";
};

partial interface Element {
  DOMRectList getClientRects();
  [NewObject] DOMRect getBoundingClientRect();
  void scrollIntoView(optional (boolean or ScrollIntoViewOptions) arg = {});
  void scroll(optional ScrollToOptions options = {});
  void scroll(unrestricted double x, unrestricted double y);
  void scrollTo(optional ScrollToOptions options = {});
  void scrollTo(unrestricted double x, unrestricted double y);
  void scrollBy(optional ScrollToOptions options = {});
  void scrollBy(unrestricted double x, unrestricted double y);
  attribute unrestricted double scrollTop;
  attribute unrestricted double scrollLeft;
  readonly attribute long scrollWidth;
  readonly attribute long scrollHeight;
  readonly attribute long clientTop;
  readonly attribute long clientLeft;
  readonly attribute long clientWidth;
  readonly attribute long clientHeight;
};
</pre>

The <dfn method for=Element>getClientRects()</dfn> method, when invoked, must return the result of the following algorithm:

1. If the element on which it was invoked does not have an associated <a>layout box</a> return an empty {{DOMRectList}} object and stop this algorithm.
1. If the element has an associated <a>SVG layout box</a> return a {{DOMRectList}} object containing a single {{DOMRect}} object that describes the bounding box of the element as defined by the SVG specification, applying the <a>transforms</a> that apply to the element and its ancestors.
1. Return a {{DOMRectList}} object containing {{DOMRect}} objects in content order, one for each <a spec=css-break>box fragment</a>, describing its border area (including those with a height or width of zero) with the following constraints:

    * Apply the <a>transforms</a> that apply to the element and its ancestors.
    * If the element on which the method was invoked has a computed value for the 'display' property of ''table'' or ''inline-table'' include both the table box and the caption box, if any, but not the anonymous container box.
    * Replace each <a>anonymous block box</a> with its child box(es) and repeat this until no anonymous block boxes are left in the final list.

Note: The {{DOMRect}} objects returned by {{Element/getClientRects()}} are not <a spec=html>live</a>.

The <dfn method for=Element caniuse=getboundingclientrect>getBoundingClientRect()</dfn> method, when invoked, must return the result of the following
algorithm:

1. Let <var>list</var> be the result of invoking {{Element/getClientRects()}} on the same element this method was invoked on.
1. If the <var>list</var> is empty return a {{DOMRect}} object
    whose {{DOMRect/x}}, {{DOMRect/y}}, {{DOMRect/width}} and {{DOMRect/height}} members are zero.
1. If all rectangles in <var>list</var> have zero width or height, return the first rectangle in
    <var>list</var>.
1. Otherwise, return a {{DOMRect}} object describing the smallest rectangle that includes all
    of the rectangles in <var>list</var> of which the height or width is not zero.

Note: The {{DOMRect}} object returned by {{Element/getBoundingClientRect()}} is not <a spec=html>live</a>.

<div class='example'>
    The following snippet gets the dimensions of the first <code>div</code> element in a document:

    <pre highlight=javascript>
    var example = document.getElementsByTagName("div")[0].getBoundingClientRect();
    var exampleWidth = example.width;
    var exampleHeight = example.height;
    </pre>
</div>

The <dfn method for=Element caniuse=scrollintoview>scrollIntoView(<var>arg</var>)</dfn> method must run these steps:

1. Let <var>behavior</var> be "<code>auto</code>".
1. Let <var>block</var> be "<code>start</code>".
1. Let <var>inline</var> be "<code>nearest</code>".
1. If <var>arg</var> is a {{ScrollIntoViewOptions}} dictionary, then:
    1. Set <var>behavior</var> to the {{ScrollOptions/behavior}} dictionary member of <var>options</var>.
    1. Set <var>block</var> to the {{ScrollIntoViewOptions/block}} dictionary member of <var>options</var>.
    1. Set <var>inline</var> to the {{ScrollIntoViewOptions/inline}} dictionary member of <var>options</var>.
1. Otherwise, if <var>arg</var> is false, then set <var>block</var> to "<code>end</code>".
1. If the element does not have any associated <a>layout box</a>, then return.
1. <a lt='scroll an element into view'>Scroll the element into view</a>
    with <var>behavior</var>, <var>block</var>, and <var>inline</var>.
1. Optionally perform some other action that brings the element to the user's attention.

The <dfn method for=Element lt="scroll(options)|scroll(x, y)">scroll()</dfn> method must run these steps:

1. If invoked with one argument, follow these substeps:
    1. Let <var>options</var> be the argument.
    1. <a>Normalize non-finite values</a> for {{ScrollToOptions/left}} and {{ScrollToOptions/top}} dictionary members of <var>options</var>, if present.
    1. Let <var>x</var> be the value of the {{ScrollToOptions/left}} dictionary member of <var>options</var>, if present, or the element's current scroll position on the x axis otherwise.
    1. Let <var>y</var> be the value of the {{ScrollToOptions/top}} dictionary member of <var>options</var>, if present, or the element's current scroll position on the y axis otherwise.
1. If invoked with two arguments, follow these substeps:
    1. Let <var>options</var> be null <a lt="converted to an IDL value">converted</a> to a {{ScrollToOptions}} dictionary. [[!WEBIDL]]
    1. Let <var>x</var> and <var>y</var> be the arguments, respectively.
    1. <a>Normalize non-finite values</a> for <var>x</var> and <var>y</var>.
    1. Let the {{ScrollToOptions/left}} dictionary member of <var>options</var> have the value <var>x</var>.
    1. Let the {{ScrollToOptions/top}} dictionary member of <var>options</var> have the value <var>y</var>.
1. Let <var>document</var> be the element's <a>node document</a>.
1. If <var>document</var> is not the <a>active document</a>, terminate these steps.
1. Let <var>window</var> be the value of <var>document</var>'s {{Document/defaultView}} attribute.
1. If <var>window</var> is null, terminate these steps.
1. If the element is the root element and <var>document</var> is in <a>quirks mode</a>, terminate these steps.
1. If the element is the root element invoke {{Window/scroll()}} on <var>window</var> with {{Window/scrollX}} on <var>window</var> as first argument and <var>y</var> as second argument,
    and terminate these steps.
1. If the element is <a>the HTML <code>body</code> element</a>,
    <var>document</var> is in <a>quirks mode</a>,
    and the element is not <a>potentially scrollable</a>,
    invoke {{Window/scroll()}} on <var>window</var> with <var>options</var> as the only argument,
    and terminate these steps.
1. If the element does not have any associated <a>CSS layout box</a>,
    the element has no associated <a>scrolling box</a>,
    or the element has no overflow,
    terminate these steps.
1. <a lt='scroll an element'>Scroll the element</a> to <var>x</var>,<var>y</var>,
    with the scroll behavior being the value of the {{ScrollOptions/behavior}} dictionary member of <var>options</var>.

When the <dfn method for=Element lt="scrollTo(options)|scrollTo(x, y)">scrollTo()</dfn> method is invoked, the
user agent must act as if the {{Element/scroll()}} method was invoked with the same arguments.

When the <dfn method for=Element lt="scrollBy(options)|scrollBy(x, y)">scrollBy()</dfn> method is invoked, the
user agent must run these steps:

1. If invoked with one argument, follow these substeps:
    1. Let <var>options</var> be the argument.
    1. <a>Normalize non-finite values</a> for {{ScrollToOptions/left}} and {{ScrollToOptions/top}} dictionary members of <var>options</var>, if present.
1. If invoked with two arguments, follow these substeps:
    1. Let <var>options</var> be null <a lt="converted to an IDL value">converted</a> to a {{ScrollToOptions}} dictionary. [[!WEBIDL]]
    1. Let <var>x</var> and <var>y</var> be the arguments, respectively.
    1. <a>Normalize non-finite values</a> for <var>x</var> and <var>y</var>.
    1. Let the {{ScrollToOptions/left}} dictionary member of <var>options</var> have the value <var>x</var>.
    1. Let the {{ScrollToOptions/top}} dictionary member of <var>options</var> have the value <var>y</var>.
1. Add the value of {{Element/scrollLeft}} to the {{ScrollToOptions/left}} dictionary member.
1. Add the value of {{Element/scrollTop}} to the {{ScrollToOptions/top}} dictionary member.
1. Act as if the {{Element/scroll()}} method was invoked with <var>options</var> as the only argument.

The <dfn attribute for=Element>scrollTop</dfn> attribute, on getting, must return the result of running these steps:

1. Let <var>document</var> be the element's <a>node document</a>.
1. If <var>document</var> is not the <a>active document</a>, return zero and terminate these steps.
1. Let <var>window</var> be the value of <var>document</var>'s {{Document/defaultView}} attribute.
1. If <var>window</var> is null, return zero and terminate these steps.
1. If the element is the root element and <var>document</var> is in <a>quirks mode</a>, return zero and terminate these steps.
1. If the element is the root element return the value of {{Window/scrollY}} on <var>window</var>.
1. If the element is <a>the HTML <code>body</code> element</a>, <var>document</var> is in <a>quirks mode</a>, and the element is not <a>potentially scrollable</a>, return the value of {{Window/scrollY}} on <var>window</var>.
1. If the element does not have any associated <a>CSS layout box</a>, return zero and terminate these steps.
1. Return the y-coordinate of the <a>scrolling area</a> at the alignment point with the top of the <a>padding edge</a> of the element.

When setting the {{Element/scrollTop}} attribute these steps must be run:

1. Let <var>y</var> be the given value.
1. <a>Normalize non-finite values</a> for <var>y</var>.
1. Let <var>document</var> be the element's <a>node document</a>.
1. If <var>document</var> is not the <a>active document</a>, terminate these steps.
1. Let <var>window</var> be the value of <var>document</var>'s {{Document/defaultView}} attribute.
1. If <var>window</var> is null, terminate these steps.
1. If the element is the root element and <var>document</var> is in <a>quirks mode</a>, terminate these steps.
1. If the element is the root element invoke {{Window/scroll()}} on <var>window</var> with {{Window/scrollX}} on <var>window</var> as first argument and <var>y</var> as second argument, and terminate these steps.
1. If the element is <a>the HTML <code>body</code> element</a>, <var>document</var> is in <a>quirks mode</a>, and the element is not <a>potentially scrollable</a>, invoke {{Window/scroll()}} on <var>window</var> with {{Window/scrollX}} as first argument and <var>y</var> as second argument, and terminate these steps.
1. If the element does not have any associated <a>CSS layout box</a>, the element has no associated <a>scrolling box</a>, or the element has no overflow, terminate these steps.
1. <a lt='scroll an element'>Scroll the element</a> to {{Element/scrollLeft}},<var>y</var>, with the scroll behavior being "<code>auto</code>".

The <dfn attribute for=Element>scrollLeft</dfn> attribute, on getting, must return the result of running these steps:

1. Let <var>document</var> be the element's <a>node document</a>.
1. If <var>document</var> is not the <a>active document</a>, return zero and terminate these steps.
1. Let <var>window</var> be the value of <var>document</var>'s {{Document/defaultView}} attribute.
1. If <var>window</var> is null, return zero and terminate these steps.
1. If the element is the root element and <var>document</var> is in <a>quirks mode</a>, return zero and terminate these steps.
1. If the element is the root element return the value of {{Window/scrollX}} on <var>window</var>.
1. If the element is <a>the HTML <code>body</code> element</a>, <var>document</var> is in <a>quirks mode</a>, and the element is not <a>potentially scrollable</a>, return the value of {{Window/scrollX}} on <var>window</var>.
1. If the element does not have any associated <a>CSS layout box</a>, return zero and terminate these steps.
1. Return the x-coordinate of the <a>scrolling area</a> at the alignment point with the left of the <a>padding edge</a> of the element.

When setting the {{Element/scrollLeft}} attribute these steps must be run:

1. Let <var>x</var> be the given value.
1. <a>Normalize non-finite values</a> for <var>x</var>.
1. Let <var>document</var> be the element's <a>node document</a>.
1. If <var>document</var> is not the <a>active document</a>, terminate these steps.
1. Let <var>window</var> be the value of <var>document</var>'s {{Document/defaultView}} attribute.
1. If <var>window</var> is null, terminate these steps.
1. If the element is the root element and <var>document</var> is in <a>quirks mode</a>, terminate these steps.
1. If the element is the root element invoke {{Window/scroll()}} on <var>window</var> with <var>x</var> as first argument and {{Window/scrollY}} on <var>window</var> as second argument, and terminate these steps.
1. If the element is <a>the HTML <code>body</code> element</a>, <var>document</var> is in <a>quirks mode</a>, and the element is not <a>potentially scrollable</a>, invoke {{Window/scroll()}} on <var>window</var> with <var>x</var> as first argument and {{Window/scrollY}} on <var>window</var> as second argument, and terminate these steps.
1. If the element does not have any associated <a>CSS layout box</a>, the element has no associated <a>scrolling box</a>, or the element has no overflow, terminate these steps.
1. <a lt='scroll an element'>Scroll the element</a> to <var>x</var>,{{Element/scrollTop}}, with the scroll behavior being "<code>auto</code>".

The <dfn attribute for=Element>scrollWidth</dfn> attribute must return the result of running these steps:

1. Let <var>document</var> be the element's <a>node document</a>.
1. If <var>document</var> is not the <a>active document</a>, return zero and terminate these steps.
1. Let <var>viewport width</var> be the width of the <a>viewport</a> excluding the width of the scroll bar, if any, or zero if there is no <a>viewport</a>.
1. If the element is the root element and <var>document</var> is not in <a>quirks mode</a> return max(<a>viewport</a> <a>scrolling area</a> width, <var>viewport width</var>).
1. If the element is <a>the HTML <code>body</code> element</a>, <var>document</var> is in <a>quirks mode</a> and the element is not <a>potentially scrollable</a>, return max(<a>viewport</a> <a>scrolling area</a> width, <var>viewport width</var>).
1. If the element does not have any associated <a>CSS layout box</a> return zero and terminate these steps.
1. Return the width of the element's <a>scrolling area</a>.

The <dfn attribute for=Element>scrollHeight</dfn> attribute must return the result of running these steps:

1. Let <var>document</var> be the element's <a>node document</a>.
1. If <var>document</var> is not the <a>active document</a>, return zero and terminate these steps.
1. Let <var>viewport height</var> be the height of the <a>viewport</a> excluding the height of the scroll bar, if any, or zero if there is no <a>viewport</a>.
1. If the element is the root element and <var>document</var> is not in <a>quirks mode</a> return max(<a>viewport</a> <a>scrolling area</a> height, <var>viewport height</var>).
1. If the element is <a>the HTML <code>body</code> element</a>, <var>document</var> is in <a>quirks mode</a> and the element is not <a>potentially scrollable</a>, return max(<a>viewport</a> <a>scrolling area</a> height, <var>viewport height</var>).
1. If the element does not have any associated <a>CSS layout box</a> return zero and terminate these steps.
1. Return the height of the element's <a>scrolling area</a>.

The <dfn attribute for=Element>clientTop</dfn> attribute must run these steps:

1. If the element has no associated <a>CSS layout box</a> or if the <a>CSS layout box</a> is inline, return zero.
1. Return the computed value of the 'border-top-width' property plus the height of any scrollbar rendered between the top <a>padding edge</a> and the top <a>border edge</a>, ignoring any <a>transforms</a> that apply to the element and its ancestors.

The <dfn attribute for=Element>clientLeft</dfn> attribute must run these steps:

1. If the element has no associated <a>CSS layout box</a> or if the <a>CSS layout box</a> is inline, return zero.
1. Return the computed value of the 'border-left-width' property plus the width of any scrollbar rendered between the left <a>padding edge</a> and the left <a>border edge</a>, ignoring any <a>transforms</a> that apply to the element and its ancestors.

The <dfn attribute for=Element>clientWidth</dfn> attribute must run these steps:

1. If the element has no associated <a>CSS layout box</a> or if the <a>CSS layout box</a> is inline, return zero.
1. If the element is the root element and the element's <a>node document</a> is not in <a>quirks mode</a>, or if the element is <a>the HTML <code>body</code> element</a> and the element's <a>node document</a> <em>is</em> in <a>quirks mode</a>, return the <a>viewport</a> width excluding the size of a rendered scroll bar (if any).
1. Return the width of the <a>padding edge</a> excluding the width of any rendered scrollbar between the <a>padding edge</a> and the <a>border edge</a>, ignoring any <a>transforms</a> that apply to the element and its ancestors.

The <dfn attribute for=Element>clientHeight</dfn> attribute must run these steps:

1. If the element has no associated <a>CSS layout box</a> or if the <a>CSS layout box</a> is inline, return zero.
1. If the element is the root element and the element's <a>node document</a> is not in <a>quirks mode</a>, or if the element is <a>the HTML <code>body</code> element</a> and the element's <a>node document</a> <em>is</em> in <a>quirks mode</a>, return the <a>viewport</a> height excluding the size of a rendered scroll bar (if any).
1. Return the height of the <a>padding edge</a> excluding the height of any rendered scrollbar between the <a>padding edge</a> and the <a>border edge</a>, ignoring any <a>transforms</a> that apply to the element and its ancestors.


<h3 id=element-scrolling-members>{{Element}} Scrolling Members</h3>

To <dfn>scroll an element into view</dfn> <var>element</var>,
with a scroll behavior <var>behavior</var>,
a block flow direction position <var>block</var>,
and an inline base direction position <var>inline</var>,
means to run these steps for each ancestor element or <a>viewport</a> that establishes
a <a>scrolling box</a> <var>scrolling box</var>, in order of innermost to outermost <a>scrolling box</a>:

1. If the {{Document}} associated with <var>element</var> is not <a>same origin</a> with the {{Document}} associated with the element or <a>viewport</a> associated with <var>box</var>, terminate these steps.
1. Let <var>element bounding border box</var> be the box that the return value of invoking {{Element/getBoundingClientRect()}} on <var>element</var> represents.
1. Let <var>scrolling box edge A</var> be the <a>beginning edge</a> in the <a>block flow direction</a> of <var>scrolling box</var>, and let <var>element edge A</var> be <var>element bounding border box</var>'s edge on the same physical side as that of <var>scrolling box edge A</var>.
1. Let <var>scrolling box edge B</var> be the <a>ending edge</a> in the <a>block flow direction</a> of <var>scrolling box</var>, and let <var>element edge B</var> be <var>element bounding border box</var>'s edge on the same physical side as that of <var>scrolling box edge B</var>.
1. Let <var>scrolling box edge C</var> be the <a>beginning edge</a> in the <a>inline base direction</a> of <var>scrolling box</var>, and let <var>element edge C</var> be <var>element bounding border box</var>'s edge on the same physical side as that of <var>scrolling box edge C</var>.
1. Let <var>scrolling box edge D</var> be the <a>ending edge</a> in the <a>inline base direction</a> of <var>scrolling box</var>, and let <var>element edge D</var> be <var>element bounding border box</var>'s edge on the same physical side as that of <var>scrolling box edge D</var>.
1. Let <var>element height</var> be the distance between <var>element edge A</var> and <var>element edge B</var>.
1. Let <var>scrolling box height</var> be the distance between <var>scrolling box edge A</var> and <var>scrolling box edge B</var>.
1. Let <var>element width</var> be the distance between <var>element edge C</var> and <var>element edge D</var>.
1. Let <var>scrolling box width</var> be the distance between <var>scrolling box edge C</var> and <var>scrolling box edge D</var>.
1. Let <var>position</var> be the scroll position <var>scrolling box</var> would have by following these steps:

    1. If <var>block</var> is "<code>start</code>", then align <var>element edge A</var> with <var>scrolling box edge A</var>.
    1. Otherwise, if <var>block</var> is "<code>end</code>", then align <var>element edge B</var> with <var>scrolling box edge B</var>.
    1. Otherwise, if <var>block</var> is "<code>center</code>", then align the center of <var>element bounding border box</var> with the center of <var>scrolling box</var> in <var>scrolling box</var>'s <a>block flow direction</a>.
    1. Otherwise, <var>block</var> is "<code>nearest</code>":
        <dl class=switch>
            <dt>If <var>element edge A</var> and <var>element edge B</var> are both outside <var>scrolling box edge A</var> and <var>scrolling box edge B</var>
            <dd>Do nothing.

            <dt>If <var>element edge A</var> is outside <var>scrolling box edge A</var> and <var>element height</var> is less than <var>scrolling box height</var>
            <dt>If <var>element edge B</var> is outside <var>scrolling box edge B</var> and <var>element height</var> is greater than <var>scrolling box height</var>
            <dd>Align <var>element edge A</var> with <var>scrolling box edge A</var>.

            <dt>If <var>element edge A</var> is outside <var>scrolling box edge A</var> and <var>element height</var> is greater than <var>scrolling box height</var>
            <dt>If <var>element edge B</var> is outside <var>scrolling box edge B</var> and <var>element height</var> is less than <var>scrolling box height</var>
            <dd>Align <var>element edge B</var> with <var>scrolling box edge B</var>.
        </dl>
    1. If <var>inline</var> is "<code>start</code>", then align <var>element edge C</var> with <var>scrolling box edge C</var>.
    1. Otherwise, if <var>inline</var> is "<code>end</code>", then align <var>element edge D</var> with <var>scrolling box edge D</var>.
    1. Otherwise, if <var>inline</var> is "<code>center</code>", then align the center of <var>element bounding border box</var> with the center of <var>scrolling box</var> in <var>scrolling box</var>'s <a>inline base direction</a>.
    1. Otherwise, <var>inline</var> is "<code>nearest</code>":
        <dl class=switch>
            <dt>If <var>element edge C</var> and <var>element edge D</var> are both outside <var>scrolling box edge C</var> and <var>scrolling box edge D</var>
            <dd>Do nothing.

            <dt>If <var>element edge C</var> is outside <var>scrolling box edge C</var> and <var>element width</var> is less than <var>scrolling box width</var>
            <dt>If <var>element edge D</var> is outside <var>scrolling box edge D</var> and <var>element width</var> is greater than <var>scrolling box width</var>
            <dd>Align <var>element edge C</var> with <var>scrolling box edge C</var>.

            <dt>If <var>element edge C</var> is outside <var>scrolling box edge C</var> and <var>element width</var> is greater than <var>scrolling box width</var>
            <dt>If <var>element edge D</var> is outside <var>scrolling box edge D</var> and <var>element width</var> is less than <var>scrolling box width</var>
            <dd>Align <var>element edge D</var> with <var>scrolling box edge D</var>.
        </dl>

1. If <var>position</var> is the same as <var>scrolling box</var>'s current scroll position, and <var>scrolling box</var> does not have an ongoing <a>smooth scroll</a>, then return.
1. <dl class=switch>
        <dt>If <var>scrolling box</var> is associated with an element
        <dd>
            Let <var>associated element</var> be the element.

        <dt>If <var>scrolling box</var> is associated with a <a>viewport</a>
        <dd>
            Let <var>document</var> be the <a>viewport’s</a> associated {{Document}}.
            Let <var>associated element</var> be <var>document</var>'s root element, if there is one, or null otherwise.
    </dl>
1. <a>Perform a scroll</a> of <var>scrolling box</var> to <var>position</var>, <var>associated element</var> as the associated element and <var>behavior</var> as the scroll behavior.


To <dfn>scroll an element</dfn> <var>element</var> to <var>x</var>,<var>y</var> optionally with a scroll behavior <var>behavior</var> (which is "<code>auto</code>" if omitted) means to:

1. Let <var>box</var> be <var>element</var>'s associated <a>scrolling box</a>.
1. <dl class=switch>
        <dt>If <var>box</var> has rightward <a>overflow direction</a>
        <dd>Let <var>x</var> be max(0, min(<var>x</var>, <var>element</var> <a>scrolling area</a> width - <var>element</var> <a>padding edge</a> width)).

        <dt>If <var>box</var> has leftward <a>overflow direction</a>
        <dd>Let <var>x</var> be min(0, max(<var>x</var>, <var>element</var> <a>padding edge</a> width - <var>element</var> <a>scrolling area</a> width)).
    </dl>
1. <dl class=switch>
        <dt>If <var>box</var> has downward <a>overflow direction</a>
        <dd>Let <var>y</var> be max(0, min(<var>y</var>, <var>element</var> <a>scrolling area</a> height - <var>element</var> <a>padding edge</a> height)).

        <dt>If <var>box</var> has upward <a>overflow direction</a>
        <dd>Let <var>y</var> be min(0, max(<var>y</var>, <var>element</var> <a>padding edge</a> height - <var>element</var> <a>scrolling area</a> height)).
    </dl>
1. Let <var>position</var> be the scroll position <var>box</var> would have by aligning <a>scrolling area</a> x-coordinate <var>x</var> with the left of <var>box</var> and aligning <a>scrolling area</a> y-coordinate <var>y</var> with the top of <var>box</var>.
1. If <var>position</var> is the same as <var>box</var>'s current scroll position, and <var>box</var> does not have an ongoing <a>smooth scroll</a>, abort these steps.
1. <a>Perform a scroll</a> of <var>box</var> to <var>position</var>, <var>element</var> as the associated element and <var>behavior</var> as the scroll behavior.



<h2 id=extensions-to-the-htmlelement-interface>Extensions to the {{HTMLElement}} Interface</h2>

<pre class=idl>
partial interface HTMLElement {
  readonly attribute Element? offsetParent;
  readonly attribute long offsetTop;
  readonly attribute long offsetLeft;
  readonly attribute long offsetWidth;
  readonly attribute long offsetHeight;
};
</pre>

The <dfn attribute for=HTMLElement>offsetParent</dfn> attribute must return the result of running these steps:

1. If any of the following holds true return null and terminate this algorithm:
    * The element does not have an associated <a>CSS layout box</a>.
    * The element is the root element.
    * The element is <a>the HTML <code>body</code> element</a>.
    * The element's computed value of the 'position' property is ''position/fixed''.
1. Let <var>ancestor</var> be the parent of the element in the <a>flat tree</a> and repeat these substeps:
    1. If <var>ancestor</var> is <a>closed-shadow-hidden</a> from the element and its computed value of the 'position' property is ''position/fixed'', terminate this algorithm and return null.
    1. If <var>ancestor</var> is not <a>closed-shadow-hidden</a> from the element and satisfies at least one of the following, terminate this algorithm and return <var>ancestor</var>.
        * The element is a containing block of absolutely-positioned descendants (regardless of whether there are any absolutely-positioned descendants).
        * It is <a>the HTML <code>body</code> element</a>.
        * The computed value of the 'position' property of the element is ''static'' and the ancestor is one of the following <a>HTML elements</a>: <code>td</code>, <code>th</code>, or <code>table</code>.
    1. If there is no more parent of <var>ancestor</var> in the <a>flat tree</a>, terminate this algorithm and return null.
    1. Let <var>ancestor</var> be the parent of <var>ancestor</var> in the <a>flat tree</a>.

The <dfn attribute for=HTMLElement>offsetTop</dfn> attribute must return the result of running these steps:

1. If the element is <a>the HTML <code>body</code> element</a> or does not have any associated <a>CSS layout box</a> return zero and terminate this algorithm.
1. If the {{HTMLElement/offsetParent}} of the element is null return the y-coordinate of the top <a>border edge</a> of the first <a>CSS layout box</a> associated with the element, relative to the <a>initial containing block</a> origin, ignoring any <a>transforms</a> that apply to the element and its ancestors, and terminate this algorithm.
1. Return the result of subtracting the y-coordinate of the top <a>padding edge</a>
    of the first <a>CSS layout box</a> associated with the {{HTMLElement/offsetParent}} of the element
    from the y-coordinate of the top <a>border edge</a>
    of the first <a>CSS layout box</a> associated with the element,
    relative to the <a>initial containing block</a> origin,
    ignoring any <a>transforms</a> that apply to the element and its ancestors.

    Note: An inline element that consists of multiple line boxes will only have its first <a>CSS layout box</a> considered.

The <dfn attribute for=HTMLElement>offsetLeft</dfn> attribute must return the result of running these steps:

1. If the element is <a>the HTML <code>body</code> element</a> or does not have any associated <a>CSS layout box</a> return zero and terminate this algorithm.
1. If the {{HTMLElement/offsetParent}} of the element is null return the x-coordinate of the left <a>border edge</a> of the first <a>CSS layout box</a> associated with the element, relative to the <a>initial containing block</a> origin, ignoring any <a>transforms</a> that apply to the element and its ancestors, and terminate this algorithm.
1. Return the result of subtracting the x-coordinate of the left <a>padding edge</a> of the first <a>CSS layout box</a> associated with the {{HTMLElement/offsetParent}} of the element from the x-coordinate of the left <a>border edge</a> of the first <a>CSS layout box</a> associated with the element, relative to the <a>initial containing block</a> origin, ignoring any <a>transforms</a> that apply to the element and its ancestors.

The <dfn attribute for=HTMLElement>offsetWidth</dfn> attribute must return the result of running these steps:

1. If the element does not have any associated <a>CSS layout box</a> return zero and terminate this algorithm.
1. Return the <a>border edge</a> width of the first <a>CSS layout box</a> associated with the element, ignoring any <a>transforms</a> that apply to the element and its ancestors.

The <dfn attribute for=HTMLElement>offsetHeight</dfn> attribute must return the result of running these steps:

1. If the element does not have any associated <a>CSS layout box</a> return zero and terminate this algorithm.
1. Return the <a>border edge</a> height of the first <a>CSS layout box</a> associated with the element, ignoring any <a>transforms</a> that apply to the element and its ancestors.


<h2 id=extensions-to-the-htmlimageelement-interface>Extensions to the {{HTMLImageElement}} Interface</h2>

<pre class=idl>
partial interface HTMLImageElement {
  readonly attribute long x;
  readonly attribute long y;
};
</pre>

The <dfn attribute for=HTMLImageElement>x</dfn> attribute, on getting, must return the x-coordinate of the left <a>border edge</a> of the
first <a>CSS layout box</a> associated with the element, relative to the <a>initial containing block</a> origin, ignoring any
<a>transforms</a> that apply to the element and its ancestors, or zero if there is no <a>CSS layout box</a>.

The <dfn attribute for=HTMLImageElement>y</dfn> attribute, on getting, must return the y-coordinate of the top <a>border edge</a> of the
first <a>CSS layout box</a> associated with the element, relative to the <a>initial containing block</a> origin, ignoring any
<a>transforms</a> that apply to the element and its ancestors, or zero if there is no <a>CSS layout box</a>.


<h2 id=extensions-to-the-range-interface>Extensions to the {{Range}} Interface</h2>

<pre class=idl>
partial interface Range {
  DOMRectList getClientRects();
  [NewObject] DOMRect getBoundingClientRect();
};
</pre>

The <dfn method for=Range>getClientRects()</dfn> method, when invoked, must return an empty
{{DOMRectList}} object if the range is not in the document and otherwise a {{DOMRectList}} object
containing a list of {{DOMRect}} objects in content order that matches the following constraints:

* For each element selected by the range, whose parent is not selected by the range, include the border areas returned by invoking {{Element/getClientRects()}} on the element.
* For each {{Text}} node selected or partially selected by the range (including when the
    boundary-points are identical), include a {{DOMRect}} object (for the part that is selected, not
    the whole line box). The bounds of these {{DOMRect}} objects are computed using font metrics;
    thus, for horizontal writing, the vertical dimension of each box is determined by the font
    ascent and descent, and the horizontal dimension by the text advance width. If the range covers
    a partial <a spec=css-text>typographic character unit</a> (e.g. half a surrogate pair or part of
    a grapheme cluster), the full <a spec=css-text>typographic character unit</a> must be included
    for the purpose of computing the bounds of the relevant {{DOMRect}}. [[!CSS-TEXT-3]] The
    <a>transforms</a> that apply to the ancestors are applied.

Note: The {{DOMRect}} objects returned by {{Range/getClientRects()}} are not <a spec=html>live</a>.

The <dfn method for=Range>getBoundingClientRect()</dfn> method, when invoked, must return the result of the following
algorithm:

1. Let <var>list</var> be the result of invoking {{Range/getClientRects()}} on the same range this method was invoked on.
1. If <var>list</var> is empty return a {{DOMRect}} object whose {{DOMRect/x}}, {{DOMRect/y}}, {{DOMRect/width}} and {{DOMRect/height}} members are zero.
1. If all rectangles in <var>list</var> have zero width or height, return the first rectangle in
    <var>list</var>.
1. Otherwise, return a {{DOMRect}} object describing the smallest rectangle that includes all
    of the rectangles in <var>list</var> of which the height or width is not zero.

Note: The {{DOMRect}} object returned by {{Range/getBoundingClientRect()}} is not <a spec=html>live</a>.

<h2 id=extensions-to-the-mouseevent-interface>Extensions to the {{MouseEvent}} Interface</h2>

Issue: The object IDL fragment redefines some members. Can we resolve this somehow?

<!-- x/y do not match IE in the position:relative case but do match other
browsers -->

<pre class=idl>
partial interface MouseEvent {
  readonly attribute double screenX;
  readonly attribute double screenY;
  readonly attribute double pageX;
  readonly attribute double pageY;
  readonly attribute double clientX;
  readonly attribute double clientY;
  readonly attribute double x;
  readonly attribute double y;
  readonly attribute double offsetX;
  readonly attribute double offsetY;
};

partial dictionary MouseEventInit {
  double screenX = 0.0;
  double screenY = 0.0;
  double clientX = 0.0;
  double clientY = 0.0;
};
</pre>

The <dfn attribute for=MouseEvent>screenX</dfn> attribute must return the x-coordinate of
the position where the event occurred relative to the origin of the
<a>Web-exposed screen area</a>.

The <dfn attribute for=MouseEvent>screenY</dfn> attribute must return the y-coordinate of
the position where the event occurred relative to the origin of the
<a>Web-exposed screen area</a>.

The <dfn attribute for=MouseEvent>pageX</dfn> attribute must follow these steps:

1. If the event's <a>dispatch flag</a> is set, return the horizontal coordinate of the position where the event occurred relative to the origin of the <a>initial containing block</a> and terminate these steps.
1. Let <var>offset</var> be the value of the {{Window/scrollX}} attribute of the event's associated {{Window}} object, if there is one, or zero otherwise.
1. Return the sum of <var>offset</var> and the value of the event's {{MouseEvent/clientX}} attribute.

The <dfn attribute for=MouseEvent>pageY</dfn> attribute must follow these steps:

1. If the event's <a>dispatch flag</a> is set, return the vertical coordinate of the position where the event occurred relative to the origin of the <a>initial containing block</a> and terminate these steps.
1. Let <var>offset</var> be the value of the {{Window/scrollY}} attribute of the event's associated {{Window}} object, if there is one, or zero otherwise.
1. Return the sum of <var>offset</var> and the value of the event's {{MouseEvent/clientY}} attribute.

The <dfn attribute for=MouseEvent>clientX</dfn> attribute must return the x-coordinate of
the position where the event occurred relative to the origin of the
<a>viewport</a>.

The <dfn attribute for=MouseEvent>clientY</dfn> attribute must return the y-coordinate of
the position where the event occurred relative to the origin of the
<a>viewport</a>.

The <dfn attribute for=MouseEvent>x</dfn> attribute must return the value of {{MouseEvent/clientX}}.

The <dfn attribute for=MouseEvent>y</dfn> attribute must return the value of {{MouseEvent/clientY}}.

The <dfn attribute for=MouseEvent>offsetX</dfn> attribute must follow these steps:

1. If the event's <a>dispatch flag</a> is set, return the x-coordinate of the position where the event occurred relative to the origin of the <a>padding edge</a> of the target node, ignoring the <a>transforms</a> that apply to the element and its ancestors, and terminate these steps.
1. Return the value of the event's {{MouseEvent/pageX}} attribute.

The <dfn attribute for=MouseEvent>offsetY</dfn> attribute must follow these steps:

1. If the event's <a>dispatch flag</a> is set, return the y-coordinate of the position where the event occurred relative to the origin of the <a>padding edge</a> of the target node, ignoring the <a>transforms</a> that apply to the element and its ancestors, and terminate these steps.
1. Return the value of the event's {{MouseEvent/pageY}} attribute.


<h2 id=geometry>Geometry</h2>

<h3 id="the-geometryutils-interface" class=atrisk>The {{GeometryUtils}} Interface</h3>

<pre class=idl>
enum CSSBoxType { "margin", "border", "padding", "content" };
dictionary BoxQuadOptions {
  CSSBoxType box = "border";
  GeometryNode relativeTo; // XXX default document (i.e. viewport)
};

dictionary ConvertCoordinateOptions {
  CSSBoxType fromBox = "border";
  CSSBoxType toBox = "border";
};

interface mixin GeometryUtils {
  sequence&lt;DOMQuad> getBoxQuads(optional BoxQuadOptions options = {});
  DOMQuad convertQuadFromNode(DOMQuadInit quad, GeometryNode from, optional ConvertCoordinateOptions options = {});
  DOMQuad convertRectFromNode(DOMRectReadOnly rect, GeometryNode from, optional ConvertCoordinateOptions options = {});
  DOMPoint convertPointFromNode(DOMPointInit point, GeometryNode from, optional ConvertCoordinateOptions options = {}); // XXX z,w turns into 0
};

Text includes GeometryUtils; // like Range
Element includes GeometryUtils;
CSSPseudoElement includes GeometryUtils;
Document includes GeometryUtils;

typedef (Text or Element or CSSPseudoElement or Document) GeometryNode;
</pre>

The <dfn method for=GeometryUtils lt="getBoxQuads(options)|getBoxQuads()">getBoxQuads(<var>options</var>)</dfn> method must run the following steps:

<ol>
 <li class=issue>
  DOM order

  p1 = top left even in RTL

  scale to 0 means divide by zero, return 0x0

  cross-frames not allowed, throw WrongDocumentError?

  points are flattened (3d transform), z=0. like getClientRect

  test block in inline

  pseudo-elements before/after are children of the element

  viewport boxes are all the same
</ol>

The <dfn method for=GeometryUtils lt="convertQuadFromNode(quad, from, options)|convertQuadFromNode(quad, from)">convertQuadFromNode(<var>quad</var>, <var>from</var>, <var>options</var>)</dfn> method
must run the following steps:

<ol>
 <li><p class=issue>...
</ol>

The <dfn method for=GeometryUtils lt="convertRectFromNode(rect, from, options)|convertRectFromNode(rect, from)">convertRectFromNode(<var>rect</var>, <var>from</var>, <var>options</var>)</dfn> method
must run the following steps:

<ol>
 <li><p class=issue>...
</ol>

The <dfn method for=GeometryUtils lt="convertPointFromNode(point, from, options)|convertPointFromNode(point, from)">convertPointFromNode(<var>point</var>, <var>from</var>, <var>options</var>)</dfn>
method must run the following steps:

<ol>
 <li><p class=issue>...
</ol>


<h2 id=events>Events</h2>

<h3 id=resizing-viewports>Resizing viewports</h3>

This section integrates with the <a spec=html>event loop</a> defined in HTML. [[!HTML]]

When asked to <dfn>run the resize steps</dfn> for a {{Document}} <var>doc</var>, run these steps:

1. If <var>doc</var>'s <a>viewport</a> has had its width or height changed
    (e.g. as a result of the user resizing the browser window,
    or changing the <span>page zoom</span> scale factor,
    or an <code>iframe</code> element's dimensions are changed)
    since the last time these steps were run,
    <a>fire an event</a> named <a event>resize</a>
    at the {{Window}} object associated with <var>doc</var>.


<h3 id=scrolling-events>Scrolling</h3>

This section integrates with the <a spec=html>event loop</a> defined in HTML. [[!HTML]]

Each {{Document}} has an associated list of <dfn>pending scroll event targets</dfn>, initially empty.

Whenever a <a>viewport</a> gets scrolled (whether in response to user interaction or by an API), the user agent must run these steps:

1. Let <var>doc</var> be the <a>viewport’s</a> associated {{Document}}.
1. If <var>doc</var> is already in <var>doc</var>'s <a>pending scroll event targets</a>, abort these steps.
1. Append <var>doc</var> to <var>doc</var>'s <a>pending scroll event targets</a>.

Whenever an element gets scrolled (whether in response to user interaction or by an API), the user agent must run these steps:

1. Let <var>doc</var> be the element's <a>node document</a>.
1. If the element is already in <var>doc</var>'s <a>pending scroll event targets</a>, abort these steps.
1. Append the element to <var>doc</var>'s <a>pending scroll event targets</a>.

When asked to <dfn>run the scroll steps</dfn> for a {{Document}} <var>doc</var>, run these steps:

1. For each item <var>target</var> in <var>doc</var>'s <a>pending scroll event targets</a>,
    in the order they were added to the list, run these substeps:

    1. If <var>target</var> is a {{Document}}, <a>fire an event</a> named <a event>scroll</a> that bubbles at <var>target</var>.
    1. Otherwise, <a>fire an event</a> named <a event>scroll</a> at <var>target</var>.
1. Empty <var>doc</var>'s <a>pending scroll event targets</a>.


<h3 id=event-summary>Event summary</h3>

<i>This section is non-normative.</i>

<table class="complex data">
 <thead>
  <tr>
   <th>Event
   <th>Interface
   <th>Interesting targets
   <th>Description
 <tbody>
  <tr>
   <td><dfn event for=Window>resize</dfn>
   <td>{{Event}}
   <td>{{Window}}
   <td>Fired at the {{Window}} when the <a>viewport</a> is resized.
  <tr>
   <td><dfn event for="Document, Element">scroll</dfn>
   <td>{{Event}}
   <td>{{Document}}, elements
   <td>Fired at the {{Document}} or element when the <a>viewport</a> or element is scrolled, respectively.
</table>

<h2 id=css-properties>CSS properties</h2>

Issue: The features in this section should be moved to some other specification.

<h3 id=smooth-scrolling caniuse=css-scroll-behavior>Smooth Scrolling: The 'scroll-behavior' Property</h3>

<pre class=propdef>
Name: scroll-behavior
Value: auto | smooth
Initial: auto
Applies to: <a>scrolling boxes</a>
Inherited: no
Computed value:    specified value
Animatable: no
Canonical Order: per grammar
</pre>

The 'scroll-behavior' property specifies the scrolling behavior for a <a>scrolling box</a>,
when scrolling happens due to navigation or CSSOM scrolling APIs.
Any other scrolls, e.g. those that are performed by the user, are not affected by this property.
When this property is specified on the root element, it applies to the <a>viewport</a> instead.

<p class=note>The 'scroll-behavior' property of the HTML <code>body</code> element is <em>not</em> propagated to the viewport.

<dl dfn-type=value dfn-for=scroll-behavior>
 <dt><dfn>auto</dfn>
 <dd>The <a>scrolling box</a> is scrolled in an instant fashion.

 <dt><dfn>smooth</dfn>
 <dd>The <a>scrolling box</a> is scrolled in a smooth fashion using a user-agent-defined timing function over a user-agent-defined period of time. User
 agents should follow platform conventions, if any. <!--fingerprint-->
</dl>

User agents may ignore this property. <!--fingerprint-->

<h2 id='change-history' class="no-num">Change History</h2>

This section documents some of the changes between publications of this specification. This section is not exhaustive. Bug fixes and editorial changes are
generally not listed.


<h3 id='changes-from-2013-12-17' class=no-num>Changes From 17 December 2013</h3>

* The {{Element/scrollIntoView()}} method on {{Element}} was changed and extended.
* The {{Element/scrollTop}} and {{Element/scrollLeft}} IDL attributes on {{Element}} changed to no
    longer take an object; the {{Element/scroll()}}, {{Element/scrollTo()}} and
    {{Element/scrollBy()}} methods were added instead.
* The {{Element/scrollWidth}}, {{Element/scrollHeight}}, {{Element/clientTop}},
    {{Element/clientLeft}}, {{Element/clientWidth}} and {{Element/clientHeight}} IDL attributes on
    {{Element}} were changed back to return integers.
* The <code>DOMRectList</code> interface was removed.
* The {{Document/scrollingElement}} IDL attribute on {{Document}} was added.
* Some readonly attributes on {{Window}} were annotated with <code>[Replaceable]</code> IDL extended
    attribute.
* {{MediaQueryList}}, <a event>scroll</a> event and <a event>resize</a> event are integrated with
    the <a spec=html>event loop</a> in HTML so they are synchronized with animation frames.
* The <code>instant</code> value of 'scroll-behavior' was renamed to ''scroll-behavior/auto''.
* The origin of {{Element/scrollLeft}} on {{Element}} was changed (for RTL).
* The {{Element/scrollIntoView()}} method on {{Element}} and {{Window/scroll()}},
    {{Window/scrollTo()}} and {{Window/scrollBy()}} methods on {{Window}} take the relevant
    dictionary as the first argument.
* The {{MediaQueryList}} interface was changed to use regular event API and define
    {{MediaQueryList/addListener()}} in terms of that.


<h3 id='changes-from-2011-08-04' class=no-num>Changes From 4 August 2011 To 17 December 2013</h3>

* The specification now handles right-to-left and vertical writing modes.
* The specification is now aware of <a>page zoom</a> and <a>pinch zoom</a>.
* The 'scroll-behavior' CSS property is introduced and scrolling APIs are extended with a mechanism to control smooth scrolling.
* The {{Window/moveTo()}}, {{Window/moveBy()}}, {{Window/resizeTo()}} and {{Window/resizeBy()}} methods are now defined.
* {{Window/innerWidth}} et al now use the WebIDL type {{double}} instead of {{long}}.
* {{Window/devicePixelRatio}} is now defined.
* The <code>features</code> argument to <a method for=Window lt="open()">window.open()</a> is now defined.
* The {{Screen/colorDepth}} and {{Screen/pixelDepth}} attributes of {{Screen}} now always return 24.
* The {{Document/elementsFromPoint()}} method of {{Element}} is introduced.
* The specification is now aware of <a>transforms</a>.
* Some geometry utility APIs are introduced but are not yet specified.
* <code>ClientRect</code> has been renamed to {{DOMRect}} and has moved to the Geometry specification. [[GEOMETRY-1]]
* The specification now defines when the <code>resize</code> and <code>scroll</code> events fire.

<h2 id='acks' class="no-num">Acknowledgments</h2>

The editors would like to thank
Alan Stearns,
Alexey Feldgendler,
Antonio Gomes,
Bj&ouml;rn H&ouml;hrmann,
Boris Zbarsky,
Chris Rebert,
Corey Farwell,
Dan Bates,
David Vest,
Elliott Sprehn,
Garrett Smith,
Henrik Andersson,
Hallvord R. M. Steen,
Kang-Hao Lu,
Koji Ishii,
Leif Arne Storset,
Luiz Agostini,
Maciej Stachowiak,
Michael Dyck,
Mike Wilson,
Morten Stenshorne,
Olli Pettay,
Pavel Curtis,
Peter-Paul Koch,
Rachel Kmetz,
Rick Byers,
Robert O'Callahan,
Sam Weinig,
Scott Johnson,
Sebastian Zartner,
Stewart Brodie,
Sylvain Galineau,
Tab Atkins,
Tarquin Wilton-Jones,
Thomas Moore,
Thomas Shinnick,
and
Xiaomei Ji
for their contributions to this document.

Special thanks to the Microsoft employees who first implemented many of
the features specified in this draft, which were first widely deployed by
the Windows Internet Explorer browser.
