diff --git a/components/layout/flow/root.rs b/components/layout/flow/root.rs index f3a4e558ff0..8107e1ef066 100644 --- a/components/layout/flow/root.rs +++ b/components/layout/flow/root.rs @@ -31,7 +31,7 @@ use crate::fragment_tree::{FragmentFlags, FragmentTree}; use crate::geom::{LogicalVec2, PhysicalSize}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; use crate::replaced::ReplacedContents; -use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside}; +use crate::style_ext::{AxesOverflow, Display, DisplayGeneratingBox, DisplayInside}; use crate::taffy::{TaffyItemBox, TaffyItemBoxInner}; use crate::{DefiniteContainingBlock, PropagatedBoxTreeData}; @@ -60,11 +60,10 @@ impl BoxTree { // > used overflow value of visible. let root_style = root_element.style(&context.style_context); - let mut viewport_overflow_x = root_style.clone_overflow_x(); - let mut viewport_overflow_y = root_style.clone_overflow_y(); + let mut viewport_overflow = AxesOverflow::from(&*root_style); let mut element_propagating_overflow = root_element; - if viewport_overflow_x == Overflow::Visible && - viewport_overflow_y == Overflow::Visible && + if viewport_overflow.x == Overflow::Visible && + viewport_overflow.y == Overflow::Visible && !root_style.get_box().display.is_none() { for child in root_element.children() { @@ -77,8 +76,7 @@ impl BoxTree { let style = child.style(&context.style_context); if !style.get_box().display.is_none() { - viewport_overflow_x = style.clone_overflow_x(); - viewport_overflow_y = style.clone_overflow_y(); + viewport_overflow = AxesOverflow::from(&*style); element_propagating_overflow = child; break; @@ -112,8 +110,8 @@ impl BoxTree { // > If visible is applied to the viewport, it must be interpreted as auto. // > If clip is applied to the viewport, it must be interpreted as hidden. viewport_scroll_sensitivity: AxesScrollSensitivity { - x: viewport_overflow_x.to_scrollable().into(), - y: viewport_overflow_y.to_scrollable().into(), + x: viewport_overflow.x.to_scrollable().into(), + y: viewport_overflow.y.to_scrollable().into(), }, } } diff --git a/components/layout/style_ext.rs b/components/layout/style_ext.rs index 8849d3d9f09..a1c80ff4ecd 100644 --- a/components/layout/style_ext.rs +++ b/components/layout/style_ext.rs @@ -64,6 +64,24 @@ pub struct AxesOverflow { pub y: Overflow, } +impl Default for AxesOverflow { + fn default() -> Self { + Self { + x: Overflow::Visible, + y: Overflow::Visible, + } + } +} + +impl From<&ComputedValues> for AxesOverflow { + fn from(style: &ComputedValues) -> Self { + Self { + x: style.clone_overflow_x(), + y: style.clone_overflow_y(), + } + } +} + impl DisplayGeneratingBox { pub(crate) fn display_inside(&self) -> DisplayInside { match *self { @@ -594,79 +612,60 @@ impl ComputedValuesExt for ComputedValues { /// flex containers, and grid containers. And some box types only accept a few values. /// fn effective_overflow(&self, fragment_flags: FragmentFlags) -> AxesOverflow { - let style_box = self.get_box(); - let mut overflow_x = style_box.overflow_x; - let mut overflow_y = style_box.overflow_y; - - // Inline boxes should never establish scroll containers. - if self.is_inline_box(fragment_flags) { - return AxesOverflow { - x: Overflow::Visible, - y: Overflow::Visible, - }; - } - // https://www.w3.org/TR/css-overflow-3/#overflow-propagation // The element from which the value is propagated must then have a used overflow value of visible. if fragment_flags.contains(FragmentFlags::PROPAGATED_OVERFLOW_TO_VIEWPORT) { - return AxesOverflow { - x: Overflow::Visible, - y: Overflow::Visible, - }; + return AxesOverflow::default(); } + let mut overflow = AxesOverflow::from(self); + // From : // "On replaced elements, the used values of all computed values other than visible is clip." if fragment_flags.contains(FragmentFlags::IS_REPLACED) { - if overflow_x != Overflow::Visible { - overflow_x = Overflow::Clip; + if overflow.x != Overflow::Visible { + overflow.x = Overflow::Clip; } - if overflow_y != Overflow::Visible { - overflow_y = Overflow::Clip; + if overflow.y != Overflow::Visible { + overflow.y = Overflow::Clip; } - return AxesOverflow { - x: overflow_x, - y: overflow_y, - }; + return overflow; } - let ignores_overflow = match style_box.display.inside() { + let ignores_overflow = match self.get_box().display.inside() { + // + // `overflow` doesn't apply to inline boxes. + stylo::DisplayInside::Flow => self.is_inline_box(fragment_flags), + + // According to , + // - overflow applies to table-wrapper boxes and not to table grid boxes. + // That's what Blink and WebKit do, however Firefox matches a CSSWG resolution that says + // the opposite: + // Due to the way that we implement table-wrapper boxes, it's easier to align with Firefox. + // - Tables ignore overflow values different than visible, clip and hidden. + // This affects both axes, to ensure they have the same scrollability. stylo::DisplayInside::Table => { - // According to , - // - overflow applies to table-wrapper boxes and not to table grid boxes. - // That's what Blink and WebKit do, however Firefox matches a CSSWG resolution that says - // the opposite: - // Due to the way that we implement table-wrapper boxes, it's easier to align with Firefox. - // - Tables ignore overflow values different than visible, clip and hidden. - // This affects both axes, to ensure they have the same scrollability. !matches!(self.pseudo(), Some(PseudoElement::ServoTableGrid)) || - matches!(overflow_x, Overflow::Auto | Overflow::Scroll) || - matches!(overflow_y, Overflow::Auto | Overflow::Scroll) + matches!(overflow.x, Overflow::Auto | Overflow::Scroll) || + matches!(overflow.y, Overflow::Auto | Overflow::Scroll) }, + + // + // Table-track and table-track-group boxes ignore overflow. stylo::DisplayInside::TableColumn | stylo::DisplayInside::TableColumnGroup | stylo::DisplayInside::TableRow | stylo::DisplayInside::TableRowGroup | stylo::DisplayInside::TableHeaderGroup | - stylo::DisplayInside::TableFooterGroup => { - // - // Table-track and table-track-group boxes ignore overflow. - true - }, + stylo::DisplayInside::TableFooterGroup => true, + _ => false, }; - if ignores_overflow { - AxesOverflow { - x: Overflow::Visible, - y: Overflow::Visible, - } - } else { - AxesOverflow { - x: overflow_x, - y: overflow_y, - } + return AxesOverflow::default(); } + + overflow } /// Return true if this style is a normal block and establishes