diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp index 267b719467..ddbd02cd25 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -93,8 +93,23 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla return !element.next_element_sibling(); case CSS::Selector::SimpleSelector::PseudoClass::Type::OnlyChild: return !(element.previous_element_sibling() || element.next_element_sibling()); - case CSS::Selector::SimpleSelector::PseudoClass::Type::Empty: - return !(element.first_child_of_type() || element.first_child_of_type()); + case CSS::Selector::SimpleSelector::PseudoClass::Type::Empty: { + if (!element.has_children()) + return true; + if (element.first_child_of_type()) + return false; + // NOTE: CSS Selectors level 4 changed ":empty" to also match whitespace-only text nodes. + // However, none of the major browser supports this yet, so let's just hang back until they do. + bool has_nonempty_text_child = false; + element.for_each_child_of_type([&](auto const& text_child) { + if (!text_child.data().is_empty()) { + has_nonempty_text_child = true; + return IterationDecision::Break; + } + return IterationDecision::Continue; + }); + return !has_nonempty_text_child; + } case CSS::Selector::SimpleSelector::PseudoClass::Type::Root: return is(element); case CSS::Selector::SimpleSelector::PseudoClass::Type::FirstOfType: