mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 18:07:34 +00:00
LibWeb: Propagate overflow modes from <html> or <body> to viewport
This patch implements "Overflow Viewport Propagation" from CSS-OVERFLOW. It fixes an issue where many websites were not scrollable because they had `overflow: scroll` on the body element and we didn't propagate it.
This commit is contained in:
parent
09eed8eea2
commit
4011a107a4
5 changed files with 76 additions and 0 deletions
|
@ -917,6 +917,38 @@ void Document::invalidate_layout()
|
|||
schedule_layout_update();
|
||||
}
|
||||
|
||||
static void propagate_overflow_to_viewport(Element& root_element, Layout::Viewport& viewport)
|
||||
{
|
||||
// https://drafts.csswg.org/css-overflow-3/#overflow-propagation
|
||||
// UAs must apply the overflow-* values set on the root element to the viewport
|
||||
// when the root element’s display value is not none.
|
||||
auto* overflow_origin_node = root_element.layout_node();
|
||||
auto& viewport_computed_values = const_cast<CSS::MutableComputedValues&>(static_cast<CSS::MutableComputedValues const&>(static_cast<CSS::ComputedValues const&>(viewport.computed_values())));
|
||||
|
||||
// However, when the root element is an [HTML] html element (including XML syntax for HTML)
|
||||
// whose overflow value is visible (in both axes), and that element has as a child
|
||||
// a body element whose display value is also not none,
|
||||
// user agents must instead apply the overflow-* values of the first such child element to the viewport.
|
||||
if (root_element.is_html_html_element()) {
|
||||
auto* root_element_layout_node = root_element.layout_node();
|
||||
auto& root_element_computed_values = const_cast<CSS::MutableComputedValues&>(static_cast<CSS::MutableComputedValues const&>(static_cast<CSS::ComputedValues const&>(root_element_layout_node->computed_values())));
|
||||
if (root_element_computed_values.overflow_x() == CSS::Overflow::Visible && root_element_computed_values.overflow_y() == CSS::Overflow::Visible) {
|
||||
auto* body_element = root_element.first_child_of_type<HTML::HTMLBodyElement>();
|
||||
if (body_element && body_element->layout_node())
|
||||
overflow_origin_node = body_element->layout_node();
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: This is where we assign the chosen overflow values to the viewport.
|
||||
auto& overflow_origin_computed_values = const_cast<CSS::MutableComputedValues&>(static_cast<CSS::MutableComputedValues const&>(static_cast<CSS::ComputedValues const&>(overflow_origin_node->computed_values())));
|
||||
viewport_computed_values.set_overflow_x(overflow_origin_computed_values.overflow_x());
|
||||
viewport_computed_values.set_overflow_y(overflow_origin_computed_values.overflow_y());
|
||||
|
||||
// The element from which the value is propagated must then have a used overflow value of visible.
|
||||
overflow_origin_computed_values.set_overflow_x(CSS::Overflow::Visible);
|
||||
overflow_origin_computed_values.set_overflow_y(CSS::Overflow::Visible);
|
||||
}
|
||||
|
||||
void Document::update_layout()
|
||||
{
|
||||
// NOTE: If our parent document needs a relayout, we must do that *first*.
|
||||
|
@ -943,6 +975,8 @@ void Document::update_layout()
|
|||
m_layout_root = verify_cast<Layout::Viewport>(*tree_builder.build(*this));
|
||||
}
|
||||
|
||||
propagate_overflow_to_viewport(*document_element(), *m_layout_root);
|
||||
|
||||
Layout::LayoutState layout_state;
|
||||
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue