Skip to content

[css-sizing] How to handle min-content being bigger than max-content? #12076

Closed

Description

@Loirooriol

https://drafts.csswg.org/css-sizing-3/#intrinsic-sizes defines the min-content and max-content sizes as the "preferred minimum width" and "preferred width" from CSS2: https://drafts.csswg.org/css2/#float-width

calculate the preferred width by formatting the content without breaking lines other than where explicit line breaks occur, and also calculate the preferred minimum width, e.g., by trying all possible line breaks. CSS 2 does not define the exact algorithm.

There seems to be the assumption that the min-content size can't exceed the max-content size.
For example, CSS Grid has a note stating

min-content contribution ≤ max-content contribution

However, consider this case:

<!DOCTYPE html>
<style>span { display: inline-block; margin-right: -50px }</style>
<div style="width: min-content; border: solid">aaaaaaaaaaaa<span></span></div>
<div style="width: max-content; border: solid">aaaaaaaaaaaa<span></span></div>

When we avoid wrapping lines as per max-content, then the negative margin of the span makes the line shorter than when wrapping lines as per min-content! Browsers don't agree:

  • Firefox just allows min-content to be bigger than max-content
  • Blink ceils the min-content to not exceed the max-content
  • WebKit floors the max-content to be at least as big as the min-content (not really, see next comment)
  • Servo was like Firefox but in a bunch of places we assumes min-content <= max-content, leading to assert failures. So I aligned with WebKit for now, since typically in case of conflict CSS tends to choose the maximum amount.
Firefox, Servo Blink WebKit, Servo
Image

Activity

  1. Loirooriol commented on Apr 14, 2025

    @Loirooriol
    ContributorAuthor

    Actually, rather than flooring the max-content by the min-content at the very end, it seems that WebKit floors the intrinsic contributions of each content to be at least zero. That also avoids the problem, but seems suboptimal:

    <!DOCTYPE html>
    <style>
    span {
      display: inline-block;
      vertical-align: top;
      height: 50px;
      background: rgba(0, 0, 0, 0.25);
    }
    </style>
    <div style="width: max-content; border: solid">
      <span style="width: 100px"></span>
      <span style="margin-right: -50px"></span>
      <span style="width: 100px"></span>
    </div>
    WebKit Others
  2. changed the title [-][css-sizing] How to handle min-content being bigger than max-context?[/-] [+][css-sizing] How to handle min-content being bigger than max-content?[/+] on Apr 14, 2025
  3. Loirooriol commented on Apr 16, 2025

    @Loirooriol
    ContributorAuthor

    Similar example with flexbox (based on /css/css-flexbox/intrinsic-size/row-wrap-002.tentative.html)

    <!DOCTYPE html>
    <style>.flex { display: flex; flex-wrap: wrap; height: 50px; border: solid }</style>
    <div class="flex" style="width: min-content">
      <div style="width: 50px"></div>
      <div style="margin-left: -25px"></div>
    </div>
    <div class="flex" style="width: max-content">
      <div style="width: 50px"></div>
      <div style="margin-left: -25px"></div>
    </div>

    Unlike for block containers, Blink now floors the max-content instead of ceiling the min-content.

    Firefox, Servo Blink, WebKit, Servo
  4. dbaron commented on Jun 20, 2025

    @dbaron
    Member

    For what it's worth, my intuition is that the min-content calculation in this examples is incorrect. The idea that breaking at every possible break point produces the minimum is a heuristic that's not always correct -- and it's wrong in this case, where having fewer breaks can lead to a smaller width. (This does assume that the layout algorithm can correctly produce that set of breaks given the input width, which I think it should, but I'd be surprised if all implementations were bug free on this point!)

    (On the other hand, I think the max-content calculation is probably correct as-is, because even though there are break configurations that produce a wider width, the layout algorithm shouldn't actually produce those configurations of breaks when given that width as input.)

  5. Loirooriol commented on Jun 20, 2025

    @Loirooriol
    ContributorAuthor

    So given S the set of all possible break opportunities, you think the min-content size should be the minimum size resulting from taking the break opportunities in T, among every possible subset T of S? Taking T=S typically provides such minimum, but not necessarily.

    That seems reasonable from a theoretical point of view, but hard to implement.

    Also, the min/max-content sizes are already heuristical with regard to float clearance and avoidance, so it seems fine to also be heuristical for taking line breaks.

  6. 10 remaining items

  7. bfgeek commented on Aug 29, 2025

    @bfgeek

    This resolution will affect CSS2/text/text-indent-intrinsic-00{3,4}.xht due to testing a negative text-indent in those tests.

  8. Loirooriol commented on Aug 29, 2025

    @Loirooriol
    ContributorAuthor

    Ah, I didn't notice that because in Servo we don't take text-indent into account for the intrinsic sizes 🤦, so we fail all these tests.

    But on the other hand, in the past Blink already added a flexbox test asserting what we resolved the other day: https://chromium-review.googlesource.com/c/chromium/src/+/4598273

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions