Closed Bug 1281320 Opened 8 years ago Closed 8 years ago

[css-grid] Implement 'fit-content([ <length> | <percentage> ])' value for <track-size>

Categories

(Core :: Layout, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla51
Tracking Status
firefox50 --- affected
firefox51 --- fixed

People

(Reporter: MatsPalmgren_bugz, Assigned: MatsPalmgren_bugz)

References

(Blocks 1 open bug)

Details

(Keywords: dev-doc-complete)

Attachments

(2 files)

This is a fairly recent spec addition: https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-fit-content It's still somewhat unclear exactly how it should be implemented: https://github.com/w3c/csswg-drafts/issues/209
Attached patch fix (deleted) — Splinter Review
The style system part is clear in the spec, but the layout part isn't. Implemented it as suggested in the github issue linked above.
Attachment #8765679 - Flags: review?(dholbert)
Depends on: 1279182
Comment on attachment 8765679 [details] [diff] [review] fix Review of attachment 8765679 [details] [diff] [review]: ----------------------------------------------------------------- Here are my review comments on the changes to nsGridContainerFrame.cpp. r=me with these & comment 3 addressed. ::: layout/generic/nsGridContainerFrame.cpp @@ +183,5 @@ > "track size data is expected to be initialized to zero"); > auto minSizeUnit = aMinCoord.GetUnit(); > + auto maxSizeUnit = aMaxCoord.GetUnit(); > + if (minSizeUnit == eStyleUnit_None) { > + // fit-content(size) behaves as minmax(auto,max-content), clamped to 'size'. Two nits on this comment: (1) It feels like a bit of a non-sequitur -- it's indirectly saying we're now dealing with a fit-content() expression, but it's not obvious that we've actually just checked for fit-content (due to the non-obvious/sneaky representation used for fit-content() in the style system, with the "None" unit in a particular spot by convention.) (2) (minor) The phrase "clamped to size" is ambiguous on whether it's a lower-bound or upper-bound - might as well add an extra word or two to clarify that, as long as this comment's expanding a bit. So, consider expanding this comment to something like the following, which (I think) addresses both of my nits: // This track is sized using fit-content(size) (represented in style system // with minCoord=None,maxCoord=size). In layout, fit-content(size) behaves // as minmax(auto, max-content), with 'size' as an additional upper-bound. @@ +1382,5 @@ > + nscoord newBase = sz.mBase + delta; > + if (MOZ_UNLIKELY((sz.mState & TrackSize::eFitContent) && > + aFitContentClamper)) { > + // Clamp mLimit to the fit-content() size, for §12.5.2 step 5/6. > + if (aFitContentClamper(track, sz.mBase, &newBase)) { The phrase "Clamp mLimit" is a typo here, I think. Pretty sure this wants to say "Clamp newBase". (That's the outparam being clamped here.) @@ +1384,5 @@ > + aFitContentClamper)) { > + // Clamp mLimit to the fit-content() size, for §12.5.2 step 5/6. > + if (aFitContentClamper(track, sz.mBase, &newBase)) { > + didClamp = true; > + delta = newBase - sz.mBase; Perhaps we should assert that delta is strictly greater than 0 here, as a sanity-check that the provided aFitContentClamper is behaving properly? (and its outparam & boolean-return-val are agreeing with each other) ::: layout/style/nsCSSParser.cpp @@ +8757,1 @@ > return CSSParseResult::NotFound; You need to add an UngetToken() call before the return here, to put mToken back into the stream for our caller to re-parse as something else. (In case splinter doesn't show it, this is inside the if-check for LowerCaseEqualsLiteral("minmax"). In the old code, this comparison-failure would produce an UngetToken() call, and we should make sure that it still does in the new code as well.) If you can think of a regression test that would've caught this bug, it'd be great to add one of those, too. (i.e. with an expression that *could* include minmax, but has something else instead; where the current patch would incorrectly slurp up a token & not put it back when checking for "minmax", and end up doing the wrong thing in the parser from that point on.) @@ +8845,1 @@ > return false; It's not superficially clear why "fit-content" just produces an immediate "return false" here. Please add a comment to explain why, between the assert and the return statement. (Presumably, fit-content() expressions do not count as <fixed-size>?) ::: layout/style/nsComputedDOMStyle.cpp @@ +2494,5 @@ > { > + if (aMinValue.GetUnit() == eStyleUnit_None) { > + // A fit-content() function. > + RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue; > + nsAutoString argumentStr, result; Please rename "result" to something clearer -- perhaps "fitContentFuncStr" or "fitContentExpression"? "result" is a bit vague, and in many cases it's the name for the thing that we return (but it's not what we return here, which makes it a bit confusing). Moreover, the data flow is kind of hard to follow here, with data being transferred from val --> argumentStr --> result --> val (full circle!), and it's harder still to follow if there's a variable that's labeled "result" that is not actually the function's result. ::: layout/style/nsRuleNode.cpp @@ +8037,5 @@ > + SetGridTrackBreadth(func->Item(2), aResultMax, > + aStyleContext, aPresContext, aConditions); > + } else if (funcName == eCSSKeyword_fit_content) { > + // We represent fit-content(L) as 'none' min-sizing and L max-sizing. > + SetGridTrackBreadth(nsCSSValue(eCSSUnit_None), aResultMin, This seems like a reasonable representation, but it should perhaps also be documented closer to where this data is actually stored, which is in nsStyleStruct.h "mMinTrackSizingFunctions", here: http://searchfox.org/mozilla-central/source/layout/style/nsStyleStruct.h#1562 Maybe worth adding a comment there, explaining the representation a bit better. Maybe something like: "When mMinTrackSizingFunctions[i] and mMaxTrackSizingFunctions[i] differ, it means there's a minmax() expression, but if mMinTrackSizingFunctions[i] is None, then it represents a fit-content() expression instead." (The minmax part of this is somewhat self-evident, which is probably why it wasn't documented before; but now it's perhaps useful to document both the simple case as well as the new case, now that there are more possibilities.)
Attachment #8765679 - Flags: review?(dholbert) → review+
Huh, it seems Splinter duplicated my already-posted review feedback (comment 3) when it populated comment 4. I'll just mark comment 3 as obsolete, since it's duplicated in comment 4 now. (And just be aware that the nsGridContainerFrame.cpp notes are the only thing new pieces that I added today, if you already read/addressed comment 3 locally.)
(In reply to Daniel Holbert [:dholbert] from comment #4) > The phrase "Clamp mLimit" is a typo here, I think. Yep, fixed. > > + if (aFitContentClamper(track, sz.mBase, &newBase)) { > > + didClamp = true; > > + delta = newBase - sz.mBase; > > Perhaps we should assert that delta is strictly greater than 0 here? That doesn't hold if it clamps newBase so that it equals sz.mBase, e.g. sz.mBase = 10 newBase = 11 fit-content size = 10 It returns true b/c it did clamp 'newBase', but 'delta' is zero. I added a "delta >= 0" assertion though, just as a sanity-check. > ::: layout/style/nsCSSParser.cpp > > return CSSParseResult::NotFound; > > You need to add an UngetToken() call before the return here, to put mToken > back into the stream for our caller to re-parse as something else. OK. > If you can think of a regression test that would've caught this bug, it'd be > great to add one of those, too. (i.e. with an expression that *could* > include minmax, but has something else instead; where the current patch > would incorrectly slurp up a token & not put it back when checking for > "minmax", and end up doing the wrong thing in the parser from that point on.) I can't think of any such cases. > It's not superficially clear why "fit-content" just produces an immediate > "return false" here. Please add a comment to explain why, between the > assert and the return statement. > > (Presumably, fit-content() expressions do not count as <fixed-size>?) Yes, fit-content() is not a <fixed-size>. I added a comment. > ::: layout/style/nsComputedDOMStyle.cpp > Please rename "result" to something clearer I renamed it "fitContentStr". > ::: layout/style/nsRuleNode.cpp > This seems like a reasonable representation, but it should perhaps also be > documented closer to where this data is actually stored, which is in > nsStyleStruct.h "mMinTrackSizingFunctions", here: OK, I documentated the fit-content() representation there too.
Pushed by mpalmgren@mozilla.com: https://hg.mozilla.org/integration/mozilla-inbound/rev/b723d2220298 [css-grid] Implement 'fit-content([ <length> | <percentage> ])' value for <track-size>. r=dholbert https://hg.mozilla.org/integration/mozilla-inbound/rev/8a885bf13b8f [css-grid] Reftests for fit-content() track sizes.
Status: NEW → RESOLVED
Closed: 8 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla51
Flags: in-testsuite+
As Jean-Yves already wrote, I added/updated the related documentation. Mats, could you please have a quick look at the following MDN pages to verify if everything is fine: https://developer.mozilla.org/en-US/docs/Web/CSS/fit-content https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template Thank you! Sebastian
Flags: needinfo?(mats)
Thanks for documenting this. I've filed a few minor issues: bug 1318876, bug 1318880, bug 1318882.
Flags: needinfo?(mats)
(In reply to Mats Palmgren (:mats) from comment #11) > Thanks for documenting this. I've filed a few minor issues: bug 1318876, > bug 1318880, bug 1318882. Thank you for the review! I'll have a look at them. Sebastian
Depends on: 1359060
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: