<pre class='metadata'>
Title: CSS Anchor Positioning Module Level 2
Shortname: css-anchor-position
Level: 2
!Delta Spec: yes
Status: ED
Prepare for TR: no
Group: csswg
Work Status: exploring
ED: https://drafts.csswg.org/css-anchor-position-2/
TR: https://www.w3.org/TR/css-anchor-position-2/
Editor: Tab Atkins-Bittner, Google, http://xanthir.com/contact/, w3cid 42199
Editor: Elika J. Etemad / fantasai, Apple, http://fantasai.inkedblade.net/contact, w3cid 35400
Editor: Ian Kilpatrick, Google, w3cid 73001

Abstract: This specification defines [=anchor positioning=],
	where an positioned element can size and position itself
	relative to one or more anchor elements elsewhere on the page.
</pre>

<pre class=link-defaults>
	spec:css-conditional-5; type:dfn; text:container query
	spec:css-conditional-5; type:property; text:container-type
	spec:css-conditional-5; type:value; text:size
	spec:css-conditional-5; type:dfn; text:query container
	spec:css-conditional-5; type:at-rule; text:@container
	spec:css-conditional-5; type:type; text:<query-in-parens>
	spec:css-conditional-5; type:dfn; text:container feature
</pre>


<h2 id="delta">Delta specification</h2>

	This is a delta specification, meaning that it currently contains
	only the differences from CSS Anchor Positioning Level 1 [[!CSS-ANCHOR-POSITION-1]].

<h2 id="anchored-container-queries">Container Queries for Anchor Positioning</h2>

	This section extends [=container queries=] from [[css-conditional-5]] to allow
	querying certain aspects of elements using [=anchor positioning=].

<h3 id="container-type-anchored">Extending 'container-type' with ''anchored''</h3>

	This specification extends the ''container-type'' property defined in
	[[css-conditional-5#container-type]] with a new	''anchored'' keyword.
	''anchored'' can be combined with existing container types such as
	''container-type/scroll-state'' and ''container-type/size'':

	<pre class="prod">normal | [ [ size | inline-size ] || scroll-state || anchored ]</pre>

	<dl dfn-type=value dfn-for=container-type>
		<dt><dfn>anchored</dfn>
		<dd>
			Establishes a [=query container=] for [=container queries=],
			allowing for descendants of an anchor positioned element to be styled
			based on certain features of the anchoring. 
			(Currently, limited to which of the 'position-try-fallbacks' are applied, if any.)

			The ''anchored'' container-type applies [=style containment=] to the
			[=query container=].

		<div class=note>
			NOTE: [=Style containment=] is necessary to avoid a layout cycle for the
			following case using [=counters=]:
			- We have an ''anchored'' container
			- A [=counter=] is incremented by a descendant of the anchored container
				based on a fallback query.
			- An [=in-flow=] element, following the anchored container in tree order,
				generates content, with the counter, affecting the size of the [=in-flow=]
				element.
			- The [=in-flow=] element affects the position / size of the
				<l spec=css-anchor-position-1>[=anchor element=]</l>. In fact,
				the [=in-flow=] may be the <l spec=css-anchor-position-1>[=anchor element=]</l>
				itself.
			- The changed position / size of the <l spec=css-anchor-position-1>[=anchor element=]</l>
				may change which fallback is chosen, which in turn affects the anchored query evaluation,
				hence the counter increment.
		</div>
	</dl>

	<div class=example>
		A container can be just ''anchored'', or combined with other container types:

		<pre class=lang-css>
		#anchored { container-type: anchored; }
		#anchored-size { container-type: anchored inline-size; }
		</pre>
	</div>

<h3 id="container-rule-anchored">Extending ''@container'' syntax for ''anchored'' queries</h3>

	To query an ''anchored'' container, a new <code>anchored()</code> function is
	added to the ''@container'' syntax. It extends the container query syntax by adding the
	following production to the '<<query-in-parens>>' grammar:

	<pre class="prod def">
		<<query-in-parens>> = ...
											| anchored( <<anchored-query>> )

		<dfn><<anchored-query>></dfn> = not <<anchored-in-parens>>
										| <<anchored-in-parens>> [ [ and <<anchored-in-parens>> ]* | [ or <<anchored-in-parens>> ]* ]
										| <<anchored-feature>>
		<dfn><<anchored-in-parens>></dfn> = ( <<anchored-query>> )
												| ( <<anchored-feature>> )
												| <<general-enclosed>>
	</pre>

<h3 id="anchored-container">Anchored Container Features</h3>

<h4 id="anchored">
Applied 'position-try-fallbacks': the '@container/fallback' feature</h4>

	<pre class="descdef mq">
		Name: fallback
		For: @container
		Value: none | [ [<<dashed-ident>> || <<try-tactic>>] | <<position-area-query>> ]
		Type: discrete
	</pre>

	The '@container/fallback' [=container feature=] queries whether an anchor
	positioned element has any of its computed 'position-try-fallbacks' options
	applied.

	<dl dfn-type=value dfn-for="@container/fallback">
		<dt><dfn>none</dfn>
		<dd>
			The ''container-type/anchored'' container does not have any 'position-try-fallbacks'
			applied.
		<dt><<dashed-ident>> || <<try-tactic>></dt>
		<dd>
			The ''container-type/anchored'' container matches a combination of
			<<dashed-ident>> and <<try-tactic>> applied from 'position-try-fallbacks'.
			If any of the ''<<dashed-ident>>'' or ''<<try-tactic>>'' are left out of
			the query value, they need to be left out in the applied value from
			'position-try-fallbacks', and vice versa, in order to match.

			The ''<<dashed-ident>>'' try rule name is not considered to be a
			[=tree-scoped name=] for the sake of matching '@container/fallback'.

			The order of <<try-tactic>>s is significant. For instance
			<code>flip-start flip-block</code> is not the same as
			<code>flip-block flip-start</code>. Hence, the order must match for
			'@container/fallback' queries.
		<dt><<position-area-query>></dt>
		<dd>
			The ''container-type/anchored'' container has a ''<<position-area>>''
			applied from 'position-try-fallbacks'. The query matches if the applied
			''<<position-area>>'' from the fallback and the query value represent the
			same physical area. That is, ''<position-area-query>/block-start'' will match
			''position-area/top'' when the 'writing-mode' is ''writing-mode/horizontal-tb''.

			A query value of ''<position-area-query>/any'' always matches for the given axis.
	</dl>

	<div class=example>
		Add an arrow whose direction depends on whether an element is positioned to
		the left or right of its anchor:

		<pre class=lang-css>
		#container {
			container-type: anchored;
			position: absolute;
			position-anchor: --a;
			position-area: left;
			position-try-fallbacks: right;
			&::before { content: ">"; }

			@container anchored(fallback: right) {
				&::before { content: "<"; };
			}
		}
		</pre>
	</div>

	<div class=example>
		Matching named fallback option with '<<try-tactic>>':

		<pre class=lang-css>
		.anchored {
			container-type: anchored;
			position-try-fallbacks: --foo, --bar flip-inline;

			@container anchored(fallback: --bar flip-inline) {
				/* Applies if the '--bar' fallback applies */
				.inner { background-color: green; }
			}
			@container anchored(fallback: --bar) {
				/* Does not apply because the try-tactic also must match */
				.inner { background-color: red; }
			}
		}
		</pre>
	</div>

	<div class=example>
		Matching '<<position-area>>' fallback option in vertical 'writing-mode':

		<pre class=lang-css>
		.anchored {
			container-type: anchored;
			position-anchor: --a;
			position-try-fallbacks: right;
			writing-mode: vertical-rl;

			@container anchored(fallback: self-block-start) {
				/* Applies if the 'right' fallback applies since block-start is 'right'
						in 'vertical-rl'. */
				.inner { background-color: green; }
			}
		}
		</pre>
	</div>

	<div class=example>
		Matching '<<position-area>>' fallback option with ''<position-area-query>/any'':

		<pre class=lang-css>
		.anchored {
			container-type: anchored;
			position-anchor: --a;
			position-try-fallbacks: bottom right;
			writing-mode: vertical-rl;

			@container anchored(fallback: bottom any) {
				/* Applies because 'any' matches 'right'. */
				.inner { color: lime; }
			}
			@container anchored(fallback: right) {
				/* Applies because implicit 'any' in the vertical axis matches 'bottom'. */
				.inner { background-color: green; }
			}
		}
		</pre>
	</div>

<h4 id="position-area-query-syntax">
Syntax of <<position-area-query>> Values</h4>

Values for querying position-area fallbacks have the same syntax as <<position-area>>,
with an additional ''any'' keyword added to every production:

<pre class=prod>
<dfn>&lt;position-area-query></dfn> = [
	[ left | center | right | span-left | span-right
	| x-start | x-end | span-x-start | span-x-end
	| self-x-start | self-x-end | span-self-x-start | span-self-x-end
	| span-all | any ]
	||
	[ top | center | bottom | span-top | span-bottom
	| y-start | y-end | span-y-start | span-y-end
	| self-y-start | self-y-end | span-self-y-start | span-self-y-end
	| span-all | any ]
|
	[ block-start | center | block-end | span-block-start | span-block-end | span-all | any ]
	||
	[ inline-start | center | inline-end | span-inline-start | span-inline-end
	| span-all | any ]
|
	[ self-block-start | center | self-block-end | span-self-block-start
	| span-self-block-end | span-all | any ]
	||
	[ self-inline-start | center | self-inline-end | span-self-inline-start
	| span-self-inline-end | span-all | any ]
|
	[ start | center | end | span-start | span-end | span-all | any ]{1,2}
|
	[ self-start | center | self-end | span-self-start | span-self-end | span-all | any ]{1,2}
]
</pre>

<dl dfn-type=value dfn-for="<position-area-query>">
	: <dfn>any</dfn>
	:: ''any'' can be used for one or both of the axes. It is ambiguous about which
		axis it refers to, and is handled like other ambiguous keywords for
		'<<position-area>>' such as ''start'' or ''center'' when it comes to assigning
		axis and duplicating single keyword values.

	: <dfn>start</dfn>, <dfn>end</dfn>, <dfn>self-start</dfn>, <dfn>self-end</dfn>
	: <dfn>top</dfn>, <dfn>bottom</dfn>, <dfn>left</dfn>, <dfn>right</dfn>
	: <dfn>y-start</dfn>, <dfn>y-end</dfn>, <dfn>self-y-start</dfn>, <dfn>self-y-end</dfn>
	: <dfn>x-start</dfn>, <dfn>x-end</dfn>, <dfn>self-x-start</dfn>, <dfn>self-x-end</dfn>
	: <dfn>block-start</dfn>, <dfn>block-end</dfn>, <dfn>self-block-start</dfn>, <dfn>self-block-end</dfn>
	: <dfn>inline-start</dfn>, <dfn>inline-end</dfn>, <dfn>self-inline-start</dfn>, <dfn>self-inline-end</dfn>
	: <dfn>center</dfn>
	: <dfn>span-start</dfn>, <dfn>span-end</dfn>, <dfn>span-self-start</dfn>, <dfn>span-self-end</dfn>
	: <dfn>span-top</dfn>, <dfn>span-bottom</dfn>, <dfn>span-left</dfn>, <dfn>span-right</dfn>
	: <dfn>span-y-start</dfn>, <dfn>span-y-end</dfn>, <dfn>span-self-y-start</dfn>, <dfn>span-self-y-end</dfn>
	: <dfn>span-x-start</dfn>, <dfn>span-x-end</dfn>, <dfn>span-self-x-start</dfn>, <dfn>span-self-x-end</dfn>
	: <dfn>span-block-start</dfn>, <dfn>span-block-end</dfn>, <dfn>span-self-block-start</dfn>, <dfn>span-self-block-end</dfn>
	: <dfn>span-inline-start</dfn>, <dfn>span-inline-end</dfn>, <dfn>span-self-inline-start</dfn>, <dfn>span-self-inline-end</dfn>
	: <dfn>span-all</dfn>
	:: See respective definitions for '<<position-area>>'.
</dl>

If only a single keyword is given, '<<position-area-query>>' behaves as if the
second keyword is ''any'' if the given keyword is unambigous about its axis.
This is different from how single keywords are handled for '<<position-area>>',
which behaves as if the second keyword is ''span-all''.
Otherwise, '<<position-area-query>>' behaves as '<<position-area>>'
when it comes to assigning axes.


Security Considerations {#sec}
=======================

No Security issues have been raised against this document.

Privacy Considerations {#priv}
======================

No Privacy issues have been raised against this document.
