diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp index 6f801bd5d3eb..8d519de88a00 100644 --- a/dom/base/DOMIntersectionObserver.cpp +++ b/dom/base/DOMIntersectionObserver.cpp @@ -634,7 +634,8 @@ IntersectionInput DOMIntersectionObserver::ComputeInput( // https://w3c.github.io/IntersectionObserver/#update-intersection-observations-algo // (steps 2.1 - 2.5) IntersectionOutput DOMIntersectionObserver::Intersect( - const IntersectionInput& aInput, Element& aTarget) { + const IntersectionInput& aInput, Element& aTarget, + IgnoreContentVisibility aIgnoreContentVisibility) { const bool isSimilarOrigin = SimilarOrigin(aTarget, aInput.mRootNode) == BrowsingContextOrigin::Similar; nsIFrame* targetFrame = aTarget.GetPrimaryFrame(); @@ -647,7 +648,12 @@ IntersectionOutput DOMIntersectionObserver::Intersect( // true even if both the root and the target elements are in the skipped // contents." // https://drafts.csswg.org/css-contain/#cv-notes - if (targetFrame->IsHiddenByContentVisibilityOnAnyAncestor()) { + // + // Skip the intersection if the element is hidden, unless this is the + // DOMIntersectionObserver used specifically to track the visibility of + // `content-visibility: auto` elements. + if (aIgnoreContentVisibility == IgnoreContentVisibility::No && + targetFrame->IsHiddenByContentVisibilityOnAnyAncestor()) { return {isSimilarOrigin}; } @@ -707,11 +713,20 @@ void DOMIntersectionObserver::Update(Document* aDocument, DOMHighResTimeStamp time) { auto input = ComputeInput(*aDocument, mRoot, &mRootMargin); + // If this observer is used to determine content relevancy for + // `content-visiblity: auto` content, then do not skip intersection + // for content that is hidden by `content-visibility: auto`. + IgnoreContentVisibility ignoreContentVisibility = + aDocument->GetContentVisibilityObserver() == this + ? IgnoreContentVisibility::Yes + : IgnoreContentVisibility::No; + // 2. For each target in observer’s internal [[ObservationTargets]] slot, // processed in the same order that observe() was called on each target: for (Element* target : mObservationTargets) { // 2.1 - 2.4. - IntersectionOutput output = Intersect(input, *target); + IntersectionOutput output = + Intersect(input, *target, ignoreContentVisibility); // 2.5. Let targetArea be targetRect’s area. int64_t targetArea = (int64_t)output.mTargetRect.Width() * diff --git a/dom/base/DOMIntersectionObserver.h b/dom/base/DOMIntersectionObserver.h index 144e0ac4fea6..54b9739605ee 100644 --- a/dom/base/DOMIntersectionObserver.h +++ b/dom/base/DOMIntersectionObserver.h @@ -95,6 +95,9 @@ struct IntersectionInput { nsMargin mRootMargin; // If this is in an OOP iframe, the visible rect of the OOP frame. Maybe mRemoteDocumentVisibleRect; + // Whether this intersection is for the purposes of computing content + // relevancy for `content-visiblilty: auto`. + bool mIsForContentVisibility = false; }; struct IntersectionOutput { @@ -151,7 +154,11 @@ class DOMIntersectionObserver final : public nsISupports, static IntersectionInput ComputeInput( const Document& aDocument, const nsINode* aRoot, const StyleRect* aRootMargin); - static IntersectionOutput Intersect(const IntersectionInput&, Element&); + + enum class IgnoreContentVisibility : bool { No, Yes }; + static IntersectionOutput Intersect( + const IntersectionInput&, Element&, + IgnoreContentVisibility = IgnoreContentVisibility::No); // Intersects with a given rect, already relative to the root frame. static IntersectionOutput Intersect(const IntersectionInput&, const nsRect&); diff --git a/dom/base/Document.h b/dom/base/Document.h index 272417ed6b48..97516414ab20 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -3789,6 +3789,9 @@ class Document : public nsINode, } DOMIntersectionObserver& EnsureLazyLoadImageObserver(); + DOMIntersectionObserver* GetContentVisibilityObserver() const { + return mContentVisibilityObserver; + } DOMIntersectionObserver& EnsureContentVisibilityObserver(); void ObserveForContentVisibility(Element&); void UnobserveForContentVisibility(Element&); diff --git a/testing/web-platform/tests/css/css-contain/content-visibility/content-visibility-auto-nested-ref.html b/testing/web-platform/tests/css/css-contain/content-visibility/content-visibility-auto-nested-ref.html new file mode 100644 index 000000000000..bc00c86b8be8 --- /dev/null +++ b/testing/web-platform/tests/css/css-contain/content-visibility/content-visibility-auto-nested-ref.html @@ -0,0 +1,10 @@ + + + +Content Visibility: content in nested `content-visibility: auto` elements is considered relevant + + + +
+
content with content-visibility: auto
+
diff --git a/testing/web-platform/tests/css/css-contain/content-visibility/content-visibility-auto-nested.html b/testing/web-platform/tests/css/css-contain/content-visibility/content-visibility-auto-nested.html new file mode 100644 index 000000000000..9fc7c03b3a7c --- /dev/null +++ b/testing/web-platform/tests/css/css-contain/content-visibility/content-visibility-auto-nested.html @@ -0,0 +1,28 @@ + + + +Content Visibility: content in nested `content-visibility: auto` elements is considered relevant + + + + + + + + + + + + +
+
content with content-visibility: auto
+