Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-anchor-position-1] Can we clarify the inset-area syntax? It can be confusing to read and reason about. #9862

Closed
mirisuzanne opened this issue Jan 25, 2024 · 18 comments

Comments

@mirisuzanne
Copy link
Contributor

mirisuzanne commented Jan 25, 2024

Overall, I really like the mental model behind the inset-area property, as a quick way to set relative insets. But looking at the syntax today with @una, there were a few aspects of the syntax that make it hard to read and reason about. In my mind the primary issue is the overlap between:

  • two axis values, which can be listed in either order
  • two values within an axis for spanning multiple areas
  • for center and the logical values, names are the same on either axis
  • for single values, the implied axis is all

That leads to some interesting situations:

  • simple center value becomes center / all rather than center / center
  • center / all is not clear unless you know which axis comes first by default (but not always)
  • left / center and center / left mean the same thing, but start / center and center / start are different
  • bottom center is not the center of the bottom area, that's bottom / center (or center / bottom etc)

There's two changes that I think would help, while leaving some flexibility:

  • Clarify spans with a function syntax (span(left, center)). This would reduce the top-level space to two values without needing the / divider. (It might also be useful for grid to support a span() function for spanning multiple grid areas.)
  • I expected single axis-ambiguous values to duplicate for the cross-axis: so that the bare keywords start, end, center, self-start, and self-end resolve to eg start / start and center / center etc. (clarification: This helps with the issue where e.g. center first can mean either axis, but center alone always means one specific axis.)

Thoughts?

@una
Copy link
Contributor

una commented Jan 29, 2024

+1, as @mirisuzanne mentioned, I started exploring inset-area positioning and found the syntax very confusing thus far, especially with a single value converting to / all and not doubling, as well as the order being interchangable.

Screenshot 2024-01-29 at 5 09 48 PM

@fantasai
Copy link
Collaborator

fantasai commented Feb 2, 2024

I think we should try to go for consistency with <position> in some fashion (recognizing that this is a separate problem with its own syntax space but still).

@tabatkins
Copy link
Member

tabatkins commented Feb 2, 2024

All right, Elika and I discussed this today, and agree the syntax can be improved a bit.

First, to let us remove the slash (getting closer to <position>, as Elika just suggested), we have two possible syntax suggestions:

<inset-area-alpha> = [
  [ left | center | right | center-left | center-right
  | x-start | x-end | center-x-start | center-x-end 
  | x-self-start | x-self-end | center-x-self-start | center-x-self-end 
  | all ]
  &&
  [ top | center | bottom | center-top | center-bottom
  | y-start | y-end | center-y-start | center-y-end
  | y-self-start | y-self-end | center-y-self-start | center-y-self-end 
  | all ]
|
  [ block-start | center | block-end | center-block-start | center-block-end
  | self-block-start | self-block-end | center-self-block-start | center-self-block-end 
  | all ]
  &&
  [ inline-start | center | inline-end | center-inline-start | center-inline-end ]
  | self-inline-start | self-inline-end | center-self-inline-start | center-self-inline-end 
  | all ]
|
  [ start | center | end | center-start | center-end | all ]{1, 2}
|
  [ self-start | center | self-end | center-self-start | center-self-end | all ]{1, 2}
]

<inset-area-beta> = [
  [ left | center | right | span( left || center || right )
  | x-start | x-end | span( x-start || center || x-end )
  | x-self-start | x-self-end | span( x-self-start || center || x-self-end )
  | all ]
  &&
  [ top | center | bottom | span( top || center || bottom )
  | y-start | y-end | span( y-start || center || y-end )
  | y-self-start | y-self-end | span( y-self-start || center || y-self-end )
  | all ]
|
  [ block-start | center | block-end | span( block-start || center || block-end )
  | self-block-start | self-block-end | span( self-block-start || center || self-block-end )
  | all ]
&&
  [ inline-start | center | inline-end | span( inline-start || center || inline-end )
  | self-inline-start | self-inline-end | span( self-inline-start || center || self-inline-end)
  | all ]
|
  [ start | center | end | span( start || center || end ) | all ]{1, 2}
|
  [ self-start | center | self-end | span( self-start || center || self-end ) | all ]{1,2}
]

In alpha, we just specify the two-region values with a dashed center-* keyword, so if you want to fill the left and center columns, you write center-left.

In beta, we have the span() function, which takes two keywords and spans between them, so you'd instead right span(left center).
(The grammar is a little loose above, for readability; it would actually need to be span( [left && [center | right]] | [right && [center | left]] ), to guarantee two keywords get specified.)

In either case, the 2-track values are now single components, so we no longer need the slash. To fill just the upper-left and upper-center regions, you could say center-left top or top center-left (or equivalently, span(left center) top, for beta).

We think we mildly prefer the dashed version over the span() version, but will leave the choice up to the WG.


For the "single-value is a little confusing", we agree, and think Miriam's suggestion is reasonable. So:

Single keyword defaults other axis to:
* duplication if keyword is axis-ambiguous (start/self-start/center/end/self-end)
* all in all other cases

And then we'd probably want to sync this with <position>. Currently, we just disallow saying start by itself (you must specify two keywords if they're axis-ambiguous), but we think it would be reasonable to adopt a similar "duplicate if axis-ambiguous, center otherwise" rule, so background-position: start would be equivalent to start start.

Note that this doesn't solve Mia's bullet point of

center / all is not clear unless you know which axis comes first by default (but not always)

But that's an issue with all axis-ambiguous syntaxes. Learning that the order is always block->inline will continue to be correct across CSS.

@tabatkins
Copy link
Member

Una's three examples would thus be bottom, center-bottom, and bottom center

@fantasai
Copy link
Collaborator

fantasai commented Feb 3, 2024

But that's an issue with all axis-ambiguous syntaxes. Learning that the order is always block->inline will continue to be correct across CSS.

But in the proposed syntax above, in sync with <position>, we introduced the axis-specific keywords (block-*/inline-*) so that you don't have to remember the order.

@mirisuzanne
Copy link
Contributor Author

I like this solution, and also lean towards the alpha hyphenated approach.

I agree the axis-ordering can be learned. My main concern was the stacking of those implicit rules – with an ambiguous keyword treated as a positional axis keyword when the position is already somewhat ambiguous. This change removes the stacking of ambiguities. :)

tabatkins added a commit that referenced this issue Feb 6, 2024
@tabatkins
Copy link
Member

Okay, inset-area-alpha committed. ^_^

@tabatkins tabatkins reopened this Feb 6, 2024
@tidoust
Copy link
Member

tidoust commented Feb 6, 2024

@tabatkins The new syntax is imbalanced because the closing bracket at the end of line 400 is already closed at the end of line 398:

[ inline-start | center | inline-end | center-inline-start | center-inline-end ]
| self-inline-start | self-inline-end | center-self-inline-start | center-self-inline-end
| all ]

Not sure where the closing bracket needs to go, I let you sort that out ;)

Also, the Value Definition Syntax does not mention the possibility of whitespaces being used in multipliers, and at least the CSSTree parser chokes on those at the end of lines 402 and 404.

[ start | center | end | center-start | center-end | all ]{1, 2}

[ self-start | center | self-end | center-self-start | center-self-end | all ]{1, 2}

Could the whitespaces be dropped as well, or should CSS parsers support these whitespaces?

@tabatkins
Copy link
Member

Fixed the brackets. I also removed the whitespace from the multipliers, tho I think the parser should be forgiving of that. ^_^

@una
Copy link
Contributor

una commented Feb 8, 2024

Screenshot 2024-02-13 at 12 47 19 PM

@mirisuzanne
Copy link
Contributor Author

@una On the middle diagram, I think it would be center-block-end instead of block-end center.

@kizu
Copy link
Member

kizu commented Feb 13, 2024

I don't think a specific preference over the exact syntax, but, at the first glance, I would prefer the span() one, mostly due to a personal dislike of long chains of dashed keywords.

For someone not familiar with how things work, things like center-block-end could be confusing, as the two dashes inside represent two different concepts: one is spanning, the another is a connector inside a single keyword.

Looking at it, you'll have to spend a bit of time parsing what is going on: is it “center-block and end”? Is it “center, block, and end?“ Is it “center and block-end”?

With experience, you'd probably learn that we have these “block-end”-like entities in CSS, but I feel that this invites more cognitive load required to understand the keywords than might be necessary.

@una
Copy link
Contributor

una commented Feb 13, 2024

@una On the middle diagram, I think it would be center-block-end instead of block-end center.

Good catch, updated

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-anchor-position-1] Can we clarify the `inset-area` syntax? It can be confusing to read and reason about..

The full IRC log of that discussion <bramus> TabAtkins: (shows spec with grammar)
<bramus> TabAtkins: some time ago una and miriam found that the inset-area property is confusing to read and write
<bramus> TabAtkins: they came together and wrote up a few suggestions
<bramus> TabAtkins: fantatasai and i looked into and think they are quite right
<bramus> fantasai: we came up with some options
<bramus> TabAtkins: first one is inset-area-alpha which is what is in the spec
<bramus> nsull: do you have an example?
<bramus> TabAtkins: see the thread: examples by una
<bramus> TabAtkins: were also covered in the slides
<bramus> TabAtkins: under i-a-a you would write bottom, center-bottom or bottom center
<bramus> TabAtkins: they are all equivalent
<bramus> astearns: clarify?
<bramus> TabAtkins: one keyword is the row, the other the column
<bramus> fantasai: orig concept had a slash to divide both
<bramus> fantasai: you had 9 grid, and keyword would say which are you want to cover. very simple if you want 1 part of the grid: keywords and slash in between
<bramus> nsull: so top left?
<bramus> fantasai: top / left
<bramus> fantasai: but with multiple slots there would 2 keywords on one part of the slash
<astearns> old spec: left center / top
<bramus> TabAtkins: example in old spec: `left center / top`
<bramus> TabAtkins: what spec curr says is that would be `center-left top`
<bramus> TabAtkins: or flip the order, doesnt matter
<bramus> fantasai: dont care about slash vs space vs hyphnes
<jensimmons> q+
<bramus> fantasai: issue was about not liking the slash and needing to combine keywords
<bramus> fantasai: so thats why we need the hyphen now
<bramus> fantasai: or we need to introduce some bracketting syntax: span() or [] or …
<bramus> … to make clear that you have 2 units: 1 for each axis
<bramus> TabAtkins: with span, you could do span(left center)
<astearns> ack jensimmons
<bramus> jensimmons: getting rid of the slash seems confusing
<bramus> … and center is valid for both axis
<bramus> … you dont really know which direction
<vmpstr> q+
<bramus> … hyphenating them can group them indeed, but there’s nothing else in css that does that
<astearns> I am liking the named functions to show what the keywords are for
<bramus> … slash came from grid: grid-col: 3 /4
<bramus> … the slash delineates stuff
<kbabbitt> q+
<bramus> … dont know why the slash wasnt liked
<bramus> … still kind like it
<bramus> +1
<bramus> miriam: didnt raise issues about the slash
<bramus> … proposals happened to remove the slash
<bramus> … rest fo syntax was concfusing
<nicole> q+
<bramus> TabAtkins: once you remove, you dont need another separator
<bramus> … only use slash sparringly in css
<bramus> miriam: i found 'center left' confusing
<bramus> … is it a span(center left) or center row and left column
<bramus> TabAtkins: (clarifies on example)
<bramus> miriam: the slash only gives you htat if you are explicit about everything
<bramus> … (missed)
<bramus> … you have to know if there is an implied slash
<bramus> … vs one value of center+left
<bramus> TabAtkins: when doing center left one would be col and row
<astearns> ack vmpstr
<bramus> vmpstr: confused by 'center-bottom' and 'bottom center'
<bramus> … could this be a shorthand with al longhand like inset-row and inset-column?
<bramus> … with area its not really clear which is which (row or col)
<bramus> TabAtkins: curr spec now resembels bg-pos
<bramus> … unless you need to fill 2 rows or cols you need the dashed keywords
<bramus> … with nly 1 you get the current keywords
<bramus> … can also not use the inset-earea and use trbl props
<florian> q+
<bramus> fantasai: if you need only 2 tracks then you need new keywords. not a problem for 1 or 3 (all)
<bramus> … had resolved on syntax for bg-pos 4 which includes all logical keywords
<miriam> q+
<bramus> … both like block-start inline-start type but also x-start and y-start
<bramus> … that you can indicate the axies
<bramus> … for convenience you can do start start or end end
<bramus> … that syntax is in one of the issues
<fantasai> -> https://github.com//issues/549#issuecomment-1823607623
<astearns> ack kbabbitt
<una> q+
<bramus> kbabbitt: am I missing sth but wiotu slash `center-start all` is that left chunks or top ones?
<bramus> TabAtkins: neither tell you what axis you are on
<bramus> … we fall back to standard block and then inline order
<bramus> … so center-start is block
<bramus> … and all is inline
<bramus> … rest of css also follows this order
<bramus> … so you have top 6 cells
<bramus> kbabbitt: so you fallb ack to implicit ordering
<bramus> TabAtkins: only if we can’t really know
<bramus> fantasai: (backs that up)
<bramus> TabAtkins: with dash keywords the order is clear
<fantasai> fantasai: but you could write center-inline-start all, which would make it more obvious
<bramus> kbabbitt: maybe we can come up with some ascii art solution?
<bramus> TabAtkins: intersting for large regions. only have 3x3 here, so might be ok
<astearns> ddack nicole
<astearns> ack nicole
<bramus> nsull: is center a good keyword? maybe middle for top to bottom? to elimiate one of the cetners?
<bramus> TabAtkins: there is precedent for center to be for both axies
<bramus> nsull: syntax looks very confusing, hard on authors. both dashes and slashes I found confusing but dashes might be a bit more clear.
<bramus> TabAtkins: vast majority of cases is 1 row 1 col, and there its not that steep of a learning curve. 1 keyword and the obvious one for each axis
<masonf> One idea for the "two things" keywords: what about adding -and-. So 'center-and-start' or 'center-and-right'.
<bramus> fantasai: I think `bottom center-rigth` is a fairly common one
<bramus> nsull: and `… center-left`
<bramus> fantasai: e.g,. a dropdown that needs to grow out to the side
<bramus> … two col is reasonable common I think
<jensimmons> q+
<jensimmons> q-
<bramus> … we can introduce longer logical keywords
<bramus> … dont love the hyphenated syntax
<bramus> … if we get rid of the slash then we need to do something else
<bramus> … open to other ideas
<bramus> … need consistency with bg position
<bramus> … use same set of keywords
<bramus> qq+
<bramus> nsull: would there be a way to name the most common cases?
<bramus> TabAtkins: specialized keywords are compatible with the current spec
<bramus> astearns: and the combos for authors could be stuffed into a variable
<bramus> nsull: would be interesting to figure out the most common ones so that its easy on authors
<fantasai> scribe+
<astearns> ack bramus
<Zakim> bramus, you wanted to react to nicole
<fantasai> bramus: if inset-area was a shorthand, and the order was fixed, then it would be clearer
<astearns> ack florian
<fantasai> fantasai: which one is the row and which is the column if you use physical keywords and change writing modes?
<bramus> florian: so / has problem what miriam talked about but ohter syntaxes dont
<bramus> … one you called alpha and another one you didnt mention
<bramus> … you seem to have a preference
<astearns> +1 to function names :)
<bramus> … what are downsides ofthat other one>
<bramus> TabAtkins: its more tying: span(…)
<bramus> florian: like this one better
<bramus> TabAtkins: aesthetic decision
<bramus> fantasai: no strong opinion on either
<bramus> astearns: i like the span() too
<bramus> florian: less typing indeedt hef irst, but unclear about the hyphen when explaining/minuting
<emeyer> +1 to Nicole’s point about teaching!
<masonf> q?
<masonf> q+
<astearns> ack miriam
<bramus> TabAtkins: grammaticlaly there are similarly complex (missed)
<bramus> miriam: can get best of both worlds. confusing part is center: what if we said `bottom span-right`
<bramus> … if we take center out of the equaition
<bramus> florian: so `span-rigth` is the same as `center-rgith`
<bramus> miriam: part of confusion is center meaning two things
<chrishtr> xlo,
<bramus> … simpler keywords could fix that
<vmpstr> +1
<bramus> nsull: `span 2`
<bramus> TabAtkins: (missed)
<bramus> miriam: you could say anchor right?
<astearns> s/(missed)/maybe we could use cover?/
<bramus> florian: what about 2 rows and 2 cols?
<astearns> ack una
<bramus> chrishtr: maybe take it back to issue?
<astearns> zakim, close queue
<Zakim> ok, astearns, the speaker queue is closed
<masonf> q-
<bramus> una: important to get right indeed. all want to simplify. first spec was maybe a bit too looose. like changes in v2 as they are more consistent. spaces and slashes were confusing to me, especially with keywords that could be flipped. like idea of `span()` but could be confusing with `span 2` from grid for example
<bramus> … need to see how it interacts with rest of css. `span()` would be clear … a function would do that
<fantasai> bramus: it's confusing to have a function and keyword with the same name
<bramus> astearns: so lets take back to issue
<bramus> TabAtkins: could be get resolution on something?
<bramus> astearns: seems like people didnt mind the slash
<bramus> florian: but the syntax that include the slash had problems
<emeyer> I do not mind the slash, but also do not mind a functional syntax.
<bramus> TabAtkins: I get why center right can be confusing … any other keyword than center could fix indeed
<bramus> fantasai: yes

@mfreed7
Copy link
Contributor

mfreed7 commented Feb 13, 2024

One of the confusing things about the hyphenated names are that they use the same words as single-column/row names, just separated by a hyphen. So "center left" and "center-left" are very similar, which adds confusion. The hyphenated versions all mean two columns or rows. So how about add -and- to emphasize that. E.g.

  • center-and-left
  • center-and-top

etc.

@FremyCompany
Copy link
Contributor

FremyCompany commented Feb 13, 2024

Random thought: what if we give a name to all possible combinations that make sense. There are not many of them.

Horizontal popups:

above (top, all),
above-only (top, center),
above-and-before (top, left+center), above-and-before-only (top, left),
above-and-after (top,center+right), above-and-after-only (top, right).

Ditto with below as a prefix for the bottom row.

Vertical popups:

before (all, left),
before-only (center, left),
before-and-above (top+center, left), before-and-above-only (top, left),
before-and-below (center+bottom, left), before-and-below-only (bottom, left).

Ditto with after as a prefix for the right column.

Dialogs:
For popus that cover the entire anchor, I suspect we can also add

over for (top+center+bottom, left+center+right) and
over-only (center, center).

All the other options look rare to me, and could be achieved with a less intuitive syntax. One option would be "over" followed by a keyword to extend the area to include the related center track(s). This gives the result below:

image

Most combinations have only one unique name with this proposal. Still, the four corner cells do have two names with this proposal (e.g. above-and-after-only and after-and-above-only) but maybe another naming scheme could avoid this (but maybe it's ok though, as the two names have slightly different semantics).

I can imagine stritctly being an appealing alternative to only (but it's a bit longer to type, and usually happens as first word in English, while only is allowed on both sides, but this is a detail).

Another advantage of calling out the options is that "transforms" such as flip-block or flip-inline can be expressed as a mapping as well, which makes them super clear. A clockwise transform can just be specced in the same way, just by listing a mapping from input (e.g. below) to output (e.g. before).

@fantasai
Copy link
Collaborator

fantasai commented Mar 5, 2024

I liked @mirisuzanne's suggestion to replace "center" with "span", so you'd have e.g. bottom span-left instead of bottom center-left.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-anchor-position-1] Can we clarify the `inset-area` syntax? It can be confusing to read and reason about., and agreed to the following:

  • RESOLVED: switching center-* keywords to span-* and all to span-all
The full IRC log of that discussion <keithamus> TabAtkins: changing inset area syntax was discussed at f2f. People didn't like keywords. fantasai and I are weakly in favour of switching to span-left or span-start to indicate center and the other direction
<TabAtkins> `bottom center-left`
<fantasai> used to be `bottom / center left`
<keithamus> TabAtkins: Right now if you wanted to express <select>, it fills the center and right
<emilio> Select element behavior is actually different across platforms :')
<keithamus> TabAtkins: Proposal is more like a background syntax, we use center-* properties to indicate 2 column or 2 row.l
<TabAtkins> `bottom center` vs `bottom-center`
<dbaron> (fantasai's and Tab's irc comments above should be reordered, I think)
<fantasai> maybe we need keywords for platform behaviors...
<keithamus> TabAtkins: These were two extremely different areas being selected
<TabAtkins> `bottom span-left`
<keithamus> TabAtkins: So all center-* words are now span-*
<keithamus> TabAtkins: bottom row, span from center to left columns.
<keithamus> TabAtkins: in terms of number-pad in a 3x3 grid, cells 1 and 2
<keithamus> TabAtkins: unless anyone has a great opinion, I suggest we go with these as a different suggestion. Center being unclear, space or dash when saying out loud, and still is reasonably readable
<keithamus> astearns: I agree this is an improvement
<keithamus> dbaron: it seems less clear to me in the syntax that it's occupying two grid spaces.
<keithamus> TabAtkins: it's spanning, so by definition it covers multiple spaces
<fantasai> keithamus: At GH we have an implementation that uses compass directions
<TabAtkins> keithamus: at github we have an impl that uses compass direction
<TabAtkins> also, for example, `span-bottom span-left` covers 4 cells (4512 on numpad), and can't be written with compasses
<fantasai> https://github.com//issues/9862#issuecomment-1924919417
<keithamus> fantasai: for background position we have very analgous syntax. We can't use compass directions because we have several different coordinate systems to worry about. Start-x, start-y, x and y, and block-start, inline-start, etc. The syntax... there is a lot of keywords.
<keithamus> fantasai: this is a bunch of stuff that can be expressed in background position
<astearns> ack dbaron
<keithamus> dbaron: what's the current syntax for spanning all 3?
<keithamus> TabAtkins: all
<keithamus> TabAtkins: I'd be comfortable switching to span-all.
<keithamus> astearns: Are you uncomfortable with this dbaron?
<miriam> +1 span-all and span-(direction)
<keithamus> dbaron: I'm okay, I just would prefer something clearer
<keithamus> fantasai: I'd like to resolve on something so we can put a stake in the ground and publish a spec
<fantasai> s/I'd like/Can keep the issue open, but I'd like/
<keithamus> PROPOSED RESOLUTION: switching center-* keywords to span-* and all to span-all
<keithamus> RESOLVED: switching center-* keywords to span-* and all to span-all

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Tuesday morning
Development

No branches or pull requests