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-logical] Flow-relative syntax for margin
-like shorthands
#1282
Comments
I agree with the current proposal, a keyword in front of the values. I personally like A couple of points:
|
|
@MurakamiShinyu — I see where you are going with this, but it could potentially become often confused with I think with a keyword such as
|
I admit it's a crazy idea: 'margins' stands for "margin's writing-mode relative shorthand". But there is one advantage: 'margins' is easier to type than 'margin-relative' or 'margin: relative ...'. My concern is that people may feel troublesome to type a lot of 'relative' when css-logical-props becomes widely available. |
I like the idea of !keyword that could be added to any 4-value clockwise shorthand (and their 3-value, 2-value, and 1-value versions). How about just an unadorned
is equivalent to
Adding the |
Why not go the same route as for box-sizing? So something like Then when the support gets common you could just do:
|
Having a I totally agree with @chharvey's comment that Sebastian |
If I got the ticket right (because the opening post doesn't really explain): I think I have already answered via twitter... but I am suggesting transpose again. |
@cork I do like your idea of
One upside would be that you wouldn't have to change the Alas, a recent change of the spec indicates a different order when relative values are used.
So in the example above, by adding Another downside: you would have to have corresponding "mode" properties for the following, which could be a bit much:
|
I suspect I like the I'm concerned though, that this might lead to new CSS properties being defined as physical-first and require |
I like the idea of #1279:
e.g.
|
I have to raise my voice and say that short symbolic like a punctuation ( I'd favour extra logical properties. Aka That is a very clear and easy interface for authors and there is no clash between old properties and new properties. Authors can also use margin and margin-relative independent of each other and thus are not breaking css parsing of older browsers! So I really like @fantasai initial proposal. |
Wow, okay! Here's some responses:
|
Agree with @fantasai. Now I feel original How about
and CSS already has abbreviations in some keywords, e.g., "rl" (for "right to left direction") in |
Sorry; typo in commit message. :/ |
If the keyword route is decided upon, can the syntax allow it to be at the beginning or end of the declaration? Inspired by So for
|
Weird. My comment was posted to the wrong page |
I really don't think we should have If it is to be typed a lot (and really, that is the hope, that authors are considering bi-di and writing mode all the time), then it needs to be very short. I would say no more than 2-3 letters long. I still prefer an unadorned |
margin
-like shorthandsmargin
-like shorthands
I know there are multiple arguments against having a separate property that controls interpretations of shorthands for reasons like implementation difficulty or "action at a distance", but isn't that akin to how I'd imagine anyone who wants to use logical features would be "all in", not needing to set individual "modes" and wanting something like |
@fantasai wrote:
Even if we expect this to become the default mode of assignment for many authors, I would still prefer clarity & readability to typing efficiency, because the latter can be mitigated by code completion and code snippets in authoring tools, and IMHO shouldn't be a major concern (comparing with readability & less surprise for authors who are not familiar with flow-relative properties) when designing a language like CSS. |
I agree strongly with @bradkemper’s comment: this needs to be generic enough that it doesn't get confused with property-specific value spaces, and it also needs to be convenient enough that authors using flow-relative syntaxes are not at a significant ergonomic disadvantage compared to authors using physical syntaxes. Another option would be to have a longer per-declaration !keyword (for clarity) but also a higher-level syntax similar to |
A third option would be to have some other not-currently-used single punctuation character somewhere in the declaration, to indicate flow-relative mapping, e.g.
This is convenient to type and safe for out-of-context quoting, at the cost of being more obscure. |
I missed this discussion but fwiw, if we all agree that |
As I understood the conversation (which did not fully resolve, of course) the concern with using a new property was that it leads to cascade confusion, as |
I don't have a strong opinion between |
What about using a slash margin: 1px 2px 3px 4px; // top, right, bottom, left (respectively)
margin: 1px 2px / 3px 4px; // block-start, block-end, inline-start, inline-end (respectively) The slash would be similar to grid-template syntax, where Fallback values: margin: 1px 2px 3px; // top, horizontal, bottom
margin: 1px 2px / 3px; // block-start, block-end, inline
margin: 1px / 2px 3px; // block, inline-start, inline-end
margin: 1px 2px; // vertical, horizontal
margin: 1px / 2px; // block, inline
margin: 1px; // all (for both physical and logical) |
Any solution that uses the property value to decide between logical and physical, like At parse time we need to know to which longhands a shorthand expands, but due to variables we may not have the value until computed value time. So consider IMO it's simpler to use a flag which is not part of the grammar, like |
Yeah, IMO a new property like Given this is probably a problem that we only need to solve once (in the sense that new properties should just be logical instead), I think I'd rather go for the simple solution (adding new properties) than figuring out a complex one-off solution for this. |
The big downside of the new property is that it very clearly makes the logical variant not the default, and doesn't provide a path towards making them a default. 10 years in, if people want to be using logical-by-default (which I think we should encourage), they still can't use the more obvious & succinct |
New properties could also be named |
Until this situation gets resolved, w3c/csswg-drafts#1282 I don't want to migrate to CSS logical properties just yet.
There's a relevant article from Jeremy Keith this week - Let's Get Logical - about the limitations that currently exist in CSS when trying to write a logical-first site design. |
The CSS Working Group just discussed The full IRC log of that discussion<TabAtkins> Topic: flow-relative syntax for margin-like shorthands<TabAtkins> github: https://github.com//issues/1282 <fantasai> https://github.com//issues/1282#issuecomment-952428897 <fantasai> https://github.com//issues/1282#issuecomment-1105613943 <TabAtkins> miriam: fantasai and I looked at this last year, with Jen <TabAtkins> miriam: CSS was built around physical property - trbl, width/height <TabAtkins> miriam: For various reasons logical props are more resilient, especially with multiple langs <TabAtkins> miriam: Whether that's building it in pruposely, or automated translation <TabAtkins> miriam: It woudl be great if we could move toward a world where flow-relative logical props are the defualt <TabAtkins> miriam: The easier solution is that we just add `-logical` to various props <TabAtkins> miriam: But long-term that feels like a second-class citizen, not the default <TabAtkins> miriam: We'd like to get to a simple, clean way to default to relative <TabAtkins> miriam: Our plan is multi-step, starting with a property-by-property flag of some sort <TabAtkins> miriam: Whether tha'ts a new prop name, a !flag, or something <TabAtkins> miriam: That says "I want this property to be read as logical" <TabAtkins> miriam: And once we've defined that for each property... <TabAtkins> fantasai: Adn we'd add physical equivs so you could explicitly which way, if you wanted <TabAtkins> fantasai: Wouldn't chang the default, just let you be more specific <TabAtkins> miriam: Once defined for all props, we could look at a block-level or even file-level change of the default <r12a> q+ <TabAtkins> miriam: So like an at-rule that switches default to logical for everything in it <TabAtkins> miriam: Or even a file-level switch. <addison> q+ to clarify relationship to rtl vs. ltr <TabAtkins> miriam: Would have to be lexically scoped to the file; separate files shouldn't interact. <r12a> qq+ <TabAtkins> miriam: The second comment fantasai linked is someone just saying "let's add an 's' to the property 'margins' and 'paddings'" <dbaron> Do some of the "property-by-property" mean "declaration-by-declaration"? <TabAtkins> miriam: There's some other syntax approaches that I didn't look at closely <astearns> ack r12a <Zakim> r12a, you wanted to react to dholbert <emilio> q+ <TabAtkins> r12a: You alreayd talked about cascading - I've been using these logical props for a long time as much as possible <TabAtkins> r12a: I've been using them for arabic and hebrew pages, and I've found there are occasionally situations where you really need to leave margin-left in the code, otherwise things break <TabAtkins> r12a: there's not many, but some cases <TabAtkins> r12a: So we should be careful and warn people that if we provide a big switch and say "this'll fix everything" it can break things, too. careful applying it en masse <TabAtkins> miriam: Right. The logical shorthands would likely be in a different order than the physical anyway, so updates would require more than just the flag. <astearns> ack addison <Zakim> addison, you wanted to clarify relationship to rtl vs. ltr <TabAtkins> miriam: So the situation is more like you use this when writing a new file, not adapting an old file. <TabAtkins> addison: I think Richard was saying sometimes you need both so you need both options. <astearns> q+ <rachelandrew> q+ <TabAtkins> fantasai: Right, that's part of our proposal <r12a> q+ <TabAtkins> addison: And it's not so much as when people are mixing langs in a page, but rather they want the same stylesheet for both their LTR and RTL translations without much fiddling. <astearns> ack emilio <TabAtkins> emilio: The "switch per file" doesn't work for BEM <TabAtkins> emilio: The simplest solution is having different properties, but that's not ideal <astearns> s/BEM/OM/ <emilio> yeah, the OM <fremy> q? <TabAtkins> fantasai: The browser could parse it in and use the declarations... Our proposal provides two shorthand syntaxes, both explicit, in addition to the current "ambiguous" one. <TabAtkins> fantasai: So the ambiguous would get decided as one or the other. <TabAtkins> emilio: How would you decide that when writing it out with JS? <TabAtkins> fantasai: For inline styles you'd use the explicit switch <TabAtkins> emilio: Right but then el1.style.margin = el2.style.margin loses the detail <TabAtkins> fantasai: The OM is currently locked into physical, so we're probably stuck with that. Any ideas? <TabAtkins> dbaron: I think if you want a file-level switch, you need it to store the information in each declaration. <TabAtkins> dbaron: So I think when you said property-by-property, at least some of the time you meant decl-by-decl <TabAtkins> miriam: yeah <TabAtkins> dbaron: So a file-level switch will have to alter the declarations at parse time to store the information, and possibly indistinguishable in the OM. <emilio> q+ <TabAtkins> fremy: It's common to bundle CSS, so per-file is an issue <TabAtkins> [discussion about ease of "s" suffix or "l-" prefix] <TabAtkins> fantasai: That still makes logical CSS a second-level, more awkward option <TabAtkins> astearns: My question on file-levle switch - is there a specific set of shorthands this would apply to? Or is it just certian ambiguous properties? <TabAtkins> astearns: If we add new shorthands, will they use this switch? <TabAtkins> fantasai: Note it's not just shorthands, it's every property that assigns in a physical orientation. <TabAtkins> astearns: So it's not an allowlist, it's a set of props with this characteristic <astearns> ack astearns <TabAtkins> fantasai: Right, so we'd like look at overflow, which is x/y, and we'd define that it can also be block/inline <TabAtkins> miriam: But like 'left' won't change, it just gets a different property <astearns> ack rachelandrew <TabAtkins> fantasai: But like text-shadow shoudl be able to assign block/inline, etc <dbaron> text-shadow may be the exception to wanting the default to be logical! <TabAtkins> rachelandrew: Issues 'margins' (suffix), that's easily typo'd. Very confusing especially since th eorder changes <TabAtkins> rachelandrew: Not sure if we need a file switch at all, kinda like the staged approach. <TabAtkins> rachelandrew: Wonder if, once we have the prop-by-prop, that'll be enough, especially since we know most authors use postprocessors which can handle the "file-level" itself <florian> q+ <TabAtkins> rachelandrew: So we can find out if we even need the second step once we've done all the properties individually. <astearns> ack r12a <TabAtkins> r12a: The switch sound like it could b euseful bc it maeks things easier in some circumstances, but it's more complex <TabAtkins> r12a: We've been stuck for over a year on just margin and padding, tho <addison> q+ to say the "order" isn't different, also that the proposal for interim work seems agreeable? <TabAtkins> r12a: The margin-inline/etc already exist and are great, but don't have the 4-value sorted out <TabAtkins> r12a: So it seems like just a nomenclature, wish we could sort that out. <astearns> ack emilio <TabAtkins> The "order" is indeed different, depending on your language, addison <TabAtkins> emilio: So the devil is in the details of 'margin'. If a logical version of the shorthands is something we need eventually anyway <TabAtkins> emilio: I think it would be great ot make progress here so we can just do logical margins <TabAtkins> TabAtkins: That exact thing is step 1 of this proposal <TabAtkins> emilio: So yeah can we resolve on that? <TabAtkins> emilio: And come up with a consistent model second <iank_> +1 to emilio <astearns> ack fantasai <astearns> ack florian <TabAtkins> florian: The point of discussing this switch now is not to have it now, but to be consistent with the switch eventually <emilio> s/consistent model/consistent model for how to switch margin to the logical thing <TabAtkins> florian: bc if properties all work in different ways, we can never introduce the switch, at least not simply <r12a> q+ <TabAtkins> florian: So we don't need to decide on the switch, just need a model where we can intro it eventually <addison> consistency and completeness <TabAtkins> florian: Goal is to not just *enable* logical stylesheets, but make them *not harder* than physical <astearns> ack dbaron <TabAtkins> dbaron: Responding to emilio, I think it wasn't clear if we want `margin-logical: values` or `margin: values !logical` <TabAtkins> dbaron: I think we need to be careful about assuming the end-state is everything-logical <TabAtkins> dbaron: text-shadow was mentioned, and shadows in particular you usually want consistency of light sources. <TabAtkins> dbaron: So want the light in upper-left, even if you have vertical Japanese or RTL hebrew mixed with your English <TabAtkins> dbaron: So might need some more thought about the end state <astearns> ack addison <Zakim> addison, you wanted to say the "order" isn't different, also that the proposal for interim work seems agreeable? <TabAtkins> addison: I think the switch is an end state, and primary challenge is agreement on interim bits. Does seem to be important. <florian> q+ <TabAtkins> addison: And to get complete <TabAtkins> addison: So let's focus on that. <astearns> ack r12a <TabAtkins> astearns: Right, but agreeing that we *will* have a switch is a good impetus <TabAtkins> r12a: Dont' agree it's a good impetus since it's been years we've been talking about it without delivering <TabAtkins> q+ <dbaron> s/have vertical Japanese/have Japanese with a mix of vertical and horizontal/ <TabAtkins> r12a: Let's just make a decision <TabAtkins> r12a: All the explicit logical properties already work, just the shorthand is missing <jensimmons> :dir <TabAtkins> r12a: Meanwhile while we wait, need a way to change properties, currently browsers use :dir to do so <astearns> ack florian <TabAtkins> florian: Here's a concrete proposal, tying to david's earlier point about storing state <TabAtkins> florian: I propose we don't go with extended names. Instae we use !syntax, and add a propdef line for specifying what the property defaults to if you don't specify the !. <TabAtkins> florian: So for like text-decoration you'd say "Default Directions: n/a", but margin would say "Default Directions: physical", etc <TabAtkins> florian: And later we can worry about a global switch, maybe with smarts about shadows, etc. <TabAtkins> florian: But first is the state in the propdef table. <emilio> q+ <fantasai> TabAtkins: What Florian said. <astearns> ack TabAtkins <TabAtkins> emilio: Not a fan of the bang, would prefer a ? mark <miriam> q+ <TabAtkins> emilio: Would prefer a separate shorthand, even with `-physical` and `-logical` <emeyer> q+ <astearns> ack emilio <TabAtkins> emilio: Less to figure out there <TabAtkins> emilio: Lots of thing to sort out to make !logical work <TabAtkins> ?? What things? <TabAtkins> emilio: And I just don't like the aesthetics <TabAtkins> florian: It helps with the mental model if the front and back look similar <TabAtkins> emilio: Complexity - we don't have conditional shorthands that expand one way or another based on some condition <TabAtkins> emilio: So how do we define that, how do they serialize <TabAtkins> emilio: Easier to say that margin-logical expands to the 4 logicals, margin-physical expands to the 4 physicals <TabAtkins> emilio: But for the ! thing margin could expand to 8 properties, choosing any 4 depending conditionally <TabAtkins> fantasai: I think you can say it expands to all of them unconditionally, but the order is conditional <TabAtkins> emilio: So if you have 8 declarations... <TabAtkins> fantasai: You set the wrong ones to initial, and the right ones to the values <TabAtkins> fantasai: Just th eorder needs changing <TabAtkins> fantasai: And we simplify in serialization <TabAtkins> emilio: Say you have all 8 defined, and you serialize the margin shorthand <TabAtkins> emilio: What form do you use? <florian> s/with the mental model if the front and back look similar/with the mental model, adding a ! in the declaration ties well with the idea that this is a state to be remembered per definition/ <astearns> zakim, close queue <Zakim> ok, astearns, the speaker queue is closed <astearns> q? <TabAtkins> dbaron: I think some of these aren't much harder than today <TabAtkins> dbaron: Dunno if we do them ideally today, but today if you declare margin and then margin-inline-start, should you serialize the margin shorthand? <TabAtkins> dbaron: I think you shouldn't and that extends to this case <TabAtkins> emilio: We do serialize it <TabAtkins> dbaron: Think that's a mistake <TabAtkins> emilio: That's how they all work, they're separate properties with separate values <TabAtkins> dbaron: Back when we were doing logical props as huge array of expanded props, we would not ahve serialized it <TabAtkins> dbaron: When we did it to depend on the order, we should have depended on some of the properties of the older solution that we dropped. <astearns> ack miriam <addison> that sounds like you (emilio) are arguing for the ! syntax? <emilio> ? <emilio> quite the opposite <TabAtkins> miriam: I get it that -logical is easier to impl and more consistent, but if there's not a plan for how it becomes a first-class citizen, I don't like it <florian> q+ <TabAtkins> miriam: That's why I like the ! solution, it's easy to toggle which is the default. <astearns> ack emeyer <TabAtkins> miriam: Concerned we just do the simple-to-implemenht and leave it that way, second class <TabAtkins> emeyer: I'm not a particular fan of the ! either <TabAtkins> emilio: We ahve already "not important" jokes, and this'll look like "not logical" <TabAtkins> s/emilio/emeyer/ <TabAtkins> emeyer: Wonder if we can just add a keyword to the value <TabAtkins> fantasai: Can't do it, that interferes with some property syntaxes, but we need something that's completely consistent. Has to be outside the property space. <TabAtkins> iank_: Are there that many props... <TabAtkins> iank_: As david said there are some we want to make physical. <TabAtkins> iank_: What's the list? <addison> has someone written the list? <emilio> q+ <TabAtkins> fantasai: It's pretty long, but some that you might *usually* want physical you want logical sometimes <TabAtkins> iank_: This does make me skeptical of the switch <TabAtkins> fremy: What about a logical() function fo rthe top-level property syntax? <TabAtkins> astearns: We're out of time. I think the appraoch of figuring out what we *can* do prop-by-prop, with the switch as an eventual goal, is the way to go. <TabAtkins> astearns: Kicking things up a levle, I'm frustrated we couldn't do all the issues. Want to find a way out of this, can't always wait for tpac <TabAtkins> [skipping some scheduling talk] <chris> sad in particular we didn't get to https://github.com//issues/4497#issuecomment-763459971 |
So in the interest of resolving this in our next meeting, I propose we choose among these options:
|
I prefer the second option with It should respect both bangs if you have I see an issue with the It would be better if there was a CSS property that you set on the If there is a technical reason that it needs to be an The selected elements, and everything inside them, ignore the logical property type switch and are then layed out using physical dimensions instead of logical dimensions. |
This is why we specified the switch as being file-level, rather than cascading. That way it only applies locally to declarations in the immediate file, and does not cascade to other files. I believe the inherited property is actually more likely to impact how third-party code is parsed, since the origin of the code is ignored, and parsing is based entirely on the selected element rather than the intent of the author. |
Issues with the file-level declarations, which were mentioned in the chat log above, reiterating here.
How long is the list of ambiguous shorthand properties? If the list is short, is it worth adding a whole new language feature? This might be out on a limb here, but what if there was no support for logical shorthands? What if they all remain physical, and if devs want logical properties they have to declare them explicitly (long-hand)? With tools like IDE code-completion and CSS preprocessors, how high is the demand for shorthand? |
The only issue that prevents solutions that use the syntax of the property value to decide between logical and physical from being implemented seems to be that the user agent should know at parse time what happens with First of all, if no .element {
margin: 1em 2em; /* physical */
margin: 1em 2em 3em 4em; /* physical */
} .element {
margin: 1em / 2em; /* logical */
margin: 1em 2em / 3em 4em; /* logical */
} If a .element {
margin: var(--margin); /* physical */
} In this case, when the computed value of .element {
--margin: 1em / 2em;
margin: var(--margin); /* invalid at computed value time */
}
If the author wants their property that includes a .element {
--margin: 1em / 2em;
margin: var(--margin) !logical;
} In this example: .element {
margin: 1em / 2em !logical; /* !logical would be optional */
} the .element {
margin: 1em 2em !logical; /* invalid */
} .element {
--margin: 1em 2em;
margin: var(--margin) !logical; /* invalid at computed value time */
} Another thing to consider is what should happen when the property value consists of multiple If the property value neither contains a .element {
--margin-top-bottom: 1em;
--margin-left-right: 2em;
margin: var(--margin-top-bottom) var(--margin-left-right); /* physical */
} If the property value directly contains a .element {
--margin-block: 1em;
--margin-inline: 2em 3em;
margin: var(--margin-block) / var(--margin-inline); /* logical, a !logical is optional */
} .element {
--margin-block: 1em;
margin: var(--margin-block) / 2em 3em; /* logical, a !logical is optional */
} If the property value has .element {
--firt-margin-part: 1em /;
--second-margin-part: 2em;
margin: var(--first-margin-part) var(--second-margin-part) !logical; /* logical */
} |
How would this work? Would there be a 4th argument? element.style.setProperty("margin", "1px 2px 3px 4px"); // non-important, physical
element.style.setProperty("margin", "1px 2px 3px 4px", "important"); // important, physical
element.style.setProperty("margin", "1px 2px 3px 4px", "", "logical"); // non-important, logical
element.style.setProperty("margin", "1px 2px 3px 4px", "important", "logical"); // important, logical Or conflate all flags into the 3rd argument like What about reading? I bet most scripts will just use What about computed styles? I don't think we want to track if the value comes from a logical or physical declaration, just like we don't track the priority (computed properties are considered non-important). So should they be considered physical or logical? From the point of view of CSSOM, using different properties seems way less problematic. |
CSS currently assigns the values in the margin/padding/border shorthand to their physical longhands, i.e.
is equivalent to
I'm pretty sure we want some equivalent syntax for assigning into the logical longhands instead, but what should that be?
The current proposal is to put a keyword in front of the 4 values, like
Another possibility is to use a !keyword:
or to create a new property in its place:
or use some entirely as-yet-unused symbol or syntax.
And of course the exact keyword, if one is used, is up for debate as well; shorter would be better. People will be drawing up entire style sheets that use almost exclusively flow-relative properties, so this needs to be designed for comfort under frequent use.
Ideas welcome~
The text was updated successfully, but these errors were encountered: