From 16dffe39a0c8d73aa1f776c05dc5e1b4b7731002 Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Tue, 24 Mar 2026 13:35:58 +0100 Subject: [PATCH] LibWeb: Invalidate pseudo-elements on hover even when not yet created The hover invalidation code only tried matching ::before/::after selectors when has_pseudo_element() returned true, which requires an existing layout node. A pseudo-element that doesn't exist yet (because its content is only set by a hover rule) has no layout node, so the match was skipped and hovering never triggered a style recompute. Always try ::before/::after selectors during hover invalidation. --- Libraries/LibWeb/DOM/Document.cpp | 12 +++---- .../expected/css/pseudo-elements-on-hover.txt | 3 ++ .../css/update-pseudo-elements-on-hover.txt | 3 -- .../input/css/pseudo-elements-on-hover.html | 36 +++++++++++++++++++ .../css/update-pseudo-elements-on-hover.html | 33 ----------------- 5 files changed, 43 insertions(+), 44 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/css/pseudo-elements-on-hover.txt delete mode 100644 Tests/LibWeb/Text/expected/css/update-pseudo-elements-on-hover.txt create mode 100644 Tests/LibWeb/Text/input/css/pseudo-elements-on-hover.html delete mode 100644 Tests/LibWeb/Text/input/css/update-pseudo-elements-on-hover.html diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index 020f8fdc8a..9ce3cd1462 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -2076,14 +2076,10 @@ void Document::invalidate_style_for_elements_affected_by_pseudo_class_change(CSS SelectorEngine::MatchContext context; if (SelectorEngine::matches(selector, element, {}, context, {})) return true; - if (element.has_pseudo_element(CSS::PseudoElement::Before)) { - if (SelectorEngine::matches(selector, element, {}, context, CSS::PseudoElement::Before)) - return true; - } - if (element.has_pseudo_element(CSS::PseudoElement::After)) { - if (SelectorEngine::matches(selector, element, {}, context, CSS::PseudoElement::After)) - return true; - } + if (SelectorEngine::matches(selector, element, {}, context, CSS::PseudoElement::Before)) + return true; + if (SelectorEngine::matches(selector, element, {}, context, CSS::PseudoElement::After)) + return true; return false; }; diff --git a/Tests/LibWeb/Text/expected/css/pseudo-elements-on-hover.txt b/Tests/LibWeb/Text/expected/css/pseudo-elements-on-hover.txt new file mode 100644 index 0000000000..2d3541b604 --- /dev/null +++ b/Tests/LibWeb/Text/expected/css/pseudo-elements-on-hover.txt @@ -0,0 +1,3 @@ +update: 16 create: 0 +update: 78 create: 33 +update: 16 create: 0 diff --git a/Tests/LibWeb/Text/expected/css/update-pseudo-elements-on-hover.txt b/Tests/LibWeb/Text/expected/css/update-pseudo-elements-on-hover.txt deleted file mode 100644 index 08f5fd4f01..0000000000 --- a/Tests/LibWeb/Text/expected/css/update-pseudo-elements-on-hover.txt +++ /dev/null @@ -1,3 +0,0 @@ -Not hovering: 16 -Hovering: 78 -Not hovering: 16 diff --git a/Tests/LibWeb/Text/input/css/pseudo-elements-on-hover.html b/Tests/LibWeb/Text/input/css/pseudo-elements-on-hover.html new file mode 100644 index 0000000000..cd37fa4c84 --- /dev/null +++ b/Tests/LibWeb/Text/input/css/pseudo-elements-on-hover.html @@ -0,0 +1,36 @@ + + + +
+ diff --git a/Tests/LibWeb/Text/input/css/update-pseudo-elements-on-hover.html b/Tests/LibWeb/Text/input/css/update-pseudo-elements-on-hover.html deleted file mode 100644 index 281b8b34e7..0000000000 --- a/Tests/LibWeb/Text/input/css/update-pseudo-elements-on-hover.html +++ /dev/null @@ -1,33 +0,0 @@ - - - -
-