diff --git a/crates/html/src/adapters.rs b/crates/html/src/adapters.rs index c68b4a646..101dcf7ad 100644 --- a/crates/html/src/adapters.rs +++ b/crates/html/src/adapters.rs @@ -502,8 +502,11 @@ pub fn check_element_stripe_child(el: &StaticElement<'_>, style: &StyleValues) - // The cascade already expands inset; a winning `auto` longhand // must not be overwritten by the earlier shorthand. let inset = ["top", "right", "bottom", "left"].map(|prop| sv(style, prop)); - let height_stretches = - height_raw == "100%" || (static_edge_hugs(&inset[0]) && static_edge_hugs(&inset[2])); + // Opposing insets stretch only an auto-height box. With a definite + // height CSS drops the bottom constraint instead of stretching it. + let height_stretches = height_raw == "100%" + || ((height_raw.is_empty() || height_raw == "auto") + && static_edge_hugs(&inset[0]) && static_edge_hugs(&inset[2])); if !height_stretches { return Vec::new(); } diff --git a/crates/html/tests/stripe_child.rs b/crates/html/tests/stripe_child.rs index cae36ffa3..c89ab882a 100644 --- a/crates/html/tests/stripe_child.rs +++ b/crates/html/tests/stripe_child.rs @@ -64,6 +64,26 @@ fn absolute_top_bottom_flags() { assert!(hits[0].contains("stripe child (left)")); } +#[test] +fn absolute_definite_height_does_not_stretch_between_insets() { + for height in ["4px", "1rem", "25%", "calc(2px + 2px)"] { + let html = format!(r#"
+ +
"#); + assert!(side_tab_snippets(&html).is_empty(), "definite height {height} is not stretched"); + } +} + +#[test] +fn interactive_host_stripes_keep_the_border_rule_exemptions() { + for tag in ["a", "button"] { + let html = format!(r#"<{tag} style="position:relative;display:block;width:320px;height:100px"> + +"#); + assert!(side_tab_snippets(&html).is_empty(), "{tag} is an exempt control"); + } +} + #[test] fn flex_column_does_not_flag() { let html = r#"