Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
4349deb
Implement flex-wrap: balance and flex-line-count from CSS Flexbox Lev…
nicoburns Aug 14, 2026
8f0c7db
Add flex-wrap: balance and flex-line-count to the changelog
nicoburns Aug 14, 2026
36eca5b
Rename FlexWrap::WrapReverseBalance to FlexWrap::BalanceReverse
nicoburns Aug 14, 2026
99f53b3
Remove redundant comment on FlexWrap parser
nicoburns Aug 14, 2026
e2848ed
Fix yoga benchmark build for new FlexWrap balance variants
nicoburns Aug 14, 2026
003f22d
Rename balance_divided_cross_space parameter to cross_available_space
nicoburns Aug 14, 2026
3bd92bb
Hoist balance dispatch out of collect_flex_lines
nicoburns Aug 14, 2026
59c8f23
Use f64 arithmetic instead of fixed-point for flex line balancing
nicoburns Aug 14, 2026
95a9edb
Rewrite flex line balancing from the CSS Flexbox Level 2 spec
nicoburns Aug 14, 2026
a075959
Add gentest fixtures covering WPT css-flexbox/balance gaps
nicoburns Aug 14, 2026
12c1a83
Fix fit-content sizing of balanced flex containers under definite ava…
nicoburns Aug 14, 2026
4048904
Apply flex-line-count cross-space division to all multi-line containers
nicoburns Aug 14, 2026
7de42be
Optimize balanced line breaking with divide-and-conquer DP
nicoburns Aug 14, 2026
3d89e37
Score balancing by squared line sizes and enforce the zero-sized-item…
nicoburns Aug 14, 2026
cfbfda5
Store the zero-item flags alongside the prefix sums, saving an alloca…
nicoburns Aug 14, 2026
13c314a
Divide the fit-content cross stretch size by the requested line count
nicoburns Aug 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

### Added

- Support for `flex-wrap: balance` and the `flex-line-count` property from [CSS Flexbox Level 2](https://drafts.csswg.org/css-flexbox-2/#balance-values), gated behind a new on-by-default `flexbox_balance` cargo feature (which depends on `flexbox`):
- `FlexWrap` gains `Balance` and `BalanceReverse` variants, and its CSS parser accepts the multi-keyword grammar `nowrap | [ wrap | wrap-reverse ] || balance`. When balancing, items are collected into flex lines such that the largest line is as small as possible (minimising the sum of squares of each line's free space), rather than greedily filling each line
- `Style::flex_line_count` (and a corresponding `FlexboxContainerStyle::flex_line_count` trait method) specifies the minimum number of lines to balance items into (default `1`). When it is greater than 1 on any multi-line container (`wrap`, `wrap-reverse`, `balance` or `balance-reverse`), definite cross-axis available space for measuring items is divided between the requested number of lines (after subtracting cross-axis gaps), per the [CSSWG resolution](https://github.com/w3c/csswg-drafts/issues/13414)

- `Dimension` (used for `size`) now supports the sizing keywords `min-content`, `max-content`, `fit-content`, `fit-content(<length-percentage>)` and `stretch` via new constructors (`Dimension::min_content()`, `Dimension::max_content()`, `Dimension::fit_content()`, `Dimension::fit_content_px()`, `Dimension::fit_content_percent()`, `Dimension::stretch()`), new `CompactLength::FIT_CONTENT_KEYWORD_TAG`/`CompactLength::STRETCH_TAG` representations, and CSS parsing support. These keywords are resolved:
- In block layout: for the widths of in-flow children and floats
- In flexbox layout: for the main-axis size when determining an item's flex base size, for the cross-axis size when determining an item's hypothetical cross size, and for `flex-basis` (where `stretch` resolves to the stretch-fit main size and the other keywords determine the sizing constraint the item is measured under when computing its flex base size)
Expand Down
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ default = [
"std",
"taffy_tree",
"flexbox",
"flexbox_balance",
"grid",
"block_layout",
"float_layout",
Expand All @@ -54,6 +55,8 @@ block_layout = []
float_layout = []
## Enables the Flexbox layout algorithm. See [`compute_flexbox_layout`](crate::compute_flexbox_layout).
flexbox = []
## Enables support for `flex-wrap: balance` and `flex-line-count` from [CSS Flexbox Level 2](https://drafts.csswg.org/css-flexbox-2/)
flexbox_balance = ["flexbox"]
## Enables the CSS Grid layout algorithm. See [`compute_grid_layout`](crate::compute_grid_layout).
grid = ["alloc", "dep:smallvec"]
## Enables calc() values for all layout algorithms
Expand Down
3 changes: 3 additions & 0 deletions benches/src/yoga_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ fn apply_taffy_style(node: &mut yg::Node, style: &tf::Style) {
tf::FlexWrap::NoWrap => yg::Wrap::NoWrap,
tf::FlexWrap::Wrap => yg::Wrap::Wrap,
tf::FlexWrap::WrapReverse => yg::Wrap::WrapReverse,
// Yoga has no equivalent of `flex-wrap: balance`
tf::FlexWrap::Balance => yg::Wrap::Wrap,
tf::FlexWrap::BalanceReverse => yg::Wrap::WrapReverse,
});
node.set_flex_basis(into_yg_units(style.flex_basis));
node.set_flex_grow(style.flex_grow);
Expand Down
4 changes: 4 additions & 0 deletions scripts/gentest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ async fn main() {
if name.starts_with("grid") {
writeln!(&mut mod_file, r#"#[cfg(feature = "grid")]"#).unwrap();
}
if name.starts_with("balance") {
writeln!(&mut mod_file, r#"#[cfg(feature = "flexbox_balance")]"#).unwrap();
}
writeln!(
&mut mod_file,
"#[test]
Expand Down Expand Up @@ -650,6 +653,7 @@ fn generate_node(w: &mut XmlWriter, node: &Value) {
maybe_write(w, "clear", get_str_attr(&style["clear"], None));
maybe_write(w, "flex-direction", get_str_attr(&style["flexDirection"], Some("row")));
maybe_write(w, "flex-wrap", get_str_attr(&style["flexWrap"], Some("nowrap")));
maybe_write(w, "flex-line-count", get_num_attr(&style["flexLineCount"], Some(1.0)));
maybe_write(w, "overflow-x", get_str_attr(&style["overflowX"], Some("visible")));
maybe_write(w, "overflow-y", get_str_attr(&style["overflowY"], Some("visible")));

Expand Down
1 change: 1 addition & 0 deletions scripts/gentest/test_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ function describeElement(e) {

flexDirection: parseEnum(e.style.flexDirection),
flexWrap: parseEnum(e.style.flexWrap),
flexLineCount: parseNumber(e.style.flexLineCount),
overflowX: parseEnum(e.style.overflowX),
overflowY: parseEnum(e.style.overflowY),
scrollbarWidth: getScrollBarWidth(),
Expand Down
Loading