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.
This commit is contained in:
parent
77b9fcf7f9
commit
16dffe39a0
5 changed files with 43 additions and 44 deletions
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
update: 16 create: 0
|
||||
update: 78 create: 33
|
||||
update: 16 create: 0
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
Not hovering: 16
|
||||
Hovering: 78
|
||||
Not hovering: 16
|
||||
36
Tests/LibWeb/Text/input/css/pseudo-elements-on-hover.html
Normal file
36
Tests/LibWeb/Text/input/css/pseudo-elements-on-hover.html
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
.outer {
|
||||
height: 100px;
|
||||
}
|
||||
.update {
|
||||
display: inline-block;
|
||||
}
|
||||
.update::before {
|
||||
content: "Hi";
|
||||
}
|
||||
.outer:hover .update::before {
|
||||
content: "Long text";
|
||||
}
|
||||
.create {
|
||||
display: inline-block;
|
||||
}
|
||||
.outer:hover .create::before {
|
||||
content: "Flag";
|
||||
}
|
||||
</style>
|
||||
<script src="../include.js"></script>
|
||||
<div class="outer"><div class="update"></div><div class="create"></div></div>
|
||||
<script>
|
||||
test(() => {
|
||||
const update = document.querySelector('.update');
|
||||
const create = document.querySelector('.create');
|
||||
println(`update: ${update.clientWidth} create: ${create.clientWidth}`);
|
||||
|
||||
internals.mouseMove(50, 50);
|
||||
println(`update: ${update.clientWidth} create: ${create.clientWidth}`);
|
||||
|
||||
internals.mouseMove(200, 200);
|
||||
println(`update: ${update.clientWidth} create: ${create.clientWidth}`);
|
||||
});
|
||||
</script>
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
<!doctype html>
|
||||
<style>
|
||||
.outer {
|
||||
height: 100px;
|
||||
}
|
||||
.inner {
|
||||
display: inline-block;
|
||||
}
|
||||
.inner::before {
|
||||
content: "Hi";
|
||||
background-color: red;
|
||||
}
|
||||
.outer:hover .inner::before {
|
||||
content: "Long text";
|
||||
background-color: lime;
|
||||
}
|
||||
</style>
|
||||
<script src="../include.js"></script>
|
||||
<div class="outer"><div class="inner"></div></div>
|
||||
<script>
|
||||
test(() => {
|
||||
const inner = document.querySelector('.inner');
|
||||
println('Not hovering: ' + inner.clientWidth);
|
||||
|
||||
// Move mouse over .outer
|
||||
internals.mouseMove(80, 80);
|
||||
println('Hovering: ' + inner.clientWidth);
|
||||
|
||||
// Move mouse away again
|
||||
internals.mouseMove(200, 200);
|
||||
println('Not hovering: ' + inner.clientWidth);
|
||||
});
|
||||
</script>
|
||||
Loading…
Reference in a new issue