-
Notifications
You must be signed in to change notification settings - Fork 155
Description
As per #28 (comment), we would like to support CSS Grid in Taffy. This is a modified version of research I did on supporting this in Stretch (vislyhq/stretch#63 (comment)). Which I thought I would copy and update here as a starting point.
Status (22nd Dec 2022)
The implementation is largely feature complete, and a pre-release version of Taffy containing the CSS Grid implementation has been released. There is now a lot of testing and validating to be done before it is ready for a stable release.
Blocking questions / issues
-
How should Grid interact with intrinsically sized leaf nodes. The spec seems to define child nodes as having both amin-size(e.g. text node that wraps at all opportunities) andmax-size(e.g. a text node that doesn't wrap at all). Possibly these would need to be added to nodes as additional "measure functions"? Or possibly they could both be assumed to be equal to the one measure functions at first? Possibly min can be obtained by passing the MeasureFuncwidth: 0, height: 0, and max can be obtained by passing the MeasureFuncwidth: undefined, height: undefined? But perhaps it would be better to redefine the MeasureFunc to "sizing constraints" (https://www.w3.org/TR/css-sizing-3/#constraints) in addition a definite size constraint if one is available? https://www.w3.org/TR/css-sizing-3/#intrinsic-contribution
Plan is to updateMeasureFuncto take the sizing constraint as parameter (which it can then use or ignore as it sees fit). -
The interaction between nested Grid and Flexbox nodes. The comment at https://github.com/DioxusLabs/taffy/blob/main/src/flexbox.rs#L463-L466 suggests that the Flex implementation could be made more spec compliant by passing min-content/max-content constraints into to the top (presumably of thecompute_internalfunction. I feel like this may be a prerequisite to getting Grid and Flex to play nicely with each other in indefinitely sized contexts. Tracking issue here: Fixmin_maxcomputation when resolving flexible lengths to follow the spec #122
Plan is not to worry about integration at first, but it's likely that we'll adjust the Flexbox implementation to take sizing constraints as input as suggested above when we are ready to integrate.
Update: Both of these solutions were implemented as part of #246. Grid's integration with other layout modes is now unblocked.
Useful Resources:
- CSS Grid Level 1 Specification: https://www.w3.org/TR/css-grid-1
- CSS Grid Level 2 Specification: https://www.w3.org/TR/css-grid-2
- CSS Sizing Level 3 Sizing Values https://www.w3.org/TR/css-sizing-3/#sizing-values
- CSS Sizing Level 3 Intrinsic Sizes https://www.w3.org/TR/css-sizing-3/#intrinsic-sizes
- CSS Alignment Level 3 https://www.w3.org/TR/css-align-3/
- MDN Explanation of Subgrid (https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Subgrid)
- CSS Grid Garden: https://cssgridgarden.com
- CSS Tricks Complete guide to CSS Grid
- MDN value definition syntax https://developer.mozilla.org/en-US/docs/Web/CSS/Value_definition_syntax
MVP Implementation Plan
-
Extend the Style and Geometry sections of Stretch to include definitions for CSS Grid styles, while ensuring that the existing Flex implementation continues to work:
-
This has been implemented as thefrunitsFlexvariant of the newTrackSizingFunctionenum rather than being added toDimensionas it only applies to grid templates, and it turns out there are also a bunch of other options (likeminmax) that apply there but not elsewhere. -
display: grid -
grid-template-columns/grid-template-rows -
grid-auto-rows/grid-auto-columns/grid-auto-flow -
grid-column/grid-row/grid-row-start/grid-row-end/grid-column-start/grid-column-end -
row-gap/column-gap(note:gapshorthand implemented instead) -
justify-items/justify-self(justify-content/align-content/align-items/align-selfalready implemented for flexbox). Note: *-items and *-self properties align grid items (children) within their cell. *-content properties align cells (rows/columns) within the grid container. I think that all are set to stretch to fit by default.
We can probably ignore the shorthand properties for now, as their functionality is covered by the longhand equivalents above.
-
-
Resolve the explicit grid:
- Count the number of tracks in the "explicit grid". This is the rows and columns as defined by
grid-template-columns/grid-template-rows(Sections 7.1-7.4 of the spec). - Extend gentest infrastructure to support
repeat()syntax - Implement resolving fixed repetition explicit tracks
repeat(integer)Grid: Add support for repeat() with an integer repetition count #342 - Implement resolving auto-generated explicit tracks
repeat(auto-fill) - Implement collapsing tracks for
repeat(auto-fit)
(Not strictly necessary features like named grid lines/areas defined by
grid-template-areaswill be left until later.) - Count the number of tracks in the "explicit grid". This is the rows and columns as defined by
-
Implement grid placement. Matching Grid Items (child nodes of the grid) to Grid Areas. This may include generating extra rows and columns that form the "implicit grid" if any Grid Items are placed outside of the bounds of the "explicit grid". (note: the "implicit grid" is the whole grid, not just the extra bit) (Sections 7.5-8.5 of the spec)
-
Resolve the track sizing functions for all grid tracks (explicit and implicit).
-
Implement the Grid Sizing Algorithm to determine the size of each Grid Area. This mostly consists of the Track Sizing Algorithm, iterated a few times. A Grid Track is a row or column of the grid. Gutters sizes should also be resolved here, although this is relatively simple. (Section 11 of the spec).
- Resolve size of fixed size tracks (11.4. "Initialize Track Sizes" and 11.6. "Maximise Tracks")
- Resolve size of flexible tracks (with no children affecting size) (11.7 "Expand Flexible Tracks")
- Resolve size of intrinsically sized tracks (with no children affecting size) (11.8. "Stretch auto Tracks")
- Allow children of span 1 to affect track size (11.5. "Resolve Intrinsic Track Sizes" Step 2)
- Allow children with span > 1 to affect track size (11.5. "Resolve Intrinsic Track Sizes" Step 3 and 4)
- Support for
fit-content()track sizing functions- Fixed points fit-content arguments
- Percentage fit-content arguments
-
Resolve Grid Item (node) sizes and positions, by summing the size of the track and gutters in their grid area (in each axis), and taking into accounts spacing and alignment properties (Section 10 of the spec).
- Align grid track using
align_contentandjustify_content - Align items within their grid area using
align_items/align_self/justify_items/justify_self
- Align grid track using
-
Resolve sizes and positions of absolutely positioned elements (Section 9 of the spec)
-
Support for baseline alignment Grid: baseline alignment support #344
Code quality tasks:
- Fix all warnings
- Fix clippy lints
- Convert track sizing function enums to use
LengthPercentagerather thanDimension - Implement existing style helper functions (auto, zero, points) for grid styles
- Add new style helpers:
- percent
- min_content
- max_content
- flex
- minmax
- repeat
- track (line?)
- span
- Refactor code that deals with axes (make consistent)
- Evaluate use of
gridcrate - Update release notes to reflect the changes in this branch
- Updates to alignment styles
- CSS Grid layout mode
- Add feature flag for CSS grid feature (
experimental_grid?)
Correctness fixes:
- Don't distribute maximum's space to growth limits for flex items
- Apply align-content/justify-content when estimating opposite-axis available space
- Crash when children are implicitly placed outside the explicit grid
- More careful handling of grid lines indexes. One should not do arithmetic on grid lines without using the explicit track count as it is non-linear around 0. Grid line zero should be treated as "auto" and/or
GridPlacement::Lineshould useNonZeroI16. Grid/refactor coordinate handling #301 - Only accept track sizing functions as input to the minmax() helper #346
- Distribute space in proportion to flexible sizing functions Grid: Fixes for minmax, fr proportions and distributing space across multiple tracks #349
To test thoroughly
-
Repetition ((covered by unit tests. could still do with gentests but lower priority)repeat(integer),repeat(auto-fill)andrepeat(auto-fit)) -
Placement using Span(covered by unit tests. could still do with gentests but lower priority) -
Flex-column childrenWe don't match chrome on this, but our behaviour (actually containing the width of the child node) seems better, and matches the spec as best as I can tell. - Containers with padding/borders
- Absolutely positioned children
- Hidden children
- Children with margins
- Percent-size grid containers sizing into definite available_space Grid: Fix percent sizing #306
- Children with percentage width/height/padding/border/margin Grid: Fix percent sizing #306
- Top-to-bottom writing direction children Grid/width depends on height tests #300
- Percentage sized tracks Fix percent sized tracks #314
- Children with defined aspect ratio Fixes for aspect ratio and min/max sizes #317
- Min and max width/height Fixes for aspect ratio and min/max sizes #317
- Fit-content (including percentage arguments) Fix grid track sizing for
fit-content(percentage)and for items spanning percentage gaps #335 - Items spanning both fixed and percentage gaps Fix grid track sizing for
fit-content(percentage)and for items spanning percentage gaps #335 - Baseline Alignment Grid: baseline alignment support #344
- Distribute space in proportion to flexible sizing functions Grid: Fixes for minmax, fr proportions and distributing space across multiple tracks #349
- Items spanning multiple tracks where the tracks are flexible or intrinsically sized Grid: Fixes for minmax, fr proportions and distributing space across multiple tracks #349
- Content sizing of
minmax()tracks Grid: Fixes for minmax, fr proportions and distributing space across multiple tracks #349 - Tracks with
frvalues summing to less than 1 Grid: Fixes for minmax, fr proportions and distributing space across multiple tracks #349 - Complex integration tests (including Interaction with Flexbox):
Performance related tasks:
- CSS Grid Benchmarks #340
- Fix exponential blowup with regard to nesting depth Optimise CSS Grid #338
- Add tests checking for relayout counts Optimise CSS Grid #338
- Only compute child intrinsic size when needed Optimise CSS Grid #338
- Add early exit for grid container measurement Optimise CSS Grid #338
- Only do second track sizing iteration if "any of the item's min-content contributions have changed" Grid: selectively rerun track sizing #341
- Implement optimised track sizing for items that span exactly 1 track Grid: single track span optimisation #343
Further tasks
Grid related further tasks
- Support for named grid lines
- Support for
grid-template-areasandgrid-area - Support for CSS Grid Level 2 (subgrids)
Non-grid further tasks
- Support for
min-content/max-content/fit-contentsizes (widths/heights) - Add sub-directory support to gentests to separate grid and flexbox tests.