Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
87ef4cb
Add definition of the zoom css property
chrishtr Dec 12, 2023
60e6b37
Spell out the complete spec
chrishtr Dec 20, 2023
949b515
none
chrishtr Dec 20, 2023
44b4fdf
Avoid zero
chrishtr Dec 20, 2023
b150914
Further clarifications
chrishtr Dec 20, 2023
75dce70
Add zoom in more places
chrishtr Dec 21, 2023
120441e
Fixes to formatting
chrishtr Jan 4, 2024
aa8c478
Fixes to formatting
chrishtr Jan 4, 2024
abfba55
Replace 'or zoom' with 'unscaled'
chrishtr Jan 4, 2024
11ee897
Fix formatting and add alt text
chrishtr Jan 4, 2024
5c144b6
Shorten notes
chrishtr Jan 4, 2024
ec234ea
Shorten heading
chrishtr Jan 4, 2024
2fdbf35
Add background images
chrishtr Jan 4, 2024
56a6b7d
Omit fenced frames; clarify note about iframes
chrishtr Jan 4, 2024
bf27c4b
Fix spec reference type
chrishtr Jan 4, 2024
0ba0eed
Fix spaces and tabs
chrishtr Jan 4, 2024
78a456c
Fix some lint issues
chrishtr Jan 4, 2024
7b4e3d3
Remove stray character
chrishtr Jan 4, 2024
9471f9d
Remove more 'and zoom'
chrishtr Jan 4, 2024
665e588
fix unscaled
chrishtr Jan 4, 2024
742955c
Fix newlines
chrishtr Jan 4, 2024
a7612a6
Special-case 0 and 0%
chrishtr Jan 10, 2024
9fa4adf
HTMLImageElement.{x,y} should be scaled
chrishtr Jan 12, 2024
65cfc7d
Address code review feedback
chrishtr Jan 17, 2024
51a2dfc
Address code review comments
chrishtr Jan 17, 2024
75ba05b
Fix flat tree
chrishtr Jan 17, 2024
3729a02
Add notes about web compat
chrishtr Jan 17, 2024
8cce793
Fix references that should say 'scaled'
chrishtr Jan 17, 2024
652f315
Clarify effective zoom
chrishtr Jan 17, 2024
1f6d09a
Fix typo
chrishtr Jan 18, 2024
92d9734
Switch to used value instead of computed style
chrishtr Jan 23, 2024
e5a842f
Merge branch 'zoom' of https://github.com/chrishtr/csswg-drafts into …
chrishtr Jan 23, 2024
ce7628c
define used value instead of claiming it as a consequence
chrishtr Jan 23, 2024
993c701
Clarify flat tree ancestors
chrishtr Jan 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions css-viewport/Overview.bs
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,154 @@ only the value previously set to it.
}
</pre>

<h2 id='zoom-property'>
The 'zoom' property</h2>

An element becomes zoomed when the 'zoom' property has a positive computed value
different than 1. 'zoom' affects computed property values and inherited
property values. The computed value of 'zoom' is applied as a scalar to
the used value &lt;length&gt;s CSS properties for the element and
its descendants (including inherited properties such as 'line-height' or
'font-size'), plus intrinsic sizing of
all replaced elements and nested frames, resulting in a magnification or
minification effect.

Nested values of 'zoom' multiply, resulting in additional scaling
of &lt;length&gt; values.

The 'zoom' property has no effect on &lt;length&gt; property values with
computed values that are ''auto'' or &lt;percent&gt;.

<div class="note">Unlike 'transform', scaling the 'zoom' property affects
layout.</div>

<p class="note"> The computed value of 'font-size' is never &lt;percent&gt;
thus 'zoom' always applies.</p>

<p class="note">'zoom' does not affect or prevent 'transform' scaling.</p>

<pre class="propdef">
Name: zoom
Value: &lt;number&gt;
Initial: 1
Applies to: all &lt;length&gt; property values of block-level elements
Inherited: no
Percentages: Refer to all &lt;length&gt; property values
Media: visual
Computed value: as specified
</pre>

The values of this property have the following meanings:

<dl dfn-for="wrap-flow" dfn-type=value>
<dt><dfn lt="'zoom'!!'number'">number</dfn>
<dd>
Positive floating point number indicating a zoom factor. Numbers smaller
than 1.0 indicate a "zoom out" or minification effect, while numbers
greater than 1.0 indicate a "zoom in" or magnification effect.

<dt><dfn lt="'zoom'!!&lt;percent&gt;">percent</dfn>
<dd>
Positive floating point number, followed by a percentage character ("%")
which indicates a zoom factor multiplied by 100.
</dl>

Negative or zero values for 'zoom' are illegal.

<div class="example">
Example of the 'zoom' property applied during hover for magnification effect.

<pre>
&lt;div class="messageBox"&gt;
&lt;div class="label"&gt;Text of the label&lt;/div&gt;
&lt;/div&gt;

&lt;style type="text/css"&gt;
.messageBox {
width: 10em;
padding: 2em;
border: medium solid lightblue;
}

.messageBox:hover {
zoom: 150%;
}

.label {
background: lightgrey;
padding: 1em;
text-align: center;
}
&lt;/style&gt;
</pre>

Illustration of the before and after hover state of the message box element.
<img src="css_zoom_hover_example.png" />
</div>

<div class="example">
Example of nested zoom. In this example, "Inner text" is 4x as large as
"Outer text", and "Middle text" is 2x as large as "Outer text".

<pre>
&lt;div style="zoom: 2"&gt;
Middle text
&lt;div style="zoom: 2"&gt;
Inner text
&lt;div&gt;
&lt;div&gt;
Outer text
</pre>
</div>

<div class="example">
Example of replaced elements. In this example, the image and iframe will
be twice as large as their default sizing.

<pre>
&lt;div style="zoom: 2"&gt;
&lt;img src=""&gt;
&lt;iframe src=""&gt;
&lt;div&gt;
</pre>
</div>

The <dfn>effective zoom</dfn> of an element is the product of its computed
value of 'zoom' and all ancestors' computed values of 'zoom'.

The <dfn>scaled</dfn> value of a CSS length is the used value of that length;
in particular it includes zoom.

The <dfn>unscaled</dfn> value of a CSS length relative to an element is the
<a>scaled</a> value divided by the element's <a>effective zoom</a>.

<div class="note">Zoom applied to an iframe multiplies all its CSS lengths
during layout, but is otherwise invisible to authors except via the observable
width and height of the viewport in CSS units, and via
{{Window/devicePixelRatio}}. In other words, the <a>effective zoom</a> of
elements in an iframe are 1 unless 'zoom' is set on them directly or their
ancestor in the same document.
</div>

<h3 id='dom--cssom-interactions'>
DOM and CSSOM interaction</h3>

Computed style APIs (i.e., all values returned by {{getComputedStyle()}}) that
are non-auto and non-percentage lengths must be <a>unscaled</a>.

The {{Element/getBoundingClientRect}}, {{Element/getClientRects}},
and {{IntersectionObserver}} APIs must return rects with <a>scaled</a>
lengths.

All other APIs related to element geometries must return <a>unscaled</a>
lengths. This is explained in detail in
[[cssom-view#extensions-to-the-htmlelement-interface]].


The {{Window/devicePixelRatio}} of a frame is multiplied by the
<a>effective zoom</a> inherited by its parent frame.
</h3>

<h2 class="no-num" id="changes">Appendix A. Changes</h2>

This appendix is <em>informative</em>.
Expand Down
Binary file added css-viewport/css_zoom_hover_example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 19 additions & 15 deletions cssom-view-1/Overview.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1143,7 +1143,7 @@ aborting on the first step that returns a value:
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.
The <a>transforms</a> and 'zoom' that apply to the element and its ancestors are applied.
1. Return null.

Note: This {{DOMRect}} object is not <a spec=html>live</a>.
Expand Down Expand Up @@ -1190,7 +1190,8 @@ partial interface Element {
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 [=CSS/box=] 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. 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>
and 'zoom' 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.
Expand Down Expand Up @@ -1401,24 +1402,26 @@ The <dfn attribute for=Element>scrollHeight</dfn> attribute must return the resu
The <dfn attribute for=Element>clientTop</dfn> attribute must run these steps:

1. If the element has no associated [=CSS/box=] or if the [=CSS/box=] 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.
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> or 'zoom' 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 [=CSS/box=] or if the [=CSS/box=] 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.
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> or 'zoom' 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 [=CSS/box=] or if the [=CSS/box=] 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 <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.
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> or 'zoom' 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 [=CSS/box=] or if the [=CSS/box=] 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 <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.
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> or 'zoom' that apply to the element and its ancestors.


<h3 id=element-scrolling-members>{{Element}} Scrolling Members</h3>
Expand Down Expand Up @@ -1536,6 +1539,7 @@ The <dfn attribute for=HTMLElement>offsetParent</dfn> attribute must return the
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).
* The element has a non-default used value of 'zoom'.
* It is <a>the <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.
Expand All @@ -1544,29 +1548,29 @@ The <dfn attribute for=HTMLElement>offsetParent</dfn> attribute must return the
The <dfn attribute for=HTMLElement>offsetTop</dfn> attribute must return the result of running these steps:

1. If the element is <a>the <code>body</code> element</a> or does not have any associated [=CSS/box=] 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 [=CSS/box=] 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. If the {{HTMLElement/offsetParent}} of the element is null return the y-coordinate of the top <a>border edge</a> of the first [=CSS/box=] associated with the element, relative to the <a>initial containing block</a> origin, ignoring any <a>transforms</a> 'or zoom' 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 [=CSS/box=] associated with the {{HTMLElement/offsetParent}} of the element
from the y-coordinate of the top <a>border edge</a>
of the first [=CSS/box=] 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.
ignoring any <a>transforms</a> or 'zoom' that apply to the element and its ancestors.

Note: An inline element that consists of multiple line boxes will only have its first [=CSS/box=] considered.

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

1. If the element is <a>the <code>body</code> element</a> or does not have any associated [=CSS/box=] 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 [=CSS/box=] 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 [=CSS/box=] associated with the {{HTMLElement/offsetParent}} of the element from the x-coordinate of the left <a>border edge</a> of the first [=CSS/box=] 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.
1. If the {{HTMLElement/offsetParent}} of the element is null return the x-coordinate of the left <a>border edge</a> of the first [=CSS/box=] associated with the element, relative to the <a>initial containing block</a> origin, ignoring any <a>transforms</a> or 'zoom' 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 [=CSS/box=] associated with the {{HTMLElement/offsetParent}} of the element from the x-coordinate of the left <a>border edge</a> of the first [=CSS/box=] associated with the element, relative to the <a>initial containing block</a> origin, ignoring any <a>transforms</a> or 'zoom' 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 [=CSS/box=] return zero and terminate this algorithm.
1. Return the width of the axis-aligned bounding box
of the [=border boxes=]
of all fragments generated by the element's [=principal box=],
ignoring any <a>transforms</a> that apply to the element and its ancestors.
ignoring any <a>transforms</a> or 'zoom' that apply to the element and its ancestors.

If the element's [=principal box=] is an [=inline-level box=]
which was "split" by a [=block-level=] descendant,
Expand All @@ -1579,7 +1583,7 @@ The <dfn attribute for=HTMLElement>offsetHeight</dfn> attribute must return the
1. Return the height of the axis-aligned bounding box
of the [=border boxes=]
of all fragments generated by the element's [=principal box=],
ignoring any <a>transforms</a> that apply to the element and its ancestors.
ignoring any <a>transforms</a> or 'zoom' that apply to the element and its ancestors.

If the element's [=principal box=] is an [=inline-level box=]
which was "split" by a [=block-level=] descendant,
Expand All @@ -1598,11 +1602,11 @@ partial interface HTMLImageElement {

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 [=CSS/box=] 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 [=CSS/box=].
<a>transforms</a> or 'zoom' that apply to the element and its ancestors, or zero if there is no [=CSS/box=].

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 [=CSS/box=] 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 [=CSS/box=].
<a>transforms</a> or 'zoom' that apply to the element and its ancestors, or zero if there is no [=CSS/box=].


<h2 id=extensions-to-the-range-interface>Extensions to the {{Range}} Interface</h2>
Expand All @@ -1627,7 +1631,7 @@ containing a list of {{DOMRect}} objects in content order that matches the follo
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.
<a>transforms</a> and 'zoom' that apply to the ancestors are applied.

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

Expand Down