diff --git a/crates/obscura-render/src/lib.rs b/crates/obscura-render/src/lib.rs index 25bd9a4..abb8a5e 100644 --- a/crates/obscura-render/src/lib.rs +++ b/crates/obscura-render/src/lib.rs @@ -874,6 +874,37 @@ mod tests { assert!((out.children[1].border_box.x - 650.0).abs() < 0.01); } + #[test] + fn negative_flex_margin_overlays_without_shifting_items() { + let main = make_box(Display::Block, 900.0, 200.0); + let sidebar = LayoutStyle { + display: Display::Flex, + width: Dimension::Px(225.0), + height: Dimension::Px(180.0), + margin: Edges { + left: -900.0, + ..Default::default() + }, + ..Default::default() + }; + let root = LayoutNode { + style: make_box(Display::Flex, 900.0, 220.0), + text: None, + children: vec![LayoutNode::leaf(main), LayoutNode::leaf(sidebar)], + }; + let out = layout(&root, (900.0, 220.0)); + assert!( + out.children[0].border_box.x.abs() < 0.01, + "main shifted to {:?}", + out.children[0].border_box + ); + assert!( + out.children[1].border_box.x.abs() < 0.01, + "overlay shifted to {:?}", + out.children[1].border_box + ); + } + #[test] fn flex_row_lays_out_horizontally() { let root = LayoutNode { diff --git a/crates/obscura-render/tests/layout_test.rs b/crates/obscura-render/tests/layout_test.rs index 800be28..ab34617 100644 --- a/crates/obscura-render/tests/layout_test.rs +++ b/crates/obscura-render/tests/layout_test.rs @@ -265,3 +265,70 @@ fn long_text_run_wraps_across_multiple_lines() { div_rect.height ); } + +#[test] +fn negative_flex_margin_overlays_at_container_start() { + let html = r##" + +
+
+ +
+ + "##; + let tree = parse_html(html); + let layout = layout_dom(&tree, (900.0, 1000.0)); + let document = layout.rects[&tree.get_element_by_id("document").unwrap()]; + let main = layout.rects[&tree.get_element_by_id("main").unwrap()]; + let body = layout.rects[&tree.get_element_by_id("body").unwrap()]; + let sidebar = layout.rects[&tree.get_element_by_id("sidebar").unwrap()]; + assert!((document.x - 0.0).abs() < 0.01, "document: {document:?}"); + assert!((main.x - 0.0).abs() < 0.01, "main: {main:?}"); + assert!((body.x - 225.0).abs() < 0.01, "body: {body:?}"); + assert!((sidebar.x - 0.0).abs() < 0.01, "sidebar: {sidebar:?}"); +} + +#[test] +fn percentage_flex_overlay_uses_auto_width_parent_content_box() { + let html = r##" + +
+
+ +
+ + "##; + let tree = parse_html(html); + let layout = layout_dom(&tree, (1280.0, 1400.0)); + let document = layout.rects[&tree.get_element_by_id("document").unwrap()]; + let main = layout.rects[&tree.get_element_by_id("main").unwrap()]; + let body = layout.rects[&tree.get_element_by_id("body").unwrap()]; + let sidebar = layout.rects[&tree.get_element_by_id("sidebar").unwrap()]; + assert!((document.x - 16.0).abs() < 0.01, "document: {document:?}"); + assert!((document.width - 1248.0).abs() < 0.01, "document: {document:?}"); + assert!((main.x - 16.0).abs() < 0.01, "main: {main:?}"); + assert!((body.x - 336.0).abs() < 0.01, "body: {body:?}"); + assert!((sidebar.x - 16.0).abs() < 0.01, "sidebar: {sidebar:?}"); + assert!((sidebar.width - 320.0).abs() < 0.01, "sidebar: {sidebar:?}"); +} diff --git a/render-repros/checks.json b/render-repros/checks.json index e3e1b1d..ae11772 100644 --- a/render-repros/checks.json +++ b/render-repros/checks.json @@ -42,6 +42,12 @@ {"name": "calc combines viewport and root font units", "color": "#7048e8", "x": 122, "y": 180, "width": 100, "height": 40}, {"name": "max padding uses actual viewport", "color": "#c2255c", "x": 60, "y": 240, "width": 20, "height": 40} ], + "flex-whitespace-items": [ + {"name": "direct flex sidebar starts at container edge", "color": "#1971c2", "x": 0, "y": 0, "width": 225, "height": 180}, + {"name": "direct flex body keeps its intended inset", "color": "#2b8a3e", "x": 225, "y": 0, "width": 675, "height": 200}, + {"name": "display contents flex sidebar starts at container edge", "color": "#7048e8", "x": 0, "y": 260, "width": 150, "height": 140}, + {"name": "display contents flex body keeps its intended inset", "color": "#c2255c", "x": 150, "y": 260, "width": 450, "height": 160} + ], "grid-auto-repeat": [ {"name": "auto-fill creates all fitting tracks", "color": "#087f5b", "width": 210, "height": 60, "count": 4}, {"name": "auto-fit collapses empty tracks", "color": "#1971c2", "width": 287, "height": 60, "count": 3} diff --git a/render-repros/flex-whitespace-items.html b/render-repros/flex-whitespace-items.html new file mode 100644 index 0000000..f1aca58 --- /dev/null +++ b/render-repros/flex-whitespace-items.html @@ -0,0 +1,48 @@ + + + + + flex whitespace items + + + +
+
+ +
+
+
+
+ +
+
+ +