Part of the display: grid-lanes roadmap (umbrella: #8615). Depends on M1 (#8617) (property IDs + @lynx-js/tasm / @lynx-js/css-defines / @lynx-js/types releases). Independent of M2–M4 — can proceed in parallel. Blocks M6 and the harness's oracle Mode B.
The work items below land in lynx-family/lynx-stack (plus docs in lynx-family/lynx-website); this issue tracks them from the engine side.
Context
Lynx for Web renders styles roughly 1:1 onto real DOM CSS, so display: grid-lanes should ultimately be browser-native on Web. But the pass-through has three traps, confirmed by inspection of lynx-stack (@lynx-js/web-core is now hybrid Rust/TS; the old web-constants / web-style-transformer packages were merged into it):
- Numeric property table is positional.
CSSPropertyEnum in packages/web-platform/web-core/src/template/template_sections/style_info/css_property.rs mirrors the engine's numeric IDs (Display = 24, … OffsetDistance = 215); from_id silently drops anything beyond the last known ID. New engine properties (flow-tolerance = 237 per M1) must be appended at the exact engine indices in both STYLE_PROPERTY_MAP and the enum, or numeric-keyed inline styles vanish with no diagnostic.
--lynx-display is a closed registered grammar. @property --lynx-display { syntax: "linear | flex" } — an unknown keyword is silently discarded and falls back to initial-value: linear, so a grid-lanes container would behave as a linear box. Declared in three places (web-core/css/index.css, web-elements/src/elements/common-css/linear.css, seeded in in_shadow.css / playwright-fixtures common.css).
- The linear cascade leaks.
display: grid today has no REPLACE_RULE entry in style_transformer/rules.rs, so linear.css's justify-content/flex-* variables still apply to grid containers. Grid-lanes must get an explicit rule (and this is a good moment to fix display: grid the same way).
Deliverables (in lynx-stack unless noted)
Toolchain
@lynx-js/web-core (Rust)
@lynx-js/web-elements (CSS)
Ecosystem
Acceptance criteria
- A ReactLynx page using
display: grid-lanes + flow-tolerance builds with zero "Unsupported property" diagnostics and renders via browser-native grid-lanes in Safari 26.4 / flagged Chromium.
- In non-supporting browsers, the documented fallback renders (no linear-cascade leakage, no silently-linear containers).
- Ring 1 Mode B green on the M2-level corpus (same bundle, native vs web).
- Tailwind utilities compile; types autocomplete
'grid-lanes' / flowTolerance; E2E snapshots green.
References
- lynx-stack:
packages/web-platform/web-core/src/style_transformer/rules.rs, .../style_info/css_property.rs, packages/web-platform/web-elements/src/elements/common-css/linear.css, packages/tools/css-serializer/src/parse.ts, packages/webpack/template-webpack-plugin/src/cssDiagnostics.ts
- Waterfall precedent on web:
packages/web-platform/web-elements/src/elements/XList/x-list.css (list-type="waterfall")
- Spec degradation guidance: §9
Part of the
display: grid-lanesroadmap (umbrella: #8615). Depends on M1 (#8617) (property IDs +@lynx-js/tasm/@lynx-js/css-defines/@lynx-js/typesreleases). Independent of M2–M4 — can proceed in parallel. Blocks M6 and the harness's oracle Mode B.Context
Lynx for Web renders styles roughly 1:1 onto real DOM CSS, so
display: grid-lanesshould ultimately be browser-native on Web. But the pass-through has three traps, confirmed by inspection of lynx-stack (@lynx-js/web-coreis now hybrid Rust/TS; the oldweb-constants/web-style-transformerpackages were merged into it):CSSPropertyEnuminpackages/web-platform/web-core/src/template/template_sections/style_info/css_property.rsmirrors the engine's numeric IDs (Display = 24, …OffsetDistance = 215);from_idsilently drops anything beyond the last known ID. New engine properties (flow-tolerance= 237 per M1) must be appended at the exact engine indices in bothSTYLE_PROPERTY_MAPand the enum, or numeric-keyed inline styles vanish with no diagnostic.--lynx-displayis a closed registered grammar.@property --lynx-display { syntax: "linear | flex" }— an unknown keyword is silently discarded and falls back toinitial-value: linear, so a grid-lanes container would behave as a linear box. Declared in three places (web-core/css/index.css,web-elements/src/elements/common-css/linear.css, seeded inin_shadow.css/ playwright-fixturescommon.css).display: gridtoday has noREPLACE_RULEentry instyle_transformer/rules.rs, so linear.css'sjustify-content/flex-*variables still apply to grid containers. Grid-lanes must get an explicit rule (and this is a good moment to fixdisplay: gridthe same way).Deliverables (in lynx-stack unless noted)
Toolchain
@lynx-js/tasminpackages/webpack/template-webpack-plugin(the encoder is the only gate —@lynx-js/css-serializeris property-agnostic and passes unknown declarations through).@lynx-js/typesacross all pinned packages (~15package.jsons, all pinned to one exact version) once M1 publishesCSSPropertieswith'grid-lanes'+flowTolerance.packages/repl/src/bundler/css-processor.ts) if it validates properties.@lynx-js/web-core(Rust)flow-tolerance(and any M1 additions) toSTYLE_PROPERTY_MAP+CSSPropertyEnumat engine indices; update thefrom_idbound; unit tests mirroringtest_css_property_from_id.REPLACE_RULEentry fordisplay: grid-lanesinstyle_transformer/rules.rs(mirror thelinear/flexshape): set--lynx-display-toggle/--lynx-display, emit nativedisplay: grid-lanes. Decide whether to add the missingdisplay: gridentry in the same PR (there's an existing test asserting its absence — flip deliberately).inline_style.rs); rebuild wasm binaries (pnpm build:wasm), commit regenerated.d.ts.@lynx-js/web-elements(CSS)@property --lynx-display { syntax: "linear | flex | grid-lanes" }in all three declaration sites; add--lynx-display-grid-lanestoggle var; audit the@container style(--lynx-display: …)blocks so grid-lanes children don't inherit linear'sflexshorthand behavior.display: grid-lanesbehind@supports (display: grid-lanes); else the legacy Chromiumdisplay: masonrysyntax where present; else a documented fallback (thex-list[list-type="waterfall"]absolute-positioning approach andLinearContainer/compat are in-repo precedents). Define the support matrix explicitly (Safari 26.4+ native; Chromium flag; everything else → fallback) and what "fallback" renders (recommendation: plaindisplay: griddegradation per spec §9, not a JS polyfill, for v1).web-core-e2e/tests/reactlynx/basic-grid-lanes-*/) + snapshots; encode/decode test for the new numeric ID (element-apis.spec.tsprecedent).Ecosystem
.grid-lanesdisplay utility +flow-toleranceplugin (packages/tailwind-preset— display.ts, plugin registry, theme scales, tests).lynx-family/lynx-website):display: grid-lanes+flow-toleranceproperty pages, guide with fallback guidance, compat table fed fromcss_definescompat_data(web_lynxflags set honestly)..lynx.bundleruns through Lynx for Web in headless Chromium/WebKit — wire it into the differential harness as the product-parity oracle mode.Acceptance criteria
display: grid-lanes+flow-tolerancebuilds with zero "Unsupported property" diagnostics and renders via browser-native grid-lanes in Safari 26.4 / flagged Chromium.'grid-lanes'/flowTolerance; E2E snapshots green.References
packages/web-platform/web-core/src/style_transformer/rules.rs,.../style_info/css_property.rs,packages/web-platform/web-elements/src/elements/common-css/linear.css,packages/tools/css-serializer/src/parse.ts,packages/webpack/template-webpack-plugin/src/cssDiagnostics.tspackages/web-platform/web-elements/src/elements/XList/x-list.css(list-type="waterfall")