diff --git a/README.markdown b/README.markdown
index 6c6c65263288..6752c4feaf35 100644
--- a/README.markdown
+++ b/README.markdown
@@ -5,15 +5,14 @@ This is the official CSSWG repository for editor's drafts of CSS specifications.
See the [contributor guidelines](CONTRIBUTING.md) for how to contribute.
Specification issues are discussed as issues in this repository.
-General CSSWG discussion can be found on the public
+
+Minutes of CSSWG discussion can be found on the public
[www-style mailing list](https://lists.w3.org/Archives/Public/www-style/).
To read the specifications in this repository, see them at the
[index of all specifications](https://drafts.csswg.org/).
-This repository is a two-way mirror of https://hg.csswg.org/drafts, and
-contributing using Mercurial is also possible.
Also see the related repositories:
-* [fxtf-drafts github repository](https://github.com/w3c/fxtf-drafts/) - [fxtf mercurial repository](https://hg.fxtf.org/drafts/) - [FX Task Force generated specification index](https://drafts.fxtf.org/)
-* [css-houdini-drafts github repository](https://github.com/w3c/css-houdini-drafts/) - [css-houdini mercurial repository](https://hg.css-houdini.org/drafts/) - [CSS-TAG Houdini Task Force generated specification index](https://drafts.css-houdini.org/)
+* [fxtf-drafts github repository](https://github.com/w3c/fxtf-drafts/) - [FX Task Force generated specification index](https://drafts.fxtf.org/)
+* [css-houdini-drafts github repository](https://github.com/w3c/css-houdini-drafts/) - [CSS-TAG Houdini Task Force generated specification index](https://drafts.css-houdini.org/)
diff --git a/css-2020/Overview.bs b/css-2020/Overview.bs
index 66c83809a0c8..5c61be9f60b7 100644
--- a/css-2020/Overview.bs
+++ b/css-2020/Overview.bs
@@ -4,8 +4,7 @@ Shortname: css-2020
Level: none
Status: ED
Group: CSSWG
-Date: 2020-12-21
-Prepare for TR: yes
+Prepare for TR: no
Work Status: revising
URL: https://drafts.csswg.org/css-2020/
TR: https://www.w3.org/TR/css-2020/
diff --git a/css-2022/Overview.bs b/css-2022/Overview.bs
index c7a013d108d5..ba4a53be0dce 100644
--- a/css-2022/Overview.bs
+++ b/css-2022/Overview.bs
@@ -2,9 +2,8 @@
Title: CSS Snapshot 2022
Shortname: css-2022
Level: none
-Status: NOTE-FPWD
-Date: 2022-11-22
-Prepare for TR: yes
+Status: ED
+Prepare for TR: no
Group: CSSWG
Work Status: revising
URL: https://drafts.csswg.org/css-2022/
diff --git a/css-2023/Overview.bs b/css-2023/Overview.bs
index 3b37deba34bd..696e4cba3419 100644
--- a/css-2023/Overview.bs
+++ b/css-2023/Overview.bs
@@ -2,9 +2,8 @@
Title: CSS Snapshot 2023
Shortname: css-2023
Level: none
-Status: NOTE
-Prepare for TR: yes
-Date: 2023-12-07
+Status: ED
+Prepare for TR: no
Group: CSSWG
Work Status: revising
URL: https://drafts.csswg.org/css-2023/
diff --git a/css-2024/Overview.bs b/css-2024/Overview.bs
index 3a33e35a3384..78f28348ea55 100644
--- a/css-2024/Overview.bs
+++ b/css-2024/Overview.bs
@@ -2,9 +2,8 @@
Title: CSS Snapshot 2024
Shortname: css-2024
Level: none
-Status: NOTE
-Prepare for TR: yes
-Date: 2025-02-25
+Status: ED
+Prepare for TR: no
Group: CSSWG
Work Status: revising
URL: https://drafts.csswg.org/css-2024/
diff --git a/css-2025/Overview.bs b/css-2025/Overview.bs
index 4fb2b6e5c576..4f1c16c1e445 100644
--- a/css-2025/Overview.bs
+++ b/css-2025/Overview.bs
@@ -2,7 +2,7 @@
Title: CSS Snapshot 2025
Shortname: css-2025
Level: none
-Status: NOTE
+Status: ED
Prepare for TR: no
Group: CSSWG
Work Status: revising
@@ -357,7 +357,7 @@ Classification of CSS Specifications
and/or the CSS Working Group Blog
for any resulting changes, corrections, or clarifications.
-
+
Reliable Candidate Recommendations
The following specifications are considered to be in a reliable state, meaning they have largely stable implementations and specifications, but are not yet at the Recommendation level due to minor issues or the need for additional implementation reports.
@@ -395,6 +395,22 @@ The following specifications are considered to be in a reliable state, meaning t
Extends and supersedes [[CSS-GRID-1]],
introducing “subgrids” for managing nested markup in a shared grid framework.
+
+
+ Extends and supersedes [[CSS-CASCADE-4]],
+ introducing cascade layers which provide a structured way to organize and balance concerns within a single origin.
+
+
+ This module introduces a model and controls over automatic color adjustment by the user agent to handle user preferences and device output optimizations.
+
+
- This module introduces a model and controls over automatic color adjustment by the user agent to handle user preferences and device output optimizations.
-
-
+ This module defines APIs for querying and manipulating
+ the visual viewport and layout viewport,
+ as well as methods for scrolling elements into view.
@@ -935,6 +948,23 @@ Safe to Release pre-CR Exceptions
The [=relative color=] syntax, defined in [[!CSS-COLOR-5]]
The [[CSS-VALUES-5#request-url-modifiers|request url modifiers]], defined in [[!CSS-VALUES-5]]
+
+
The [[MEDIAQUERIES-5#display-modes|display-modes]],
+ [[MEDIAQUERIES-5#dynamic-range|dynamic-range]],
+ [[MEDIAQUERIES-5#scripting|scripting]],
+ [[MEDIAQUERIES-5#prefers-reduced-motion|prefers-reduced-motion]],
+ [[MEDIAQUERIES-5#prefers-reduced-transparency|prefers-reduced-transparency]],
+ [[MEDIAQUERIES-5#prefers-contrast|prefers-contrast]],
+ [[MEDIAQUERIES-5#forced-colors|forced-colors]],
+ and [[MEDIAQUERIES-5#prefers-color-scheme|prefers-color-scheme]],
+ media features, defined in [[!MEDIAQUERIES-5]]
+
+
The [[CSS-CONDITIONAL-5#at-supports-ext|font-tech()]] and [[CSS-CONDITIONAL-5#at-supports-ext|font-format()]] functions, defined in [[!CSS-CONDITIONAL-5]]
+
+
The '':is()'', '':where()'', and '':has()'' pseudo-classes,
+ and selector lists in '':not()'', defined in [[!SELECTORS-4]]
+
+
The 'text-decoration-thickness' and 'text-underline-offset' properties and the from-font value for 'text-underline-position', defined in [[!CSS-TEXT-DECOR-4]]
The following features have been explicitly and retroactively cleared
diff --git a/css-align-3/Overview.bs b/css-align-3/Overview.bs
index 3d06f9b04cb4..dba512560204 100644
--- a/css-align-3/Overview.bs
+++ b/css-align-3/Overview.bs
@@ -898,7 +898,7 @@ Content Distribution for Scroll Containers
Self-Alignment for Absolutely Positioned Boxes
For [=absolutely positioned=] [=alignment subjects=]
- whose relevant [=self-alignment property=] is not ''justify-self/normal'',
+ whose relevant [=used value|used=] [=self-alignment property=] is not ''justify-self/normal'',
the default [=overflow alignment=] behavior is as follows:
@@ -918,6 +918,12 @@ Self-Alignment for Absolutely Positioned Boxes
For this purpose, the |overflow limit rect| is the bounding rectangle
of the [=alignment subject's=] [=inset-modified containing block=]
and its [=original containing block=].
+ However, because the [=scrollable overflow area=] of a [=scroll container=]
+ can be extended to ensure the visibility of overflowing [=absolutely positioned=] boxes,
+ if the [=original containing block=] is generated by a [=scroll container=]
+ (and is not its [=fixed containing block=]),
+ the |overflow limit rect| is extended to infinity
+ in any direction that does not extend into the [=unreachable scrollable overflow region=].
(For [=absolutely-positioned=] [=alignment subjects=] that fail the above condition,
@@ -1157,7 +1163,7 @@ Content-Distribution Shorthand: the 'place-content' property
Name: place-content
Value: <<'align-content'>> <<'justify-content'>>?
Initial: normal
- Applies to: block containers, flex containers, and grid containers
+ Applies to: see individual properties
Inherited: no
Percentages: n/a
Computed value: see individual properties
@@ -1764,7 +1770,7 @@ Self-Alignment Shorthand: the 'place-self' property
Name: place-self
Value: <<'align-self'>> <<'justify-self'>>?
Initial: auto
- Applies to: block-level boxes, absolutely-positioned boxes, and grid items
+ Applies to: see individual properties
Inherited: no
Percentages: n/a
Computed value: see individual properties
@@ -1961,7 +1967,7 @@ Block-Axis (or Cross-Axis) Default Alignment: the 'align-items' property
Name: align-items
- Value: normal | stretch | <> | [ <>? <> ]
+ Value: normal | stretch | <> | <>? <>
Initial: normal
Applies to: all elements
Inherited: no
@@ -2064,7 +2070,7 @@ Row and Column Gutters: the 'row-gap' and 'column-gap' properties
see [[#gap-percent]].
: normal
- :: The ''gap/normal'' represents
+ :: The value ''gap/normal'' represents
a used value of ''1em'' on multi-column containers,
and a used value of ''0px'' in all other contexts.
@@ -2252,8 +2258,8 @@ Determining the Baselines of a Box
block containers
The first/last [=baseline set=] of a block container
- is taken from the first/last in-flow line box in the block container
- or the first/last in-flow block-level child in the block container
+ is taken from the first/last [=in-flow=] line box in the block container
+ or the first/last [=in-flow=] block-level child in the block container
that contributes a set of first/last baselines,
whichever comes first/last.
If there is no such line box or child,
@@ -2349,7 +2355,7 @@ Determining the Baselines of a Box
and ''vertical-rl'' if 'direction' is ''rtl''.
For the purposes of finding the baselines of a box,
- it and all its in-flow descendants with a scrolling mechanism (see the 'overflow' property)
+ it and all its [=in-flow=] descendants with a scrolling mechanism (see the 'overflow' property)
must be considered as if scrolled to their initial scroll position.
Additionally,
if the position of a [=scroll container=]’s first/last baseline
@@ -2514,175 +2520,13 @@ Appendix A: Static Position Terminology
Made [=block containers=] default to ''safe'' alignment.
- See [[#auto-safety-default]].
- (Issue 8992)
-
Made [=absolutely positioned boxes=] default to using a “smart” safe alignment
- that allows unsafe overflow of the [=inset-modified containing block=]
- while maintaining safety within the [=original containing block=].
- See [[#auto-safety-position]].
- (Issue 10316,
- Issue 9960)
-
Make all the ''space-*'' keywords fallback to ''safe'' overflow.
- (Issue 10154)
-
Clearly define the interaction of overflowing [=content distribution=] and [=scroll containers=]
- to not impact layout, but to only affect the extent of the [=scrollable overflow area=].
- (Issue 4957)
-
Only apply the special margin-edge baseline rule for [=scroll container=] [=block containers=]
- when 'baseline-source' is its [=initial value=].
- (Issue 8214)
-
When synthesizing the baseline of an orthogonal-flow box,
- make the assumed parallel [=writing mode=] sensitive to 'direction'.
- (Issue 7775)
-
-
Otherwise,
- assume either ''horizontal-tb'' or ''vertical-lr'' 'writing-mode',
- whichever is orthogonal to the box’s own 'writing-mode'.
-
Otherwise:
-
-
If the box’s own [=writing mode=] is vertical,
- assume ''horizontal-tb''.
-
If the box’s own [=writing mode=] is horizontal,
- assume ''vertical-lr'' if 'direction' is ''ltr''
- and ''vertical-rl'' if 'direction' is ''rtl''.
-
-
-
-
Clarify that spanning cells only participate in the first/last row they span
- when participating in first/last baseline alignment.
- (Issue 7655)
-
Define the 'grid-gap' properties as [=legacy name aliases=] of the 'gap' properties.
- (Issue 8014)
-
Defer definition of ''align-self/normal'' alignment for [=absolutely positioned boxes=] to [[css-position-3]].
- (Issue 11215,
- Issue 11285)
-
Changed sentence about applicability of 'row-gap' to [=multi-column containers=]
- to indicate that it applies in [[CSS-MULTICOL-2]].
- (Issue 11539)
-
Defined that [=gutters=] dissappear at [=fragmentation breaks=].
- (Issue 11520)
-
Define the baselines of a [=multi-column container=].
- (Issue 7856,
- Issue 7639)
-
Use the [=writing mode=] of the [=static-position containing block=]
- when determining the [=static position=].
- (Issue 7599,
- Issue 7612;
- Changes)
-
Remove definition of special behavior for including padding in [=scrollable overflow=]
- for non-''align-content/normal'' alignments
- since this is now defined unconditionally in [[!CSS-OVERFLOW-3]].
- (Issue 129)
-
Minor clarifications:
- * Define [=fallback alignment=] of a [=baseline-sharing group=]
- as the shared [=fallback alignment=] of its individual items.
- * Annotate <> value definitions using [=CSS bracketed range notation=].
-
Allowed reordering of ''[ first | last ]'' and ''align-self/baseline'' components of <>.
- (Issue 5235)
-
Make [=fallback alignment=] of ''space-around'' and ''space-evenly'' include ''safe''.
- (Issue 5088)
-
Various corrections to normal alignment and percentage gaps
- to match respective layout specs.
-
Corrections to special legacy handling of the [=last baseline set=] of [=scroll containers=].
- (Issue 3611)
-
Clarify that a box with no [=baseline set=] synthesizes its [=alignment baseline=] as needed.
- (Issue 3611)
-
Clarified that only non-replaced boxes are affected by [=content distribution=].
- (Issue 4545)
-
Clarified when a box has a [=coordinated self-alignment preference=]
- that enables [=baseline content-alignment=],
- particularly with respect to ''margin/auto'' [=margins=].
- (Issue 5923)
-
Better define how baseline self-alignment and content-alignment interact.
- (Issue 6389)
-
Clarify how baseline-sharing groups determine their fallback alignment.
- (Issue 7645)
-
+ Changes since the 11 March 2025 Working Draft include:
+ * Clarify that [[#auto-safety-position]] applies when 'position-area' alters the [=used value=] of ''align-self/normal''.
+ * Allow absolutely positioned boxes to honor alignment even when overflowing into
+ the scrollable overflow area of a scroll container containing block.
+ (Issue 12106)
- Changes since the 6 December 2018 Working Draft include:
-
-
Improved the center self-alignment of absolutely-positioned elements.
- Issue 4659
-
Fixed inconsistent fallback of baseline alignment in mixed writing modes.
- Issue 3454
-
Better definition of how the alignment properties interact with absolutely-positioned boxes with ''left/auto'' offsets.
- See [[#justify-abspos]], [[#align-abspos]], [[#abspos-sizing]], and [[#staticpos-rect]].
-
Added the 'row-gap' and 'column-gap' properties and 'gap' shorthand,
- applying them to both grid layout and flex layout
- to replace the grid-specific 'grid-row-gap'/'grid-column-gap'/'grid-gap' properties.
-
Dropped the ''left'' and ''right'' keywords from 'align-self' and 'align-content'.
- They may be re-introduced in a later level if there is demand.
- (Issue 1403)
-
Assigned ''end'' fallback alignment to ''align-self/stretch'' cases when combined with ''last baseline'' content-alignment.
-
Disabled baseline alignment across cells in a table column,
- due to implementation complexity.
-
-Title: CSS Anchor Positioning
+Title: CSS Anchor Positioning Module Level 1
Shortname: css-anchor-position
Level: 1
Status: ED
@@ -110,6 +110,23 @@ to find the “best” one that avoids overlap/overflow.
max-inline-size: 20em;
}
+
+ Note that using the [[HTML#the-popover-attribute|Popover API]]
+ will automatically set 'position' and create the anchoring relationship
+ without setting 'anchor-name' or 'position-anchor' value
+ (by defining an [=implicit anchor element=]),
+ so those properties wouldn't need to be explicitly set again.
+ So with the correct markup, this example can be simplified to:
+
+
+ .tooltip {
+ /* Using the popover + popovertarget attributes sets 'position: fixed'
+ and creates the necessary position-anchor relationship already. */
+ position-area: block-start;
+ position-try: flip-block;
+ max-inline-size: 20em;
+ }
+
@@ -156,7 +173,7 @@ Animation Type: discrete
The 'anchor-name' property declares
that an element is an anchor element,
-whose [=principal box=] is an anchor box,
+whose [=principal box=] is an [=anchor box=],
and gives it a list of anchor names to be targeted by.
Values are defined as follows:
@@ -168,7 +185,7 @@ Values are defined as follows:
:: If the element generates a [=principal box=],
the element is an [=anchor element=],
with a list of [=anchor names=] as specified.
- Each [=anchor name=] is a [=tree-scoped name=].
+ Each [=anchor name=] is a [=tree-scoped name/loosely matched=] [=tree-scoped name=].
Otherwise, the property has no effect.
@@ -195,6 +212,11 @@ Note: While an element is in the [=skipped contents=] of another element
it's not an [=acceptable anchor element=],
effectively acting as if it had no names.
+Note: Positioned elements in [=shadow trees=]
+can reference [=anchor names=] defined in “higher” trees.
+Currently, they cannot reference [=anchor names=]
+defined in “lower” shadow trees, though.
+
### Implicit Anchor Elements ### {#implicit}
Some specifications can define that,
@@ -214,20 +236,37 @@ The [=implicit anchor element=] of a [=pseudo-element=]
is its [=originating element=],
unless otherwise specified.
-### The Anchor's Position ### {#determining-position}
-
-Several features of this specification refer to the position and size of an [=anchor box=].
-The [=anchor box=]'s position and size is determined after layout,
-and for these purposes
-includes 'position'-based adjustments
-(such as ''position: relative'' or ''position: sticky'').
+### The Anchor Box ### {#anchor-position-size}
+
+Several features of this specification refer to the position and size of an anchor box.
+Unless otherwise specified,
+this refers to the [=border box=] edge of the [=principal box=] of the [=anchor element=].
+The [=anchor box=]'s position and size is determined after layout.
+
+This position and size includes 'zoom' and 'position'-based adjustments
+(such as ''position: relative'' or ''position: sticky'')
+as well as transforms (such as 'transform' or 'offset-path').
+In these cases, the axis-aligned bounding rectangle of the [=anchor box=]
+in the coordinate space of the [=absolutely positioned=] element's [=containing block=]
+is used instead.
+Transforms are often optimized onto a different thread,
+so transform-based updates to an [=anchor box’s=] position
+may be delayed by a few frames.
+Authors can avoid this delay by using absolute or relative positioning instead where practical.
+
+If the [=anchor box=] is [=fragmented=],
+and the [=containing block=] of the [=absolutely positioned=] box
+referring to that [=anchor box=] is outside the relevant [=fragmentation context=],
+the axis-aligned bounding rectangle of its [=box fragments=] is used instead.
+(If the [=absolutely positioned=] box is inside the [=fragmentation context=],
+it sees the [=anchor box=] as unfragmented--
+and can be itself fragmented by the [=fragmentation context=].)
-Post-layout effects, such as 'transform',
+For performance reasons,
+scrolling is handled specially, see [[#scroll]].
+Other post-layout effects, such as filters,
do not affect the [=anchor box's=] position.
-Note: Allowing an anchor to opt into including the effects of 'transform'
-or similar properties
-might be allowed in the future.
-
-Centering on the Anchor: the ''anchor-center'' alignment value {#anchor-center}
---------------------------------------------------------------
-
-
-
-The [=self-alignment properties=] allow an [=absolutely positioned box=]
-to align itself within the [=inset-modified containing block=].
-The existing values,
-plus carefully chosen [=inset properties=],
-are usually enough for useful alignment,
-but a common case for anchored positioning--
-centering over the [=anchor box=]--
-requires careful and somewhat complex set-up to achieve.
-
-The new anchor-center value
-makes this case extremely simple:
-if the positioned box has a [=default anchor box=],
-then it is centered (insofar as possible)
-over the [=default anchor box=]
-in the relevant axis.
-
-Additionally,
-any ''top/auto'' [=inset properties=] resolve to ''0''.
-
-If the box is not [=absolutely positioned=],
-or does not have a [=default anchor box=],
-this value behaves as ''/center''
-and has no additional effect on how [=inset properties=] resolve.
-
-Note: When using ''anchor-center'', by default
-if the anchor is too close to the edge of the box's
-[=original containing block=],
-it will “shift” from being purely centered,
-in order to remain within the [=original containing block=].
-See [[css-align-3#overflow-values]] for more details.
-
-Conditional Hiding: the 'position-visibility' property {#position-visibility}
-------------------------------------------------------
+Anchor-Based Alignment {#alignment}
+======================
-
-There are some conditions in which it might not make sense
-to display an [=absolutely positioned box=].
-This property allows such boxes to be made conditionally visible,
-depending on some commonly needed layout conditions.
+When 'position-area' is not ''position-area/none'',
+the [=used value=] of ''align-self/normal'' [=self-alignment=]
+changes depending on the <> value,
+to align the box towards the anchor:
-
- : always
- ::
- This property has no effect.
- (The box is displayed without regard for its anchors
- or its overflowing status.)
+* If the only the center track in an axis is selected,
+ the default alignment in that axis is ''align-self/center''.
+* If all three tracks are selected,
+ the default alignment in that axis is ''align-self/anchor-center''.
+* Otherwise, the default alignment in that axis
+ is toward the non-specified side track:
+ if it's specifying the “start” track of its axis,
+ the default alignment in that axis is ''align-self/end''; etc.
- : anchors-valid
- ::
- If any of the box's [=required anchor references=]
- do not resolve to a [=target anchor element=],
- the box's 'visibility' property computes to ''force-hidden''.
+However, if only one [=inset property=] in the relevant axis is ''inset/auto'',
+the default alignment is instead
+towards the edge with the non-''inset/auto'' inset;
+and this is an ''align-self/unsafe'' alignment.
- Issue: What is a required anchor reference?
- ''anchor()'' functions that don't have a fallback value;
- the default anchor *sometimes*?
- Need more detail here.
+Note: This single-''inset/auto'' behavior preserves the way
+a single specified inset controls the position of an [=absolutely positioned=] box.
- Issue: Any anchors are missing,
- or all anchors are missing?
- I can see use-cases for either, potentially.
- Do we want to make a decision here, or make it controllable somehow?
+
+ For example, assuming an English-equivalent writing mode (horizontal-tb, ltr),
+ then the value ''span-x-start top'' resolves to
+ the ''position-area/start'' region of the vertical axis,
+ and the ''position-area/start'' and ''position-area/center'' regions of the horizontal axis,
+ so the default alignments will be ''align-self: end''
+ (making the box's bottom [=margin edge=] flush with the bottom of the ''position-area/top'' region)
+ and ''justify-self: end''
+ (making the box's end-side [=margin edge=] flush with the end side of the ''position-area/span-start'' region).
+
- : anchors-visible
- ::
- If the box has a [=default anchor box=]
- but that [=anchor box=] is [=invisible=] or [=clipped by intervening boxes=],
- the box's 'visibility' property computes to ''force-hidden''.
+
+ If the box overflows its [=inset-modified containing block=],
+ but would still fit within its [=original containing block=],
+ by default it will “shift” to stay within its [=original containing block=],
+ even if that violates its normal alignment.
+ See [[css-align-3#overflow-values]] for details.
- : no-overflow
- ::
- If the box overflows its [=inset-modified containing block=]
- even after applying 'position-try',
- the box's 'visibility' property computes to ''force-hidden''.
-
+ This behavior makes it more likely
+ that positioned boxes remain visible
+ and within their intended bounds,
+ even when their [=containing block=]
+ ends up smaller than anticipated.
-
- An anchor box |anchor|
- is clipped by intervening boxes
- relative to a positioned box |abspos| relying on it
- if |anchor|'s [=ink overflow rectangle=]
- is fully clipped by a box
- which is an ancestor of |anchor|
- but a descendant of |abspos|'s containing block.
- Clipping in this case refers only to clipping due to 'overflow',
- or other effects (such as [=paint containment=])
- that clip to the [=overflow clip edge=].
+ For example, a ''position-area: bottom span-right'' value
+ lets the positioned box stretch
+ from its anchor's left edge
+ to its containing block's right edge,
+ and left-aligns it in that space by default.
+ But if the positioned box is larger than that space
+ (such as if the anchor is very close to the right edge of the screen),
+ it will shift leftwards to stay visible.
+
- Note: This means that if an abspos is next to its anchor in the DOM,
- for example,
- it'll remain visible even if its default anchor is scrolled off,
- since it's clipped by the same scroller anyway.
- Issue: Make sure this definition of clipped
- is consistent with View Transitions,
- which wants a similar concept.
+
+
+Centering on the Anchor: the ''anchor-center'' alignment value {#anchor-center}
+--------------------------------------------------------------
+
+
+
+The [=self-alignment properties=] allow an [=absolutely positioned box=]
+to align itself within the [=inset-modified containing block=].
+The existing values,
+plus carefully chosen [=inset properties=],
+are usually enough for useful alignment,
+but a common case for anchored positioning--
+centering over the [=anchor box=]--
+requires careful and somewhat complex set-up to achieve.
+
+The new anchor-center value
+makes this case extremely simple:
+if the positioned box has a [=default anchor box=],
+then it is centered (insofar as possible)
+over the [=default anchor box=]
+in the relevant axis.
+Additionally:
+* The [=scrollable containing block=] is used in place of the [=local containing block=]
+ where applicable,
+ so that the entire [=scrollable overflow area=] (typically) is available
+ for positioning.
+* The [=used value=] of any ''top/auto'' [=inset properties=]
+ and ''margin/auto'' [=margin properties=]
+ resolves to ''0''.
+
+If the box is not [=absolutely positioned=],
+or does not have a [=default anchor box=],
+this value behaves as ''/center''
+and has no additional effect on how [=inset properties=] resolve.
+
+Note: When using ''anchor-center'', by default
+if the anchor is too close to the edge of the box's
+[=original containing block=],
+it will “shift” from being purely centered,
+in order to remain within the [=original containing block=].
+See [[css-align-3#overflow-values]] for more details.
Anchor-Based Sizing {#sizing}
@@ -1458,10 +1404,10 @@ is equivalent to ''width: anchor-size(width)''.)
An ''anchor-size()'' function representing a [=resolvable anchor-size function=]
resolves at [=computed value=] time
(via [=style & layout interleaving=])
-to the <> separating the relevant border edges
+to the <> separating the relevant edges
(either left and right, or top and bottom,
whichever is in the specified axis)
-of the [=target anchor element=].
+of the [=target anchor element's=] [=anchor box=].
Name: position-try-fallbacks
-Value: none | [ [<> || <>] | <<'position-area'>> ]#
+Value: none | [ [<> || <>] | <> ]#
Initial: none
Inherited: no
Applies to: [=absolutely positioned boxes=]
@@ -1537,7 +1483,8 @@ This property provides a list of alternate positioning styles
to try when the [=absolutely positioned box=]
overflows its [=inset-modified containing block=].
This position options list
-is initially empty.
+initially contains a single [=position option=]
+generated from the element's base styles.
Each comma-separated entry in the list is a separate option:
either the name of a ''@position-try'' block,
@@ -1572,7 +1519,7 @@ Values have the following meanings:
and adds it to the [=position options list=].
: flip-block
@@ -1586,6 +1533,17 @@ Values have the following meanings:
swaps the values in the [=inline axis=],
essentially mirroring across a [=block-axis=] line.
+ : flip-x
+ ::
+ swaps the values in the [=horizontal axis=]
+ (between, for example, 'margin-left' and 'margin-right'),
+ essentially mirroring across a [=vertical-axis=] line.
+
+ : flip-y
+ ::
+ swaps the values in the [=vertical axis=],
+ essentially mirroring across a [=horizontal-axis=] line.
+
: flip-start
::
swaps the values of the [=start=] properties with each other,
@@ -1599,6 +1557,8 @@ Values have the following meanings:
If multiple keywords are given,
the transformations are composed in order
to produce a single [=position option=].
+ Logical directions are resolved against
+ the [=writing mode=] of the [=containing block=].
: <> || <>
::
@@ -1612,7 +1572,7 @@ Values have the following meanings:
Otherwise, does nothing.
- : <<'position-area'>>
+ : <>
::
Automatically creates a [=position option=]
composed solely of a 'position-area' property
@@ -1925,7 +1885,7 @@ The syntax of the ''@position-try'' rule is:
The <> specified in the prelude
is the rule's name.
If multiple ''@position-try'' rules are declared with the same name,
-the last one in document order "wins".
+they [=cascade=] the same as ''@keyframe'' rules do.
The ''@position-try'' rule only accepts
the following [=properties=]:
@@ -2002,7 +1962,7 @@ Applying Position Fallback {#fallback-apply}
When a positioned box
(shifted by its [=default scroll shift=])
overflows its [=inset-modified containing block=],
-and has a non-empty [=position options list=],
+and has more than one [=position option=] in its [=position options list=],
it [=determines position fallback styles=]
to attempt to find an option that avoids overflow.
@@ -2011,6 +1971,10 @@ so they affect [=computed values=]
(and can trigger transitions/etc)
even though they depend on layout and [=used values=].
+ISSUE: Rewrite this section to be less confusing and more correct.
+See Issue 12818,
+Issue 12890.
+
To apply a position option to a box's element |el|,
given a [=position option=] |new styles|:
@@ -2098,18 +2062,16 @@ laying out later boxes cannot change this decision.
At the time that {{ResizeObserver}} events are determined and delivered:
- * If a box |el| is [=absolutely positioned=],
- set its last successful position option
- to the set of [=accepted @position-try properties=] (and values)
- that it's currently using.
+ * If |el| has a [=last successful position option=]
+ remove its [=last successful position option=]
+ if any of the following are true:
- * Otherwise, if |el| has a [=last successful position option=]
- and if any of the following are true of it,
- remove its [=last successful position option=]:
-
- * |el| is not [=absolutely positioned=]
- * |el|'s computed value for 'position-try-fallbacks' has changed
- * Any of the ''@position-try'' rules referenced by |el|'s 'position-try-fallbacks'
+ * Its computed 'position' value has changed,
+ its [=containing block=] association has changed,
+ or it no longer generates a box.
+ * Its computed value for any [=longhand property|longhand=] of 'position-try' has changed.
+ * Its computed value for any [=accepted @position-try property=] has changed.
+ * Any of the ''@position-try'' rules referenced by it
have been added, removed, or mutated.
Then, [=determine position fallback styles=] for |el|
@@ -2117,6 +2079,11 @@ laying out later boxes cannot change this decision.
to the set of [=accepted @position-try properties=] (and values)
that it's now using.
+ * Otherwise, if a box |el| is [=absolutely positioned=],
+ set its last successful position option
+ to the set of [=accepted @position-try properties=] (and values)
+ that it's currently using.
+
Note: The timing of this recording/removal
is intentionally identical to the treatment of [=last remembered sizes=].
@@ -2151,6 +2118,110 @@ This limit must be at least five.
+
+There are some conditions in which it might not make sense
+to display an [=absolutely positioned box=].
+This property allows such boxes to be made conditionally visible,
+depending on some commonly needed layout conditions.
+
+
+ : always
+ ::
+ This property has no effect.
+ (The box is displayed without regard for its anchors
+ or its overflowing status.)
+
+ : anchors-valid
+ ::
+ If any of the box's [=required anchor references=]
+ do not resolve to a [=target anchor element=],
+ the box's 'visibility' property computes to ''force-hidden''.
+
+ Issue: What is a required anchor reference?
+ ''anchor()'' functions that don't have a fallback value;
+ the default anchor *sometimes*?
+ Need more detail here.
+
+ Issue: Any anchors are missing,
+ or all anchors are missing?
+ I can see use-cases for either, potentially.
+ Do we want to make a decision here, or make it controllable somehow?
+
+ : anchors-visible
+ ::
+ If the box has a [=default anchor box=]
+ but that [=anchor box=] is [=invisible=] or [=clipped by intervening boxes=],
+ the box's 'visibility' property computes to ''force-hidden''.
+
+ : no-overflow
+ ::
+ If the box overflows its [=inset-modified containing block=]
+ even after applying 'position-try',
+ the box's 'visibility' property computes to ''force-hidden''.
+
+
+
+ An anchor box |anchor|
+ is clipped by intervening boxes
+ relative to a positioned box |abspos| relying on it
+ if |anchor|'s [=ink overflow rectangle=]
+ is fully clipped by a box
+ which is an ancestor of |anchor|
+ but a descendant of |abspos|'s containing block.
+ Clipping in this case refers only to the same clipping effects
+ that are (by default) checked by {{IntersectionObserver}},
+ i.e. clipping due to 'clip-path',
+ 'overflow', or other effects (such as [=paint containment=])
+ that clip to the [=overflow clip edge=].
+
+ Whether or not |anchor| is [=clipped by intervening boxes=]
+ must be checked after [=updating content relevancy for a document=]
+ (see 'content-visibility' in [[css-contain-2]])
+ and running any {{ResizeObserver}},
+ but before running any {{IntersectionObserver}}.
+ It may also be checked at other times to improve responsiveness.
+
+
+ Note: This means that if an abspos is next to its anchor in the DOM,
+ for example,
+ it'll remain visible even if its default anchor is scrolled off,
+ since it's clipped by the same scroller anyway.
+
+ Issue: Make sure this definition of clipped
+ is consistent with View Transitions,
+ which wants a similar concept.
+
+ Note: This ensures that in a “chained anchor” situation,
+ if the first abspos is hidden due to this property
+ (due to its anchor being scrolled off),
+ then another abspos using it as an anchor will also be hidden,
+ rather than also floating in a nonsensical location.
+
+
@@ -372,7 +371,7 @@ Declaring Keyframes
the state of the animation if it were given a duration of ''10s''.
-
+ Animation states specified by keyframes
-Title: CSS Animations Level 2
+Title: CSS Animations Module Level 2
Status: ED
Work Status: Exploring
Shortname: css-animations
@@ -189,7 +189,7 @@ is elem. animation is disassociated from
elem.style.animation = 'spin 1s';
let animation = elem.getAnimations()[0]; // animation's owning element is elem
-elem.style.animation = ''; // animation no longer has an owning element
+elem.style.animation = ""; // animation no longer has an owning element
Note that although the owning element is often equal to the
@@ -704,79 +704,263 @@ When multiple 'animation-*' properties are set simultaneously,
so e.g. a change to 'animation-play-state' applies
to the simultaneously-applied timeline specified in 'animation-timeline'.
+
+
+The 'animation-trigger' property
+
+
+Name: animation-trigger
+Value: [ none | [ <> <>+ ]+ ]#
+Initial: none
+Applies to: all elements
+Inherited: no
+Percentages: N/A
+Computed value: as specified
+Animation type: not animatable
+Canonical order: per grammar
+
+
+The 'animation-trigger' property
+specifies whether the animation is a [=triggered animation=],
+and if it is,
+what trigger it responds to
+and what actions it takes in response.
+'animation-trigger' is a [=reset-only sub-property=] of the 'animation' shorthand.
+Its values are:
+
+
+ : none
+ ::
+ The corresponding animation is not a [=triggered animation=].
+
+ : [ <> <>+ ]+
+ ::
+ The corresponding animation is a [=triggered animation=],
+ responding to the triggers named by each <>,
+ and responding by taking the action named by the corresponding <>.
+ (See [[#trigger-scope]] for how <>s are resolved to [=triggers=].)
+
+ How many <>s a trigger accepts,
+ and what exactly activates them,
+ is determined by the type of the trigger.
+ ([=Event triggers=] take one and possibly an optional second, depending on whether they're stateless or stateful;
+ [=timeline triggers=] take one and optionally a second.)
+ Specifying the wrong number of actions
+ (too many or too few)
+ is valid syntactically,
+ but causes the trigger to have no effect.
+
+ If multiple triggers occur simultaneously,
+ they take effect in the order specified.
+
+ If the same <> is specified multiple times,
+ all but the last have no effect.
+
+
+The possible <> values,
+and what effect they have in each animation state:
+
+
+
+
Keyword
Extra Effect
initial
playing
paused
finished
+
+
none
—
—
—
—
—
+
play
—
{{play()}}
—
{{play()}}
{{play()}}
+
play-forwards
set playback rate to positive
{{play()}}
—
{{play()}}
{{play()}}
+
play-backwards
set playback rate to negative
{{play()}}
—
{{play()}}
{{play()}}
+
pause
—
—
{{pause()}}
—
—
+
reset
set progress to 0
—
{{pause()}}
{{pause()}}
{{pause()}}
+
replay
set progress to 0
{{play()}}
—
{{play()}}
{{play()}}
+
+ If there is an "effect",
+ it happens regardless of the current state,
+ before the state-specific action
+
-
- Animation Triggers are defined using the 'animation-trigger-*' properties.
- These list-valued properties,
- which are all [=longhands=] of the 'animation-trigger' [=shorthand=],
- form a [=coordinating list property group=]
- with 'animation-name' as the [=coordinating list base property=]
- and each item in the [=coordinated value list=]
- defining the properties of a single animation trigger.
-
- The 'animation-trigger' properties
- are [=reset-only sub-properties=] of the 'animation' [=shorthand=].
-## The 'animation-trigger-behavior' property ## {#animation-trigger-behavior}
+
-
-Name: animation-trigger-behavior
-Value: <>#
-Initial: once
+
+Triggers
+
+While CSS animations are, by default,
+automatically run as soon as the appropriate 'animation' values have been set on an element,
+the 'animation-trigger' property allows the animation's start to be delayed
+until an appropriate trigger occurs,
+and even paused, restarted, or reset by triggers
+(making it a triggered animation).
+
+This is a simplified and streamlined version
+of what can be achieved with the Web Animations API in Javascript,
+allowing simple, common interaction patterns
+to be created and managed purely in CSS.
+
+Currently, two types of triggers are defined:
+
+* [=timeline triggers=], managed by the 'timeline-trigger' properties,
+ which allow animations to be triggered by entering or leaving certain timeline ranges.
+ (Usually, [=view progress timelines=],
+ so an animation can be started when an element comes on-screen,
+ without actually driving the animation with the scroll progress.)
+
+* [=event triggers=], managed by the 'event-trigger' properties,
+ which allow animations to be triggered by certain user-interaction events,
+ such as clicking an element or pressing certain keys.
+
+A [=trigger=] is defined on some specific triggering element.
+All triggers have a name,
+and the specific type of trigger dictates how and when it's activated.
+A trigger can define multiple "types" of activation.
+(For example, [=timeline triggers=] can do different things on entry and exit.)
+
+A [=trigger=] is used on potentially any element,
+creating a trigger instance on the element.
+(For example, 'animation-trigger' associates a [=trigger instance=]
+with a specific animation on the element.)
+The trigger-using element specifies what actions to take
+when the [=trigger=] activates.
+
+Note: This design for [=triggers=] and [=trigger instances=],
+and the way they're associated with [=triggered animations=] and <>s,
+is intentionally somewhat generic,
+intended to support using [=triggers=] for other purposes in the future.
+For now, though, [=triggered animations=] are the only user of this feature.
+
+
+
+Trigger Scope/Resolution
+
+All [=triggers=] are document-global by default,
+similar to [=anchor names=].
+
+If a single element attempts to define multiple [=triggers=] of different types
+with the same name,
+it only exposes one of them,
+with [=event triggers=] winning over [=timeline triggers=].
+
+Note: This order is completely arbitrary
+(based on alphabetic order of the concept name),
+as this is just an error case.
+
+If multiple elements define [=triggers=] with the same name,
+the [=trigger=] defined by the later element in [=tree order=] is used.
+
+Note: This behavior will be improved by a trigger-scope property,
+not yet defined,
+letting you define triggers that are only visible to subtrees
+and references that only search in that subtree
+(just like 'anchor-scope').
+
+
+
+
+Timeline Triggers
+
+A timeline trigger is a [=trigger=]
+which is activated when some [=timeline=]
+enters the trigger's enter range,
+or leaves the trigger's exit range.
+It is defined on an element with the 'timeline-trigger' shorthand property,
+or its longhands.
+
+A [=timeline trigger=] has a binary trigger state associated with it;
+it is initially "untriggered".
+While it's "untriggered",
+the associated [=timeline=] entering (or starting in) the trigger's [=enter range=]
+performs an associated enter action
+and switches the [=timeline trigger/trigger state=] to "triggered";
+while it's "triggered",
+the associated timeline leaving the trigger's [=exit range=]
+performs an associated exit action
+and switches the [=timeline trigger/trigger state=] to "untriggered".
+
+Note: By default, the [=exit range=] is the same as the [=enter range=];
+even when manually specified,
+the [=exit range=] is always a superset of the [=enter range=].
+The two ranges allow, for example,
+an 'animation-trigger' to start an animation
+when an element is scrolled close the center of the screen
+(using a [=view progress timeline=] with a relatively small window as the [=enter range=]),
+but not stop it until the element is fully off-screen
+(using ''animation-timeline-range/cover'' as the [=exit range=]).
+
+Issue: I think it's WebAnim2 that needs to define
+that exit ranges are interpreted
+as the bounding range of the [=enter range=]
+and what's specified for the [=exit range=].
+
+A [=timeline trigger=] can have one or two actions associated with it
+when used as a trigger on an element
+(such as by 'animation-trigger').
+If two are specified, the first is the trigger's [=timeline trigger/enter action=]
+and the second is the trigger's [=timeline trigger/exit action=];
+if only one is specified, the first is the trigger's [=timeline trigger/enter action=]
+and its [=timeline trigger/exit action=] is to do nothing.
+
+An element can define multiple [=timeline triggers=],
+using the same [=timeline=] (potentially with different ranges)
+or different ones.
+The set of 'timeline-trigger' longhands
+form a [=coordinating list property group=],
+with 'timeline-trigger-name' as the [=coordinating list base property=],
+and each item in the [=coordinated value list=]
+defining the properties of a single [=timeline trigger=].
+
+
+
+Naming the Trigger: the 'timeline-trigger-name' property
+
+
+Name: timeline-trigger-name
+Value: none | <>#
+Initial: none
Applies to: all elements
Inherited: no
Percentages: N/A
-Computed value: list, each item a keyword as specified
-Animation type: not animatable
+Computed value: as specified
Canonical order: per grammar
+Animation type: not animatable
-<single-animation-trigger-behavior> = once | repeat | alternate | state
-
-The values of 'animation-trigger-behavior' have the following meaning
-for an [=animation trigger=] that enters its [=animation trigger/active interval|active interval=]:
-
-
-
once
-
- The animation is triggered and played once and only once.
-
-
repeat
-
- The animation is played from the beginning each time it is triggered.
- When the trigger’s [=animation trigger/active interval=] is exited the animation is reset.
+If ''timeline-trigger-name/none'' is specified,
+the element does not define any [=timeline triggers=].
-
alternate
-
- The animation is played forwards, according to its [=playback direction=], each time it is triggered.
- When the trigger’s [=animation trigger/active interval=] is exited the animation is reversed.
+If the same <> appears multiple times in the list,
+only the last one defines a [=timeline trigger=];
+the preceding ones have no effect.
-
state
-
- The animation is triggered and played once.
- When the trigger’s [=animation trigger/active interval=] is exited the animation is paused.
- When the trigger’s [=animation trigger/active interval=] is re-entered the animation is resumed.
-
-
-The behavior of each value is defined in [[web-animations-2#trigger-behaviors]].
-
-## The 'animation-trigger-timeline' property ## {#animation-trigger-timeline}
-The 'animation-trigger-timeline' property specifies the timeline
-of the animation’s associated [=animation trigger=].
+
+Linking a Timeline: the 'timeline-trigger-source' property
-Name: animation-trigger-timeline
+Name: timeline-trigger-source
Value: <>#
Initial: auto
Applies to: all elements
@@ -793,199 +977,266 @@ Canonical order: per grammar
Animation Type: not animatable
-The values of 'animation-trigger-timeline' have the same meaning as those of 'animation-timeline'.
+The 'timeline-trigger-source' property
+specifies the [=timeline trigger's=] associated [=timeline=].
+Values have the same meaning as those of 'animation-timeline',
+except that ''timeline-trigger-source/none''
+instead causes the corresponding entry in the [=coordinated value list=]
+to not define a [=timeline trigger=].
-Issue: Probably a trigger with timeline "none" is under-specified here. Need to clarify what it means.
-
-## The 'animation-trigger-range' property ## {#animation-trigger-range}
+
+The Enter Range: the 'timeline-trigger-range' property
-The 'animation-trigger-range' property is a [=shorthand property|shorthand=]
-that sets 'animation-trigger-range-start' and 'animation-trigger-range-end'
-together in a single declaration,
-specifying the [=animation trigger=]’s associated [=default range=].
+The 'timeline-trigger-range' property is a [=shorthand property=]
+that sets 'timeline-trigger-range-start' and 'timeline-trigger-range-end'
+together in a single declaration.
It has the same syntax as the 'animation-range' property.
-The behavior of 'animation-trigger-range' is defined in [[web-animations-2#trigger-ranges]].
+The behavior of 'timeline-trigger-range' is defined in [[web-animations-2#trigger-ranges]].
-## The 'animation-trigger-range-start' property ## {#animation-trigger-range-start}
+Issue: Need to rewrite WebAnim2 to use the term "enter range".
- Name: animation-trigger-range-start
- Value: [ normal | <> | <> <>? ]#
- Initial: normal
- Applies to: all elements
- Inherited: no
- Percentages: relative to the specified [=named timeline range=] if one was specified, else to the entire timeline
- Computed value: list, each item either the keyword ''animation-trigger-range-start/normal'' or a timeline range and progress percentage
- Animation type: not animatable
+Name: timeline-trigger-range-start, timeline-trigger-range-end
+Value: [ normal | <> | <> <>? ]#
+Initial: normal
+Applies to: all elements
+Inherited: no
+Percentages: relative to the specified [=named timeline range=] if one was specified, else to the entire timeline
+Computed value: list, each item either the keyword ''animation-trigger-range-start/normal'' or a timeline range and progress percentage
+Animation type: not animatable
-The 'animation-trigger-range-start' property specifies the start of the [=animation trigger=]’s
-associated [=default range=].
+The 'timeline-trigger-range-start' and 'timeline-trigger-range-end' properties
+specify the [=timeline trigger=]’s associated [=timeline trigger/enter range=].
+Values have the same meaning as 'animation-range-start' and 'animation-range-end'.
-The values of 'animation-trigger-range-start' have the same meaning as those of 'animation-range-start'.
-## The 'animation-trigger-range-end' property ## {#animation-trigger-range-end}
+
+The Exit Range: the 'timeline-trigger-exit-range' property
-
- Name: animation-trigger-range-end
- Value: [ normal | <> | <> <>? ]#
- Initial: normal
- Applies to: all elements
- Inherited: no
- Percentages: relative to the specified [=named timeline range=] if one was specified, else to the entire timeline
- Computed value: list, each item either the keyword ''animation-trigger-range-end/normal'' or a timeline range and progress percentage
- Animation type: not animatable
+
-The 'animation-trigger-range-end' property specifies the end of the [=animation trigger=]’s
-associated [=default range=].
+The 'timeline-trigger-exit-range' property is a [=shorthand property=]
+that sets 'timeline-trigger-exit-range-start' and 'timeline-trigger-exit-range-end'
+together in a single declaration.
+It has the same syntax as the 'animation-range' property.
-The values of 'animation-trigger-range-end' have the same meaning as those of 'animation-range-end'.
+The behavior of 'timeline-trigger-exit-range' is defined in [[web-animations-2#trigger-ranges]].
-## The 'animation-trigger-exit-range' property ## {#animation-trigger-exit-range}
+
+
+Name: timeline-trigger-exit-range-start, timeline-trigger-exit-range-end
+Value: [ auto | normal | <> | <> <>? ]#
+Initial: auto
+Applies to: all elements
+Inherited: no
+Percentages: relative to the specified [=named timeline range=] if one was specified, else to the entire timeline
+Computed value: list, each item either the keyword ''animation-trigger-range-start/normal'' or a timeline range and progress percentage
+Animation type: not animatable
+
+
+The 'timeline-trigger-exit-range-start' and 'timeline-trigger-exit-range-end' properties
+specify the [=timeline trigger=]’s associated [=timeline trigger/exit range=].
+Values have the same meaning as 'animation-range-start' and 'animation-range-end',
+with the following addition:
+
+
+ : auto
+ ::
+ The start (for 'timeline-trigger-exit-range-start')
+ or end (for 'timeline-trigger-exit-range-end')
+ is equal to the start/end of the [=timeline trigger's=] [=enter range=].
+
-The 'animation-trigger-exit-range' property is a [=shorthand property|shorthand=]
-that sets 'animation-trigger-exit-range-start' and 'animation-trigger-exit-range-end'
-together in a single declaration,
-specifying the [=animation trigger=]’s associated [=exit range=].
-It has the same syntax as the 'animation-range' property, with the addition of the ''animation-trigger-exit-range-start/auto'' keyword.
+The 'timeline-trigger' [=shorthand property=]
+sets all of 'timeline-trigger-name',
+'timeline-trigger-source',
+'timeline-trigger-range',
+and optionally 'timeline-trigger-exit-range'
+at once.
+
+A value of none
+is equivalent to ''none none normal''.
+
+Note: Due to significant potentially ambiguities in the syntax
+('timeline-trigger-name' vs [=timeline=] names in 'timeline-trigger-source';
+[=enter ranges=] vs [=exit ranges=]),
+this shorthand's values must be given in the specified order,
+rather than being settable in any order as is more common.
+
+Issue: I think we need the ''/'' to disambiguate the two ranges?
+
+
+
+
+
+Event Triggers
+
+An event trigger is a [=trigger=]
+which is activated when certain {{Event}}s are fired at the element.
+It is defined on an element with the 'event-trigger' shorthand property,
+or its longhands.
+
+An [=event trigger=] can be defined as either stateless or stateful:
+
+* If stateless, it has a single set of enter events
+ that activate it.
+* If stateful, it has two sets of events, its [=enter events=]
+ and another set of exit events.
+
+[=Event triggers=] are activated when one of its associated {{Event}}s are fired on the page
+with the trigger-defining element as its {{Event/target}}.
+If it's stateful,
+it has a binary trigger state associated with it,
+initially "untriggered":
+while "untriggered", it only activates when the defining element receives one of its [=enter events=],
+performing an associated enter action
+and switching its [=event trigger/trigger state=] to "triggered";
+while "triggered", it only activates when it receives one of its [=exit events=],
+performing an associated exit action
+and switching its [=event trigger/trigger state=] back to "untriggered".
+
+A stateless [=event trigger=] must be given exactly one action for its [=trigger instance=].
+A stateful one can be given one or two:
+the first is its [=event trigger/enter action=],
+and the second, if provided, is its [=event trigger/exit action=];
+if the second is not provided,
+the [=event trigger/exit action=] is to do nothing.
+
+Note: A stateful and stateless [=event trigger=] act differently
+even if you only assign a single action;
+a single-action stateful [=event trigger=] will effectively "turn off"
+until it receives one of its [=exit events=],
+ignoring any of the [=enter events=] after the first,
+while a stateless one will repeatedly trigger for every [=enter event=].
+
+An element can define multiple [=event triggers=],
+using the same {{Event}}s or different ones.
+The set of 'event-trigger' longhands
+form a [=coordinating list property group=],
+with 'event-trigger-name' as the [=coordinating list base property=],
+and each item in the [=coordinated value list=]
+defining the properties of a single [=event trigger=].
+
+Issue: The proposal I drew this text from
+specified that it only cares if the element is the *target* of the event.
+We probably want to allow for bubbling and/or capturing,
+possibly as an opt in/out.
+
+
+
+Naming the Trigger: the 'event-trigger-name' property
+
+
+Name: event-trigger-name
+Value: none | <>#
+Initial: none
+Applies to: all elements
+Inherited: no
+Percentages: N/A
+Computed value: as specified
+Canonical order: per grammar
+Animation type: not animatable
+
-The [=exit range=] replaces the [=default range=] once the [=animation trigger=]’s
-[=animation trigger/active interval|active interval=] is entered,
-and redefines the extent of the [=animation trigger=]’s [=animation trigger/active interval|active interval=].
-It is used to extend the [=default range=], for example,
-in cases where exiting the [=animation trigger/active interval|active interval=]
-may create a visual jump that needs to be avoided.
+If ''event-trigger-name/none'' is specified,
+the element does not define any [=event triggers=].
-The behavior of 'animation-trigger-exit-range' is further defined in [[web-animations-2#trigger-ranges]].
+If the same <> appears multiple times in the list,
+only the last one defines a [=event trigger=];
+the preceding ones have no effect.
-## The 'animation-trigger-exit-range-start' property ## {#animation-trigger-exit-range-start}
+
+Linking an Event: the 'event-trigger-source' property
-
- Name: animation-trigger-exit-range-start
- Value: [ auto | normal | <> | <> <>? ]#
- Initial: auto
- Applies to: all elements
- Inherited: no
- Percentages: relative to the specified [=named timeline range=] if one was specified, else to the entire timeline
- Computed value: list, each item either the keyword ''animation-trigger-exit-range-start/normal'' or a timeline range and progress percentage
- Animation type: not animatable
+
+Name: event-trigger-source
+Value: [ none | <>+ [ / <>+ ]? ]#
+Initial: none
+Applies to: all elements
+Inherited: no
+Percentages: N/A
+Computed value: as specified
+Animation type: not animatable
-The 'animation-trigger-exit-range-start' property specifies the start of the [=animation trigger=]’s
-associated [=exit range=].
-
-The values of 'animation-trigger-exit-range-start' have the following meaning:
-
-
-
auto
-
- The start of the trigger’s [=exit range=]
- is equal to the start of its [=default range=].
-
-
normal
-
- The start of the trigger’s [=exit range=]
- is the start of its associated [=timeline=];
- the start of the trigger’s [=animation trigger/active interval|active interval=]
- is determined as normal.
-
-
<>
-
- The [=exit range=] starts
- at the specified point on the [=timeline=]
- measuring from the start of the timeline.
-
-
<> <>?
-
- The [=exit range=] starts
- at the specified point on the [=timeline=]
- measuring from the start of the specified [=named timeline range=].
- If the <> is omitted,
- it defaults to 0%.
-
+The 'event-trigger-source' property
+specifies what event or events activate the [=event trigger=].
+Its values are:
-## The 'animation-trigger-exit-range-end' property ## {#animation-trigger-exit-range-end}
+
+ : none
+ :: The corresponding entry in the [=coordinated value list=] does not define a trigger.
-
- Name: animation-trigger-exit-range-end
- Value: [ auto | normal | <> | <> <>? ]#
- Initial: auto
- Applies to: all elements
- Inherited: no
- Percentages: relative to the specified [=named timeline range=] if one was specified, else to the entire timeline
- Computed value: list, each item either the keyword ''animation-trigger-exit-range-end/normal'' or a timeline range and progress percentage
- Animation type: not animatable
-
+ : <>+ [ / <>+ ]?
+ :: Defines what event(s) the [=event trigger=] responds to.
+
+ If a ''/'' is used in the value,
+ the [=event trigger=] is stateful;
+ the set of events before the ''/'' are the [=event trigger's=] [=enter events=],
+ while those after the ''/'' are the [=exit events=].
+ (The same events can occur in both sets.)
-The 'animation-trigger-exit-range-end' property specifies the end of the [=animation trigger=]’s
-associated [=exit range=].
-
-The values of 'animation-trigger-exit-range-start' have the following meaning:
-
-
-
auto
-
- The end of the trigger’s [=exit range=]
- is equal to the end of its [=default range=].
-
-
normal
-
- The end of the trigger’s [=exit range=]
- is the end of its associated [=timeline=];
- the end of the trigger’s [=animation trigger/active interval|active interval=]
- is determined as normal.
-
-
<>
-
- The [=exit range=] ends
- at the specified point on the [=timeline=]
- measuring from the start of the timeline.
-
-
<> <>?
-
- The [=exit range=] ends
- at the specified point on the [=timeline=]
- measuring from the start of the specified [=named timeline range=].
- If the <> is omitted,
- it defaults to 100%.
+ Otherwise,
+ the [=event trigger=] is stateless,
+ and the provided events are its [=enter events=].
-## The 'animation-trigger' property ## {#animation-trigger}
+
+
+Issue: Figure out the full set of events we want to handle.
-The 'animation-trigger' property is a [=shorthand property|shorthand=]
-that sets 'animation-trigger-behavior', 'animation-trigger-timeline',
-'animation-trigger-range-start', 'animation-trigger-range-end',
-'animation-trigger-exit-range-start', and 'animation-trigger-exit-range-end'
-together in a single declaration,
-specifying the [=animation trigger=] for an animation.
+
+
+The 'event-trigger' Shorthand
-Name: animation-trigger
-Value: <>#
-Initial: see individual properties
+Name: event-trigger
+Value: none | [ <<'event-trigger-name'>> <<'event-trigger-source'>> ]#
+Initial: none
Applies to: all elements
Inherited: no
Percentages: N/A
-Computed value: see individual properties
-Canonical order: per grammar
-Animation Type: not animatable
+Computed value: as specified
+Animation type: not animatable
+
+ The [=specified value=] and [=computed value=] of the <> type
+ always serialize as two values, even when the second value is ''background-size/auto'',
+ due to the [[cssom#serializing-css-values|shortest, most backwards-compatible serialization principle]].
+
Backgrounds Shorthand: the 'background' property
@@ -2453,13 +2484,37 @@ Corner Shaping
The [=margin edge=], being outside the [=border edge=],
calculates its radius by adding the corresponding margin thickness
- to each border radius.
- However, in order to create a sharper corner when the border radius is small
- (and thus ensure continuity between round and sharp corners),
- when the [=border radius=] is less than the margin,
- the margin is multiplied by the proportion 1 + (r-1)3,
- where r is the ratio of the border radius to the margin,
- in calculating the corner radii of the margin box shape.
+ to each border radius, with the corresponding [=outset-adjusted border radius=] applied.
+
+
+ background-clip-content-box-with-border-radius-002.html
+ background-clip-content-box-with-border-radius-003.html
+ background-clip-padding-box-with-border-radius-002.html
+ background-clip-padding-box-with-border-radius-003.html
+
+
+
+
+ When expanding an [=edge=] that has a [=border radius=], e.g. for computing the [=margin edge=], 'box-shadow' spread, or 'overflow-clip-margin',
+ the different [=border radius=] values are adjusted so that a small rounded corner with a big outset does not appear to be disproportionally round.
+
+ This is done by computing the corresponding [=outset-adjusted border radius=].
+
+ To compute the outset-adjusted border radius given the 2-dimensional [=size=]s |edge|, |radius|, and |outset|:
+ 1. Let |coverage| be 2 * min(|radius|'s [=width=] / |edge|'s [=width=], |radius|'s [=height=] / |edge|'s [=height=]).
+ 1. Let |adustedRadiusWidth| be the [=adjusted radius dimension=] given |coverage|, |radius|'s [=width=], and |outset|'s [=width=].
+ 1. Let |adustedRadiusHeight| be the [=adjusted radius dimension=] given |coverage|, |radius|'s [=height=], and |outset|'s [=height=].
+ 1. Return (|adustedRadiusWidth|, |adustedRadiusHeight|).
+
+ To compute the adjusted radius dimension given numbers |coverage|, |radius|, and |outset|:
+ 1. If |radius| is greater than |spread|, or if |coverage| is greater than 1, then return |radius| + |outset|.
+ 1. Let |ratio| be |radius| / |outset|.
+ 1. Return |radius| + |outset| * (1 - (1 - |ratio|)3 * (1 - |coverage|3)).
+
+ Note: this algorithm is designed to reduce the effect of the |outset| (or spread) on the shape of the corner.
+ The |coverage| factor makes this reduction more pronounced for rectangular shapes (where the [=border-radius=] is close to 0),
+ and less pronounced for elliptical shapes (where the [=border-radius=] is close to 50%).
+
@@ -3342,7 +3402,7 @@ Border Image Shorthand: the 'border-image' property
represented by 2-4 length values, an optional color, and an optional ''box-shadow/inset'' keyword.
Omitted lengths are 0; omitted colors default to ''currentColor''.
- <> = <>? && [<>{2} <>? <>?] && inset?
+ <> = <>? && [ <>{2} [ <> <>? ]? ] && inset?
The components of each <> are interpreted as follows:
@@ -3544,22 +3604,15 @@ Shadow Shape, Spread, and Knockout
the corner radii of the shadow are also increased (decreased, for inner shadows)
from the border-box (padding-box) radii by adding (subtracting)
the [=spread distance=] (and flooring at zero).
- However, in order to create a sharper corner when the border radius is small
- (and thus ensure continuity between round and sharp corners),
- when the [=border radius=] is less than the [=spread distance=]
- (or in the case of an inner shadow,
- less than the absolute value of a negative [=spread distance=]),
- the [=spread distance=]
- is first multiplied by the proportion 1 + (r-1)3,
- where r is the ratio of the border radius to the [=spread distance=],
- in calculating the corner radii of the spread shadow shape.
- For example, if the border radius is 10px and the [=spread distance=] is 20px (r = .5),
- the corner radius of the shadow shape will be 10px + 20px × (1 + (.5 - 1)3) = 27.5px
- rather than 30px.
- This adjustment is applied independently to the radii in each dimension.
+ For outer shadows, the [=border-radius=] is then [=outset-adjusted border radius|adjusted=], independently in each dimension,
+ to preserve the sharpness of rounded corners.
The 'border-image' does not affect the shape of the box-shadow.
+
+ box-shadow-radius-generated.html
+
+
Blurring Shadow Edges
@@ -3657,6 +3710,22 @@ Level 3
Changes
+
+Changes since the 11 March 2024 Candidate Recommendation Draft
+
+
+
+
Altered the border-radius outset adjustment,
+ so the radius reduction factor in the
+ minimum radius percentage of the corner, makes it less pronounced
+ the closer the corner's border-radius gets to 50%.
+ (Issue 7103)
+
+
Fixed syntax of 'box-shadow' to avoid allowing negative blur radii,
+ aligning it with the prose.
+
Cross linked to 'ink overflow' terminology
+
+
Changes since the 14 February 2023 Candidate Recommendation Snapshot
@@ -3681,6 +3750,8 @@ Changes since the 14 February 2023 Candidate Recommendation Snapshot
[=CSS/value definition syntax=].
Fixed the definition for where box shadows apply.
(Issue 9286)
+
Defined serialization of 'background-size' in [[#bg-size-serialization]].
+ (Issue 7802)
@@ -4132,4 +4203,7 @@ Changes Since the 17 December 2009 Candidate Recommendation
color-mix-currentcolor-outline-repaint-parent.html
color-mix-currentcolor-outline-repaint.html
first-letter-space-not-selected.html
-
\ No newline at end of file
+ animations/background-color-animation-custom-property.html
+ animations/background-color-animation-custom-timing-function-reverse.html
+ animations/background-color-animation-custom-timing-function.html
+
diff --git a/css-backgrounds-3/radius-expansion.html b/css-backgrounds-3/radius-expansion.html
index ff5cfb0d7eab..3519c93d7ba4 100644
--- a/css-backgrounds-3/radius-expansion.html
+++ b/css-backgrounds-3/radius-expansion.html
@@ -78,6 +78,14 @@
Oriol's variant of current spec (adding a linear factor)
+
+
+
+
+## Transitions as an enhancement ## {#transitions-as-enhancements}
+
+ A key part of the View Transition API design
+ is that an animated transition is a visual enhancement
+ to an underlying document state change.
+ That means a failure to create a visual transition,
+ which can happen due to misconfiguration or device constraints,
+ will not prevent the developer's {{ViewTransitionUpdateCallback}} being called,
+ even if it's known in advance that the transition animations cannot happen.
+
+ For example, if the developer calls {{ViewTransition/skipTransition()}} at the start of the [[#lifecycle|view transition lifecycle]],
+ the steps relating to the animated transition,
+ such as creating the [=view transition tree=],
+ will not happen.
+ However, the {{ViewTransitionUpdateCallback}} will still be called.
+ It's only the visual transition that's skipped,
+ not the underlying state change.
+
+ Note: If the DOM change should also be skipped,
+ then that needs to be handled by another feature.
+ {{NavigateEvent|navigateEvent}}.{{NavigateEvent/signal}} is an example of a feature developers could use to handle this.
+
+ Although the View Transition API allows DOM changes to be asynchronous via the {{ViewTransitionUpdateCallback}},
+ the API is not responsible for queuing or otherwise scheduling DOM changes
+ beyond any scheduling needed for the transition itself.
+ Some asynchronous DOM changes can happen concurrently (e.g if they're happening within independent components),
+ whereas others need to queue, or abort an earlier change.
+ This is best left to a feature or framework that has a more holistic view of the application.
+
+## Rendering Model ## {#rendering-model}
+
+ View Transition works by replicating an element's rendered state using UA generated pseudo-elements.
+ Aspects of the element's rendering which apply to the element itself or its descendants,
+ for example visual effects like 'filter' or 'opacity' and clipping from 'overflow' or 'clip-path',
+ are applied when generating its image in [=Capture the image=].
+
+ However, properties like 'mix-blend-mode' which define how the element draws when it is embedded can't be applied to its image.
+ Such properties are applied to the element's corresponding ''::view-transition-group()'' pseudo-element,
+ which is meant to generate a box equivalent to the element.
+
+ If the ''::view-transition-group()'' has a corresponding element in the "new" states,
+ the browser keeps the properties copied over to the ''::view-transition-group()'' in sync with the DOM element in the "new" state.
+ If the ''::view-transition-group()'' has corresponding elements both in the "old" and "new" state,
+ and the property being copied is interpolatable,
+ the browser also sets up a default animation to animate the property smoothly.
+
+## Examples ## {#examples}
+
+
+ Taking a page that already updates its content using a pattern like this:
+
+ ```js
+ function spaNavigate(data) {
+ updateTheDOMSomehow(data);
+ }
+ ```
+
+ A [=view transition=] could be added like this:
+
+ ```js
+ function spaNavigate(data) {
+ // Fallback for browsers that don't support this API:
+ if (!document.startViewTransition) {
+ updateTheDOMSomehow(data);
+ return;
+ }
+
+ // With a transition:
+ document.startViewTransition(() => updateTheDOMSomehow(data));
+ }
+ ```
+
+ This results in the default transition of a quick cross-fade:
+
+
+
+
+
+ The cross-fade is achieved using CSS animations on a [[#view-transition-pseudos|tree of pseudo-elements]],
+ so customizations can be made using CSS. For example:
+
+ ```css
+ ::view-transition-old(root),
+ ::view-transition-new(root) {
+ animation-duration: 5s;
+ }
+ ```
+
+ This results in a slower transition:
+
+
+
+
+
+
+
+ Building on the previous example, motion can be added:
+
+ ```css
+ @keyframes fade-in {
+ from { opacity: 0; }
+ }
+
+ @keyframes fade-out {
+ to { opacity: 0; }
+ }
+
+ @keyframes slide-from-right {
+ from { transform: translateX(30px); }
+ }
+
+ @keyframes slide-to-left {
+ to { transform: translateX(-30px); }
+ }
+
+ ::view-transition-old(root) {
+ animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
+ 300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
+ }
+
+ ::view-transition-new(root) {
+ animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
+ 300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
+ }
+ ```
+
+ Here's the result:
+
+
+
+
+
+
+
+ Building on the previous example,
+ the simple "whole document" transition displayed a visible judder in the purple heading bar,
+ and had the heading text always slide to the left
+ even when it was "moving" to the right in the 1->2 transition.
+ To fix these issues,
+ the header and text within the header can be given their own ''::view-transition-group()''s for the transition:
+
+ ```css
+ .main-header {
+ view-transition-name: main-header;
+ }
+
+ .main-header-text {
+ view-transition-name: main-header-text;
+ /* Give the element a consistent size, assuming identical text: */
+ width: fit-content;
+ }
+ ```
+
+ By default, these groups will transition size and position from their “old” to “new” state,
+ while their visual states cross-fade:
+
+
+
+
+
+
+
+ Building on the previous example, let's say some pages have a sidebar:
+
+
+
+
+
+ In this case, things would look better if the sidebar was static if it was in both the “old” and “new” states.
+ Otherwise, it should animate in or out.
+
+ The '':only-child'' pseudo-class can be used to create animations specifically for these states:
+
+ ```css
+ .sidebar {
+ view-transition-name: sidebar;
+ }
+
+ @keyframes slide-to-right {
+ to { transform: translateX(30px); }
+ }
+
+ /* Entry transition */
+ ::view-transition-new(sidebar):only-child {
+ animation: 300ms cubic-bezier(0, 0, 0.2, 1) both fade-in,
+ 300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
+ }
+
+ /* Exit transition */
+ ::view-transition-old(sidebar):only-child {
+ animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
+ 300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-right;
+ }
+ ```
+
+ For cases where the sidebar has both an “old” and “new” state, the default animation is correct.
+
+
+
+
+
+
+
+ Not building from previous examples this time,
+ let's say we wanted to create a circular reveal from the user's cursor.
+ This can't be done with CSS alone.
+
+ Firstly, in the CSS, allow the “old” and “new” states to layer on top of one another without the default blending,
+ and prevent the default cross-fade animation:
+
+ ```css
+ ::view-transition-image-pair(root) {
+ isolation: auto;
+ }
+
+ ::view-transition-old(root),
+ ::view-transition-new(root) {
+ animation: none;
+ mix-blend-mode: normal;
+ }
+ ```
+
+ Then, the JavaScript:
+
+ ```js
+ // Store the last click event
+ let lastClick;
+ addEventListener('click', event => (lastClick = event));
+
+ function spaNavigate(data) {
+ // Fallback for browsers that don't support this API:
+ if (!document.startViewTransition) {
+ updateTheDOMSomehow(data);
+ return;
+ }
+
+ // Get the click position, or fallback to the middle of the screen
+ const x = lastClick?.clientX ?? innerWidth / 2;
+ const y = lastClick?.clientY ?? innerHeight / 2;
+ // Get the distance to the furthest corner
+ const endRadius = Math.hypot(
+ Math.max(x, innerWidth - x),
+ Math.max(y, innerHeight - y)
+ );
+
+ // Create a transition:
+ const transition = document.startViewTransition(() => {
+ updateTheDOMSomehow(data);
+ });
+
+ // Wait for the pseudo-elements to be created:
+ transition.ready.then(() => {
+ // Animate the root's new view
+ document.documentElement.animate(
+ {
+ clipPath: [
+ \`circle(0 at ${x}px ${y}px)\`,
+ \`circle(${endRadius}px at ${x}px ${y}px)\`,
+ ],
+ },
+ {
+ duration: 500,
+ easing: 'ease-in',
+ // Specify which pseudo-element to animate
+ pseudoElement: '::view-transition-new(root)',
+ }
+ );
+ });
+ }
+ ```
+
+ And here's the result:
+
+
+
+
+
+
+ Note: though 'view-transition-name' is [=discrete|discretely animatable=], animating it doesn't
+ affect the running view transition. Rather, it's a way to set its value in a way that can change
+ over time or based on a [=timeline=]. An example for using this would be to change the 'view-transition-name'
+ based on [=scroll-driven animations=].
+
+ The 'view-transition-name' property “tags” an element
+ for [=capture in a view transition=],
+ tracking it independently in the [=view transition tree=]
+ under the specified view transition name.
+ An element so captured is animated independently of the rest of the page.
+
+
+ : none
+ :: The [=/element=] will not participate independently in a view transition.
+
+ : <>
+ :: The [=/element=] participates independently in a view transition--
+ as either an old or new [=/element=]--
+ with the specified [=view transition name=].
+
+ Each [=view transition name=] is a [=tree-scoped name=].
+
+ The values none, auto, and match-element are excluded from <> here.
+
+ Note: If this name is not unique
+ (i.e. if two elements simultaneously specify the same [=view transition name=])
+ then the [=view transition=] will abort.
+
+
+ Note: For the purposes of this API,
+ if one element has [=view transition name=] ''foo'' in the old state,
+ and another element has [=view transition name=] ''foo'' in the new state,
+ they are treated as representing different visual states of the same element,
+ and will be paired in the [=view transition tree=].
+ This may be confusing, since the elements themselves are not necessarily referring to the same object,
+ but it is a useful model to consider them to be visual states of the same conceptual page entity.
+
+ If the element’s [=principal box=] is [=fragmented=],
+ [=skips its contents|skipped=],
+ or [=element-not-rendered|not rendered=],
+ this property has no effect.
+ See [[#algorithms]] for exact details.
+
+
+ To get the document-scoped view transition name for an {{Element}} |element|:
+
+ 1. Let |scopedViewTransitionName| be the [=computed value=] of 'view-transition-name' for |element|.
+
+ 1. If |scopedViewTransitionName| is associated with |element|'s [=node document=], then return |scopedViewTransitionName|.
+
+ 1. Otherwise, return ''view-transition-name/none''.
+
+
+### Rendering Consolidation ### {#named-and-transitioning}
+
+ [=/Elements=] [=captured in a view transition=] during a [=view transition=]
+ or whose 'view-transition-name' [=computed value=] is not ''view-transition-name/none'' (at any time):
+ - Form a [=stacking context=].
+ - Are [[css-transforms-2#grouping-property-values|flattened in 3D transforms]].
+ - Form a [=backdrop root=].
+
+## Isolating Scoped View Transition Names: the ''contain/view-transition'' containment value ## {#contain-view-transition}
+
+
+ Name: contain
+ New Values: view-transition
+
+
+ The ''contain: view-transition'' value establishes view transition name containment on an element.
+ This causes any [=document-scoped view transition names=] to only be visible
+ for [=view transitions=] scoped to this element or its descendants.
+
+ Note: Most elements running a [=scoped view transition=]
+ should use [=view transition name containment=],
+ to ensure that their [=document-scoped view transition names=]
+ don't accidentally interfere with other [=scoped view transitions=].
+ Otherwise, two similar elements running the same [=scoped view transition=],
+ expecting the same-named descendants,
+ will see each other's names and abort
+ (since [=view transitions=] don't allow multiple elements to have the same 'view-transition-name').
+
+
+# Pseudo-elements # {#pseudo}
+
+## Pseudo-element Trees ## {#pseudo-root}
+
+ Note: This is a general definition for trees of pseudo-elements. If other features need this behavior, these definitions will be moved to [[css-pseudo-4]].
+
+ A pseudo-element root is a type of [=tree-abiding pseudo-element=] that is the [=tree/root=] in a [=tree=] of [=tree-abiding pseudo-elements=],
+ known as the pseudo-element tree.
+
+ The [=pseudo-element tree=] defines the document order of its [=tree/descendant=] [=tree-abiding pseudo-elements=].
+
+ When a [=pseudo-element=] [=tree/participates=] in a [=pseudo-element tree=],
+ its [=originating pseudo-element=] is its [=tree/parent=].
+
+ If a [=tree/descendant=] |pseudo| of a [=pseudo-element root=] has no other [=tree/siblings=],
+ then '':only-child'' matches that |pseudo|.
+
+ Note: This means that `::view-transition-new(ident):only-child` will only select `::view-transition-new(ident)` if the parent `::view-transition-image-pair(ident)` contains a single [=tree/child=].
+ As in, there is no [=tree/sibling=] `::view-transition-old(ident)`.
+
+## View Transition Pseudo-elements ## {#view-transition-pseudos}
+
+ The visualization of a [=view transition=]
+ is represented as a [=pseudo-element tree=]
+ called the view transition tree
+ composed of the view transition pseudo-elements defined below.
+ This tree is built during the [=setup transition pseudo-elements=] step,
+ and is rooted under a ''::view-transition'' pseudo-element
+ [=originating element|originating=] from the {{ViewTransition}}'s [=ViewTransition/root element=].
+ All of the [=view transition pseudo-elements=] are selected
+ from their [=ultimate originating element=],
+ the {{ViewTransition}}'s [=ViewTransition/root element=].
+
+ The [=view transition tree=] is not exposed to the accessibility tree.
+
+
+ For example,
+ even though a ''::view-transition-group()'' pseudo-element
+ is nested underneath its parent ''::view-transition'' pseudo-element
+ for styling and layout purposes,
+ it's selected directly on the element hosting the {{ViewTransition}}:
+ if you'd use ''.foo::view-transition'',
+ you'll also use ''.foo::view-transition-group()''.
+
+ Doing ''.foo::view-transition::view-transition-group()'' is incorrect,
+ and won't select anything.
+
+
+
+ Once the user-agent has captured both the “old” and “new” states of the document,
+ it creates a structure of pseudo-elements like the following:
+
+ ```
+ ::view-transition
+ ├─ ::view-transition-group(name)
+ │ └─ ::view-transition-image-pair(name)
+ │ ├─ ::view-transition-old(name)
+ │ └─ ::view-transition-new(name)
+ └─ …other groups…
+ ```
+
+ Each element with a 'view-transition-name' is captured separately,
+ and a ''::view-transition-group()'' is created for each unique 'view-transition-name'.
+
+ For convenience, the [=document element=] is given the 'view-transition-name' "root" in the [[#ua-styles|user-agent style sheet]].
+
+ Either ''::view-transition-old()'' or ''::view-transition-new()'' are absent in cases where the capture does not have an “old” or “new” state.
+
+ Each of the pseudo-elements generated can be targeted by CSS in order to customize its appearance,
+ behavior and/or add animations.
+ This enables full customization of the transition.
+
+
+### Named View Transition Pseudo-elements ### {#named-view-transition-pseudo}
+
+ Several of the [=view transition pseudo-elements=]
+ are named view transition pseudo-elements,
+ which are [=functional pseudo-element|functional=] [=tree-abiding pseudo-element|tree-abiding=] [=view transition pseudo-elements=]
+ associated with a [=view transition name=].
+ These pseudo-elements take a <> as their argument,
+ and their syntax follows the pattern:
+
+