LibWeb/HTML: Implement HTMLElement.scrollParent

Corresponds to d3effb701c

What a "fixed position container" is isn't clear to me, and we don't
seem to use that elsewhere, so I've left the steps using that as FIXMEs
for now.

There's no test coverage for this in WPT yet and I'm not confident
enough in the specific behaviour to write one myself. So, waiting on
https://github.com/web-platform-tests/wpt/issues/53214
This commit is contained in:
Sam Atkins 2025-06-17 10:43:45 +01:00
parent 5d5f16845c
commit af9a227ca3
Notes: github-actions[bot] 2025-06-17 11:39:46 +00:00
3 changed files with 43 additions and 0 deletions

View file

@ -461,6 +461,47 @@ String HTMLElement::outer_text()
return get_the_text_steps();
}
// https://drafts.csswg.org/cssom-view/#dom-htmlelement-scrollparent
GC::Ptr<DOM::Element> HTMLElement::scroll_parent() const
{
// 1. If any of the following holds true, return null and terminate this algorithm:
// - The element does not have an associated box.
// - The element is the root element.
// - The element is the body element.
// - FIXME: The elements computed value of the position property is fixed and no ancestor establishes a fixed position containing block.
if (!layout_node())
return nullptr;
if (is_document_element())
return nullptr;
if (is_html_body_element())
return nullptr;
// 2. Let ancestor be the containing block of the element in the flat tree and repeat these substeps:
auto ancestor = layout_node()->containing_block();
while (true) {
// 1. If ancestor is the initial containing block, return the scrollingElement for the elements document if it
// is not closed-shadow-hidden from the element, otherwise return null.
if (ancestor->is_viewport()) {
auto const scrolling_element = document().scrolling_element();
if (scrolling_element && !scrolling_element->is_closed_shadow_hidden_from(*this))
return const_cast<Element*>(scrolling_element.ptr());
return nullptr;
}
// 2. If ancestor is not closed-shadow-hidden from the element, and is a scroll container, terminate this
// algorithm and return ancestor.
if (!ancestor->dom_node()->is_closed_shadow_hidden_from(*this) && ancestor->is_scroll_container()) {
return const_cast<Element*>(static_cast<DOM::Element const*>(ancestor->dom_node()));
}
// FIXME: 3. If the computed value of the position property of ancestor is fixed, and no ancestor establishes a fixed
// position containing block, terminate this algorithm and return null.
// 4. Let ancestor be the containing block of ancestor in the flat tree.
ancestor = layout_node()->containing_block();
}
}
// https://www.w3.org/TR/cssom-view-1/#dom-htmlelement-offsetparent
GC::Ptr<DOM::Element> HTMLElement::offset_parent() const
{