diff --git a/components/layout/fragment_tree/box_fragment.rs b/components/layout/fragment_tree/box_fragment.rs index 12b0206f26a..2e9fe8b53ba 100644 --- a/components/layout/fragment_tree/box_fragment.rs +++ b/components/layout/fragment_tree/box_fragment.rs @@ -24,7 +24,7 @@ use crate::formatting_contexts::Baselines; use crate::geom::{ AuOrAuto, LengthPercentageOrAuto, PhysicalPoint, PhysicalRect, PhysicalSides, ToLogical, }; -use crate::style_ext::ComputedValuesExt; +use crate::style_ext::{AxesOverflow, ComputedValuesExt}; use crate::table::SpecificTableGridInfo; use crate::taffy::SpecificTaffyGridInfo; @@ -271,12 +271,13 @@ impl BoxFragment { // overflow together, but from the specification it seems that if the border // box of an item is in the "wholly unreachable scrollable overflow region", but // its scrollable overflow is not, it should also be excluded. + let overflow_style = self.style.effective_overflow(self.base.flags); let scrollable_overflow = self .children .iter() .fold(physical_padding_rect, |acc, child| { let scrollable_overflow_from_child = child - .calculate_scrollable_overflow_for_parent() + .calculate_scrollable_overflow_for_parent(Some(overflow_style)) .translate(content_origin); // Note that this doesn't just exclude scrollable overflow outside the @@ -359,27 +360,33 @@ impl BoxFragment { tree.end_level(); } - pub(crate) fn scrollable_overflow_for_parent(&self) -> PhysicalRect { + pub(crate) fn scrollable_overflow_for_parent( + &self, + parent_overflow_style: Option, + ) -> PhysicalRect { let mut overflow = self.border_rect(); - if !self.style.establishes_scroll_container(self.base.flags) { - // https://www.w3.org/TR/css-overflow-3/#scrollable - // Only include the scrollable overflow of a child box if it has overflow: visible. - let scrollable_overflow = self.scrollable_overflow(); - let bottom_right = PhysicalPoint::new( - overflow.max_x().max(scrollable_overflow.max_x()), - overflow.max_y().max(scrollable_overflow.max_y()), - ); + let overflow_style = self.style.effective_overflow(self.base.flags); + let scrollable_overflow = self.scrollable_overflow(); + let bottom_right = PhysicalPoint::new( + overflow.max_x().max(scrollable_overflow.max_x()), + overflow.max_y().max(scrollable_overflow.max_y()), + ); - let overflow_style = self.style.effective_overflow(self.base.flags); - if overflow_style.y == ComputedOverflow::Visible { - overflow.origin.y = overflow.origin.y.min(scrollable_overflow.origin.y); - overflow.size.height = bottom_right.y - overflow.origin.y; - } + // https://www.w3.org/TR/css-overflow-3/#scrollable + // For each axis, we only include the scrollable overflow of a child box + // if either its parent or child has overflow: visible. + if parent_overflow_style.is_some_and(|style| style.y == ComputedOverflow::Visible) || + overflow_style.y == ComputedOverflow::Visible + { + overflow.origin.y = overflow.origin.y.min(scrollable_overflow.origin.y); + overflow.size.height = bottom_right.y - overflow.origin.y; + } - if overflow_style.x == ComputedOverflow::Visible { - overflow.origin.x = overflow.origin.x.min(scrollable_overflow.origin.x); - overflow.size.width = bottom_right.x - overflow.origin.x; - } + if parent_overflow_style.is_some_and(|style| style.x == ComputedOverflow::Visible) || + overflow_style.x == ComputedOverflow::Visible + { + overflow.origin.x = overflow.origin.x.min(scrollable_overflow.origin.x); + overflow.size.width = bottom_right.x - overflow.origin.x; } if !self diff --git a/components/layout/fragment_tree/fragment.rs b/components/layout/fragment_tree/fragment.rs index 77072b2797b..c64e77f9de2 100644 --- a/components/layout/fragment_tree/fragment.rs +++ b/components/layout/fragment_tree/fragment.rs @@ -23,7 +23,7 @@ use super::{ use crate::cell::ArcRefCell; use crate::flow::inline::SharedInlineStyles; use crate::geom::{LogicalSides, PhysicalPoint, PhysicalRect}; -use crate::style_ext::ComputedValuesExt; +use crate::style_ext::{AxesOverflow, ComputedValuesExt}; #[derive(Clone, MallocSizeOf)] pub(crate) enum Fragment { @@ -168,14 +168,19 @@ impl Fragment { let fragment = fragment.borrow(); fragment.offset_by_containing_block(&fragment.scrollable_overflow()) }, - _ => self.scrollable_overflow_for_parent(), + _ => self.scrollable_overflow_for_parent(None), } } - pub(crate) fn scrollable_overflow_for_parent(&self) -> PhysicalRect { + pub(crate) fn scrollable_overflow_for_parent( + &self, + parent_overflow_style: Option, + ) -> PhysicalRect { match self { Fragment::Box(fragment) | Fragment::Float(fragment) => { - return fragment.borrow().scrollable_overflow_for_parent(); + return fragment + .borrow() + .scrollable_overflow_for_parent(parent_overflow_style); }, Fragment::AbsoluteOrFixedPositioned(_) => PhysicalRect::zero(), Fragment::Positioning(fragment) => fragment.borrow().scrollable_overflow_for_parent(), @@ -185,9 +190,12 @@ impl Fragment { } } - pub(crate) fn calculate_scrollable_overflow_for_parent(&self) -> PhysicalRect { + pub(crate) fn calculate_scrollable_overflow_for_parent( + &self, + parent_overflow_style: Option, + ) -> PhysicalRect { self.calculate_scrollable_overflow(); - self.scrollable_overflow_for_parent() + self.scrollable_overflow_for_parent(parent_overflow_style) } pub(crate) fn calculate_scrollable_overflow(&self) { diff --git a/components/layout/fragment_tree/fragment_tree.rs b/components/layout/fragment_tree/fragment_tree.rs index 69c1e404c33..0b4bc6a58e1 100644 --- a/components/layout/fragment_tree/fragment_tree.rs +++ b/components/layout/fragment_tree/fragment_tree.rs @@ -15,6 +15,7 @@ use super::{BoxFragment, ContainingBlockManager, Fragment}; use crate::ArcRefCell; use crate::context::LayoutContext; use crate::geom::PhysicalRect; +use crate::style_ext::ComputedValuesExt; #[derive(MallocSizeOf)] pub struct FragmentTree { @@ -117,8 +118,15 @@ impl FragmentTree { let scrollable_overflow = self.root_fragments.iter().fold( self.initial_containing_block, |overflow, fragment| { + let overflow_style = match fragment { + Fragment::Box(fragment) | Fragment::Float(fragment) => { + let fragment_flags = fragment.borrow().base.flags; + Some(fragment.borrow().style.effective_overflow(fragment_flags)) + }, + _ => None, + }; fragment - .calculate_scrollable_overflow_for_parent() + .calculate_scrollable_overflow_for_parent(overflow_style) .union(&overflow) }, ); diff --git a/components/layout/fragment_tree/positioning_fragment.rs b/components/layout/fragment_tree/positioning_fragment.rs index 5547a9d86a1..937bd1b511f 100644 --- a/components/layout/fragment_tree/positioning_fragment.rs +++ b/components/layout/fragment_tree/positioning_fragment.rs @@ -79,7 +79,7 @@ impl PositioningFragment { |acc, child| { acc.union( &child - .calculate_scrollable_overflow_for_parent() + .calculate_scrollable_overflow_for_parent(None) .translate(self.rect.origin.to_vector()), ) }, diff --git a/tests/wpt/meta/css/cssom-view/scrolling-quirks-vs-nonquirks.html.ini b/tests/wpt/meta/css/cssom-view/scrolling-quirks-vs-nonquirks.html.ini deleted file mode 100644 index 84808d34540..00000000000 --- a/tests/wpt/meta/css/cssom-view/scrolling-quirks-vs-nonquirks.html.ini +++ /dev/null @@ -1,27 +0,0 @@ -[scrolling-quirks-vs-nonquirks.html] - [scrollWidth/scrollHeight on the root element in non-quirks mode] - expected: FAIL - - [scrollWidth/scrollHeight on the root element in quirks mode] - expected: FAIL - - [scrollWidth/scrollHeight on the HTML body element in quirks mode] - expected: FAIL - - [scroll() on the root element in non-quirks mode] - expected: FAIL - - [scrollBy() on the root element in non-quirks mode] - expected: FAIL - - [scrollLeft/scrollTop on the root element in non-quirks mode] - expected: FAIL - - [scroll() on the HTML body element in quirks mode] - expected: FAIL - - [scrollBy() on the HTML body element in quirks mode] - expected: FAIL - - [scrollLeft/scrollTop on the HTML body element in quirks mode] - expected: FAIL