Skip to content

[css-logical] Handling ambiguous physical/logical shorthands with var() #9690

Open

Description

@tabatkins

A few shorthands can potentially expand to either physical longhands or logical longhands, depending on the content of the property. For example, margin: 5px 10px; expands to margin-top: 5px; margin-bottom: 5px; margin-left: 10px; margin-right: 10px;, but margin: logical 5px 10px; instead expands to margin-block: 5px; margin-inline: 10px;.

The fact that they expand to one set of longhands is, currently, important for the model, since we track precisely whether you've used a physical or logical longhand for each axis/side.

However, if you write margin: var(--foo);, you can't tell whether the property will expand into physical or logical longhands until computed-value time, but we need to know that at parse time. Because of the above point about why they need to expand to either physical or logical but not both, they can't do the normal var()-in-shorthand trick of expanding into a magic unserializable form that'll become real at computed-value time.

We either need to add some more magic to the "did you set this side using physical or logical" that allows for a magic unobservable var() value that will decide its origin later, or we need to switch the syntax for "I'm gonna expand into logical values" to outside the value space, such as with a bang-syntax.

I think we should try for the first option first, since this also applies to our attempt to put logical keywords into the background-position property. The syntax isn't ambiguous in that case (unlike with margin), so it would be awkward to have to write background-position: start start !logical;.

Activity

  1. Loirooriol commented on Dec 12, 2023

    @Loirooriol
    Contributor

    A few shorthands can potentially expand to either physical longhands or logical longhands

    That's not the currently the case in implementations.

    margin: logical 5px 10px

    This syntax is under discussion in #1282, which seems to be leaning towards other approaches.

    put logical keywords into the background-position

    If this is the only problematic case, it seems simpler to just not put logical keywords into background-position.

  2. tabatkins commented on Dec 12, 2023

    @tabatkins
    MemberAuthor

    Yeah, if it ends up being the only such case, I agree.

  3. weinig commented on Apr 28, 2025

    @weinig
    Contributor

    @tabatkins, I am starting to try and think about this problem as I try to add support for the logical keywords from CSS Values 5 (https://drafts.csswg.org/css-values-5/#position).

    Can you clarify where in the model (which spec?) "track[ing] precisely whether you've used a physical or logical longhand for each axis/side" is required?

  4. Loirooriol commented on Apr 28, 2025

    @Loirooriol
    Contributor

    The spec is simply not implementable in the current form, that's why opposed the change.

  5. weinig commented on Apr 28, 2025

    @weinig
    Contributor

    Ok. But can you help me understand what part isn’t implementable?

  6. tabatkins commented on May 1, 2025

    @tabatkins
    MemberAuthor

    Per the current model in the spec, we cascade logical and physical longhands independently, then associate them early in computed-value time (after writing-mode and direction have been computed), and treat both associated properties as having the cascaded value of whichever one has the highest, uh, not technically specificity but "cascade winning-ness" (since it depends on more than just the specificity). Basically we retcon things as if the associated properties were actually the same single property in the stylesheet.

    (Within a single rule, order of declarations thus matters: in an English document, whether you specify border-left: 5px; border-inline-start: 10px; or border-inline-start: 10px; border-left: 5px; changes whether those two properties end up being 5px or 10px. This is a new concept that isn't required for anything else, since otherwise order of declarations is resolved at parse-time by just throwing out earlier declarations.)

    The issue, then, is about what properties a shorthand actually expands to. Saying margin: logical 10px; should set margin-block-start: 10px;/etc, while margin: 10px; should set margin-top: 10px;/etc. If you just say margin: var(--foo);, tho, it could be either. You can't set all of them, both physical and logical, to a "pending" value tho, because then whichever set comes second overrides the set that comes first, even if it turns out that the first set is what was actually defined by the var().

    So there's a design issue there. If the physical/logical switch is in the value space, variables can mean that it hides until computed-value time, but it needs to be known at parse time. If the switch isn't in the value space (say it's margin: 10px !logical; or something), then it's impossible to set logical values via variables and similar things, since they can't expand into the ! portion of a declaration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions