diff --git a/components/style/dom.rs b/components/style/dom.rs index 3f0924cf77e..1cdac5089b3 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -19,6 +19,7 @@ use crate::shared_lock::{Locked, SharedRwLock}; use crate::stylist::CascadeData; use crate::traversal_flags::TraversalFlags; use crate::values::AtomIdent; +use crate::values::computed::Display; use crate::{LocalName, Namespace, WeakAtom}; use atomic_refcell::{AtomicRef, AtomicRefMut}; use selectors::matching::{QuirksMode, VisitedHandlingMode}; @@ -946,7 +947,7 @@ pub trait TElement: /// Returns the size of the element to be used in container size queries. /// This will usually be the size of the content area of the primary box, /// but can be None if there is no box or if some axis lacks size containment. - fn query_container_size(&self) -> euclid::default::Size2D>; + fn query_container_size(&self, display: &Display) -> euclid::default::Size2D>; } /// TNode and TElement aren't Send because we want to be careful and explicit diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 69272b15417..bf06761d6f0 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -63,6 +63,7 @@ use crate::shared_lock::{Locked, SharedRwLock}; use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; use crate::stylist::CascadeData; use crate::values::{AtomIdent, AtomString}; +use crate::values::computed::Display; use crate::CaseSensitivityExt; use crate::LocalName; use app_units::Au; @@ -1036,7 +1037,14 @@ impl<'le> TElement for GeckoElement<'le> { } #[inline] - fn query_container_size(&self) -> Size2D> { + fn query_container_size(&self, display: &Display) -> Size2D> { + // If an element gets 'display: contents' and its nsIFrame has not been removed yet, + // Gecko_GetQueryContainerSize will not notice that it can't have size containment. + // Other cases like 'display: inline' will be handled once the new nsIFrame is created. + if display.is_contents() { + return Size2D::new(None, None); + } + let mut width = -1; let mut height = -1; unsafe { diff --git a/components/style/matching.rs b/components/style/matching.rs index 0534d1ad0c5..a22dba26808 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -981,6 +981,13 @@ pub trait MatchMethods: TElement { // Stopped being a size container. Re-evaluate container queries and units on all our descendants. // Changes into and between different size containment is handled in `UpdateContainerQueryStyles`. restyle_requirement = ChildRestyleRequirement::MustMatchDescendants; + } else if old_container_type.is_size_container_type() && + !old_primary_style.is_display_contents() && + new_primary_style.is_display_contents() + { + // Also re-evaluate when a container gets 'display: contents', since size queries will now evaluate to unknown. + // Other displays like 'inline' will keep generating a box, so they are handled in `UpdateContainerQueryStyles`. + restyle_requirement = ChildRestyleRequirement::MustMatchDescendants; } restyle_requirement = cmp::max( diff --git a/components/style/stylesheets/container_rule.rs b/components/style/stylesheets/container_rule.rs index 8e9babff28c..8badfb80536 100644 --- a/components/style/stylesheets/container_rule.rs +++ b/components/style/stylesheets/container_rule.rs @@ -201,7 +201,7 @@ impl ContainerCondition { } } - let size = potential_container.query_container_size(); + let size = potential_container.query_container_size(&box_style.clone_display()); let style = style.clone(); TraversalResult::Done(ContainerLookupResult { element: potential_container, @@ -464,7 +464,7 @@ impl<'a> ContainerSizeQuery<'a> { let box_style = style.get_box(); let container_type = box_style.clone_container_type(); - let size = e.query_container_size(); + let size = e.query_container_size(&box_style.clone_display()); match container_type { ContainerType::Size => { TraversalResult::Done(