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-values-4] Simplification algorithm should possibly return single child for min/max #9559

Closed
johannesodland opened this issue Nov 5, 2023 · 8 comments

Comments

@johannesodland
Copy link

Step 5 for min/max of simplify a calculation tree currently states:

If root is a Min or Max node, attempt to partially simplify it:

For each node child of root’s children:

If child is a numeric value with enough information to compare magnitudes with another child of the same unit (see note in previous step), and there are other children of root that are numeric values with the same unit, combine all such children with the appropriate operator per root, and replace child with the result, removing all other child nodes involved.

Return root.

I might miss something, but this seems to simplify the children of the Min or Max node, but if you're left with only one child it seems to return the Min/Max node with a single child.

Should it not return the child in this case? I belive an earlier version of the spec did the same as the step for Sum nodes:

If root has only a single child at this point, return the child. Otherwise, return root.

@cdoublev
Copy link
Collaborator

cdoublev commented Nov 5, 2023

I belive an earlier version of the spec did the same as the step for Sum nodes

You are right (see 56fb598). But I think I remember some discussions about preserving min(1em).

@johannesodland
Copy link
Author

You are right (see 56fb598). But I think I remember some discussions about preserving min(1em).

Could it be related to #7456?

Should the Min node in min(1em) be preserved during parsing for internal representation?
It doesn't seem like it's preserved when simplifying for computed or used value though?

@cdoublev
Copy link
Collaborator

cdoublev commented Nov 5, 2023

Could it be related to #7456?

No, this issue is about my misunderstandings (which still hold to this day) regarding the simplification of a Product node, and more generally, about the whole parsing/simplification procedures. I think I was thinking to #4399.

min(1em) should not be preserved at computed/used value time. I think 1em is resolved to an absolute px at step 1.2, then min() is resolved at step 4.

To be honest, I do not know what should be the serialization as a component of a specified value, for min(1em) as input. Based on current browser outputs, I would say calc(1em) but from reading the spec, the step you are suggesting seems to be missing, indeed. There do not appear to be any existing WPTs.

@cdoublev cdoublev added the css-values-4 Current Work label Nov 5, 2023
@johannesodland
Copy link
Author

Did a quick test across browsers to check how they serialize the specified style:

Firefox: calc(1em)
Chrome: min(1em)
Safari: calc(1em)

I'm not sure how important this is though..

@cdoublev
Copy link
Collaborator

cdoublev commented Nov 20, 2023

(Sorry to have temporarily closed the issue, due to a typing error.)

Chrome now outputs calc(1em).

I was trying to figure out which part of the simplification algo would allow FF to simplify abs(abs(-1%)) as calc(1%), and the step 4 seems to apply, which reminded me of this issue, for which it also applies, I think.

edit

Actually, FF should not simplify abs(abs(-1%)) as calc(1%). But I think abs(1%) would be fine, and my initial comment above remains valid for min/max() holding a single argument.

@tabatkins
Copy link
Member

Should it not return the child in this case? I belive an earlier version of the spec did the same as the step for Sum nodes:

Note that removing a Sum node does not change the functional structure of the value; it just means that you don't have a silly Sum(5px) tree that just serializes to calc(5px) anyway. The same is not true of simplifying away other functions; that changes what the result looks like - Sum(5px + Min(10px)) serializes to calc(5px + min(10px)), rather than calc(15px) as if would if you removed the Min node.

But it does appear that browsers do exactly that simplification now, so I'm fine with making it.

(And I'm not really sure why I removed the Min/Max simplification in 56fb598#diff-fc1c32de78d227c8f0c8008469824444d1ba7f027e48a336125017d40b8f6f6fL4283; the minutes in #4399 don't suggest we stop doing that.)

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-values-4] Simplification algorithm should possibly return single child for min/max, and agreed to the following:

  • RESOLVED: Restore text simplifying out single-arg min/max functions
The full IRC log of that discussion <fantasai> scribe+
<fantasai> TabAtkins: Several years ago, we discussed simplifying calculation trees
<fantasai> TabAtkins: we agreed to aggressively simplify, e.g. min() if same units simplifies out
<fantasai> TabAtkins: as part of changes, I ended up removing the spec text about min() or max() with single argument
<fantasai> TabAtkins: I'm not sure why I dropped that spec text, I suspect it was an accident
<fantasai> TabAtkins: today all browsers do aggressively drop single-arg min()/max()
<fantasai> TabAtkins: e.g. min(5px) + 10px becomes 15px
<fantasai> TabAtkins: Chrome recently also aligned on this behavior
<dbaron> +1 to specifying what everyone does, seems like reasonable behavior.
<fantasai> TabAtkins: so I suggest we resolve on browser behavior, that single-arg min/max functions can be dropped from calc tree
<dbaron> (I think sakhapov recently wrote some reasonably major changes to calc() simplification in Chrome, to align with the spec.)
<fantasai> TabAtkins: even if the unit cannot yet be resolved
<fantasai> +1 from me
<fantasai> RESOLVED: Restore text simplifying out single-arg min/max functions

@tabatkins
Copy link
Member

As far as I can tell, the reason I removed the explicit "min()/max() is dropped if it has only one child" is that I figured it was covered by the generic "replace a node with its result if you can", and just didn't realize that the restrictions I placed on that clause ("in the canonical unit") would be too restrictive.

Anyway, restored now; as part of the special min/max "partial simplification" it'll replace itself with its sole child regardless of whether the child is fully resolveable yet.

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

No branches or pull requests

4 participants