Skip to content

Commit 471d90f

Browse files
committed
[css-anchor-position-1] Add 'inset-area' property. #9145
1 parent 05c7c9f commit 471d90f

File tree

2 files changed

+222
-15
lines changed

2 files changed

+222
-15
lines changed

css-anchor-position-1/Overview.bs

Lines changed: 222 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -347,12 +347,219 @@ Anchor-Based Positioning {#positioning}
347347
========================
348348

349349
An [=absolutely-positioned=] element
350-
can use the <dfn>anchor()</dfn> function
351-
in its [=inset properties=]
352-
to refer to the position of one or more [=anchor elements=].
353-
The ''anchor()'' function resolves to a <<length>>,
354-
exactly what is needed to position the given inset edge
355-
to the specified position on the [=anchor element=].
350+
can position itself relative to one or more [=anchor elements=] on the page.
351+
352+
The 'inset-area' function offers a convenient grid-based concept
353+
for positioning relative to the [=default anchor element=];
354+
for more complex positioning or positioning relative to multiple elements,
355+
the ''anchor()'' function can be used in the [=inset properties=]
356+
to explicitly refer to edges of an [=anchor element=].
357+
358+
The 'inset-area' Property {#inset-area}
359+
---------------------------------------
360+
361+
<pre class=propdef>
362+
Name: inset-area
363+
Value: none | <inset-area-span> [ / <inset-area-span> ]?
364+
Initial: none
365+
Inherited: no
366+
Applies to: positioned elements with a [=default anchor element=]
367+
Animation type: TBD
368+
</pre>
369+
370+
<pre class=prod>
371+
<dfn>&lt;inset-area-span></dfn> =
372+
[ top || bottom || center ] |
373+
[ left || right || center ] |
374+
[ x-start || x-end || center ] |
375+
[ y-start || y-end || center ] |
376+
[ start || end || center ] |
377+
[ self-start || self-end || center ] |
378+
all
379+
</pre>
380+
381+
Most common use-cases of anchor positioning
382+
only need to worry about
383+
the edges of the positioned element's [=containing block=],
384+
and the edges of the [=default anchor element=].
385+
These lines can be thought of as defining a 3x3 grid;
386+
'inset-area' lets you easily set up the positioned element's [=inset properties=]
387+
by specifying what area of this [=inset-area grid=] you want the positioned element to be in.
388+
Its syntax is:
389+
390+
<dl dfn-for=inset-area dfn-type=value>
391+
: <dfn>none</dfn>
392+
:: The property has no effect.
393+
394+
: <dfn><<inset-area-span>></dfn>
395+
:: Behaves as <css>&lt;inset-area-span> / all</css>,
396+
filling the entire row/column of the grid
397+
indicated by the specified value.
398+
399+
: <dfn><<inset-area-span>> [ / <<inset-area-span>> ]?</dfn>
400+
::
401+
If the element does not have a [=default anchor element=],
402+
or is not an [=absolutely-positioned=] element,
403+
this value has no effect.
404+
405+
Otherwise, the two spans define a rectangular region
406+
of the [=inset-area grid=],
407+
and have the following effects:
408+
409+
1. Any ''top/auto'' [=inset properties=] compute to
410+
the appropriate value
411+
to match the rectangular region.
412+
2. The ''align-self/normal'' value for the [=self-alignment properties=]
413+
behaves as either ''align-self/start'', ''align-self/end'',
414+
or ''align-self/anchor-center'',
415+
depending on the positioning of the region,
416+
to give a good default alignment for the positioned element.
417+
418+
See [[#resolving-spans]] for details on both of these effects.
419+
If the two <<inset-area-span>>s do not define a valid region,
420+
this property is invalid.
421+
</dl>
422+
423+
424+
<h3 id=resolving-spans>
425+
Resolving <<inset-area-span>>s</h3>
426+
427+
The <dfn export>inset-area grid</dfn> is conceptually a 3x3 grid,
428+
composed of four grid lines in each axis.
429+
In order:
430+
431+
* the start edge of the element's [=containing block=]
432+
(aka the position referred to by ''top: 0px;''
433+
or whatever [=inset property=] corresponds to
434+
the start side fo the containing block)
435+
* the ''anchor(start)'' edge of the [=default anchor element=]
436+
* the ''anchor(end)'' edge of the [=default anchor element=]
437+
* the end edge of the element's [=containing block=]
438+
(aka the position referred to by ''bottom: 0px'',
439+
or whatever [=inset property=] is opposite the first one)
440+
441+
Each <<inset-area-span>> specifies 1-3 regions in a given axis of that grid:
442+
the "start" region between the first two of those grid lines;
443+
the "center" region between the center two;
444+
or the "end region" between the last two.
445+
446+
<dl dfn-type=value dfn-for="inset-area, <inset-area-span>">
447+
: <dfn>all</dfn>
448+
:: All three regions of that axis,
449+
spanning the entire breadth of the containing block.
450+
451+
: <dfn>start</dfn>
452+
: <dfn>end</dfn>
453+
: <dfn>self-start</dfn>
454+
: <dfn>self-end</dfn>
455+
: <dfn>center</dfn>
456+
: <dfn>top</dfn>
457+
: <dfn>bottom</dfn>
458+
: <dfn>y-start</dfn>
459+
: <dfn>y-end</dfn>
460+
: <dfn>left</dfn>
461+
: <dfn>right</dfn>
462+
: <dfn>x-start</dfn>
463+
: <dfn>x-end</dfn>
464+
:: Any single keyword refers just to that region in the axis.
465+
466+
Like in ''anchor()'',
467+
''inset-area/start'' and ''inset-area/end''
468+
refer to the writing mode of the element's [=containing block=],
469+
while ''inset-area/self-start'' and ''inset-area/self-end''
470+
refer to the element's own writing mode.
471+
472+
: two keywords
473+
:: Refers to the area spanned by the two indicated regions.
474+
475+
(For example, ''top center'' spans the first two regions,
476+
but ''top bottom'' spans all three.)
477+
478+
: three keywords
479+
:: Refers to all three regions in the axis,
480+
identical to ''inset-area/all''
481+
</dl>
482+
483+
Two spans referring to different axises
484+
thus define a rectangular region of the [=inset-area grid=].
485+
486+
To determine the axises of two spans:
487+
488+
* If a span include a keyword that implies a physical axis
489+
(''inset-area/top'', ''inset-area/x-start'', etc),
490+
that's its axis.
491+
* If both of the spans include a physical keyword,
492+
they must refer to different axises.
493+
If not, then the two spans do not define a valid region.
494+
* If one of the spans include a physical keyword,
495+
and the other doesn't
496+
(it only includes ambiguous keywords,
497+
like ''inset-area/center'' or ''inset-area/start''),
498+
then the other span's axis is perpendicular to the physical one.
499+
* If neither span includes a physical keyword,
500+
the first refers to the [=block axis=]
501+
of the [=containing block=],
502+
and the second to the [=inline axis=].
503+
504+
If the spans define a valid region,
505+
they cause ''top/auto'' values for the [=inset properties=]
506+
to compute to values that will align the [=inset-modified containing block=]
507+
with the boundary of the defined region
508+
on that side.
509+
510+
Each span also implies a default alignment,
511+
which will be used if the [=self-alignment property=] on the element
512+
is ''align-self/normal'':
513+
514+
* If the span includes the center region,
515+
the default alignment in that axis is ''align-self/anchor-center''.
516+
* Otherwise, it's the opposite of the region it specifies:
517+
if it's specifying the "start" region,
518+
the default alignment in that axis is ''align-self/end''; etc.
519+
520+
<div class=example>
521+
For example, assuming an English-equivalent writing mode (horizontal-tb, ltr),
522+
then the spans ''start center / top'' resolve to
523+
the "start" region of the vertical axis,
524+
and the "start" and "center" regions of the horizontal axis,
525+
which will compute the [=inset properties=] to:
526+
527+
<pre highlight=css>
528+
/* "auto" computes to: */
529+
top: 0px;
530+
bottom: anchor(start);
531+
left: 0px;
532+
right: anchor(end);
533+
/* "normal" behaves as: */
534+
align-self: end;
535+
justify-self: anchor-center;
536+
</pre>
537+
538+
In other words, its [=inset-modified containing block=]
539+
will be the pink region in the below diagram,
540+
and the positioned element
541+
will be centered against the top edge of the anchor.
542+
543+
<figure>
544+
<img src="images/inset-area-example.png" width=400>
545+
<figcaption>
546+
An example of ''inset-area: start center / top'' positioning.
547+
</figcaption>
548+
</div>
549+
550+
Note: While the [=default anchor element=] can actually be positioned
551+
outside of the positioned element's [=containing block=],
552+
for the purpose of 'inset-area'&apos;s effects
553+
it's considered to be within the block,
554+
so the grid lines always have the described order.
555+
That is, even if the anchor is entirely below the containing block,
556+
a ''inset-area/bottom'' span will still cause the element to behave as
557+
''top: anchor(end); bottom: 0px; align-content: start;'';
558+
the rules for handling over-constrained [=inset properties=]
559+
will resolve the contradiction.
560+
561+
562+
356563

357564
The ''anchor()'' Function {#anchor-pos}
358565
---------------------------------------------------
@@ -415,7 +622,7 @@ The ''anchor()'' function has three arguments:
415622

416623
Note: These are only usable in the [=inset properties=]
417624
in the matching axis.
418-
For example, ''left'' is usable in 'left', 'right',
625+
For example, ''anchor()/left'' is usable in 'left', 'right',
419626
or the logical [=inset properties=] that refer to the horizontal axis.
420627

421628
: <dfn>start</dfn>
@@ -426,18 +633,18 @@ The ''anchor()'' function has three arguments:
426633
in the same axis as the [=inset property=] it's used in,
427634
by resolving the keyword against the [=writing mode=]
428635
of either the positioned element
429-
(for ''self-start'' and ''self-end'')
636+
(for ''anchor()/self-start'' and ''anchor()/self-end'')
430637
or the positioned element's containing block
431-
(for ''start'' and ''end'').
638+
(for ''anchor()/start'' and ''anchor()/end'').
432639

433640
: <dfn><<percentage>></dfn>
434641
: <dfn>center</dfn>
435642
:: Refers to a position
436-
a corresponding percentage between the ''start'' and ''end'' sides,
437-
with ''0%'' being equivalent to ''start''
438-
and ''100%'' being equivalent to ''end''.
643+
a corresponding percentage between the ''anchor()/start'' and ''anchor()/end'' sides,
644+
with ''0%'' being equivalent to ''anchor()/start''
645+
and ''100%'' being equivalent to ''anchor()/end''.
439646

440-
''center'' is equivalent to ''50%''.
647+
''anchor()/center'' is equivalent to ''50%''.
441648

442649
* the optional <<length-percentage>> final argument is a fallback value,
443650
specifying what the function should resolve to
@@ -687,7 +894,7 @@ for non-''justify-self/auto'' alignment values.
687894

688895
If the element is not [=absolutely positioned=],
689896
or does not have a [=default anchor element=],
690-
this value behaves as ''center''
897+
this value behaves as ''<self-position>/center''
691898
and has no additional effect on how [=inset properties=] resolve.
692899

693900
Issue: Do we want to hook the "try to stay in the IMCB" behavior to safe vs unsafe?
@@ -784,7 +991,7 @@ only if all the following conditions are true:
784991
on an [=absolutely-positioned=] element.
785992
* If its <<anchor-side>> specifies a physical keyword,
786993
it's being used in an [=inset property=] in that axis.
787-
(For example, ''left'' can only be used in 'left', 'right',
994+
(For example, ''anchor()/left'' can only be used in 'left', 'right',
788995
or a logical [=inset property=] in the horizontal axis.)
789996
* The result of determining the [=target anchor element=] is not nothing when
790997
given the querying element as the element it's used on,
56.1 KB
Loading

0 commit comments

Comments
 (0)