Commit graph

29 commits

Author SHA1 Message Date
Sam Atkins
eb1ad8655e LibWeb/CSS: Move and rename PseudoElement types to prep for code gen
The upcoming generated types will match those for pseudo-classes: A
PseudoElementSelector type, that then holds a PseudoElement enum
defining what it is. That enum will be at the top level in the Web::CSS
namespace.

In order to keep the diffs clearer, this commit renames and moves the
types, and then a following one will replace the handwritten enum with
a generated one.
2025-03-21 12:06:37 +00:00
Sam Atkins
d5b9c39a98 LibWeb: Replace webkit meter-state pseudo-elements with pseudo-classes
This also implements the `:high-value` and `:low-value` that are in the
spec.

Same note as before about this being based on the very-drafty CSS Forms
spec. In fact, some of this isn't even in that spec yet. Specifically,
the `:suboptimal-value` and `:even-less-good-value` names are undecided
and subject to change. However, it's clear that this is a pseudo-class
situation, not a pseudo-element one, so I think this is still an
improvement, as it allows styling of the `::fill` pseudo-element
regardless of what state it is in.

Relevant spec issue: https://github.com/openui/open-ui/issues/1130
2025-03-19 10:10:03 +00:00
Sam Atkins
3ebdb64fed LibWeb: Replace ::-webkit pseudo-elements with ones from CSS Forms spec
This spec is very early on, and likely to change. However, it still
feels preferable to use these rather than the prefixed -webkit ones.

Plus, as we have a `::fill` on range inputs, we can use that for styling
the bar instead of inserting CSS from C++.
2025-03-19 10:10:03 +00:00
Sam Atkins
db597843d6 LibWeb/CSS: Correct parsing of @supports selector()
A couple of fixes here:
- Parse a `<complex-selector>` instead of a `<selector-list>`
- Don't match if any unknown `::-webkit-*` pseudo-elements are found
2025-03-17 10:00:19 +00:00
Aliaksandr Kalenik
84ecaaa75c LibWeb: Limit sibling style invalidation by max distance
If an element is affected only by selectors using the direct sibling
combinator `+`, we can calculate the maximum invalidation distance and
use it to limit style invalidation. For example, the selector
`.a + .b + .c` has a maximum invalidation distance of 2, meaning we can
skip invalidating any element affected by this selector if it's more
than two siblings away from the element that triggered the style
invalidation.

This change results in visible performance improvement when hovering
PR list on GitHub.
2025-03-10 18:56:55 +01:00
Aliaksandr Kalenik
1843a54df7 LibWeb: Skip quick selector rejection using ancestor filter if possible
If selector does not have any descendant combinators then we know for
sure it won't be filtered out by ancestor filter, which means there is
no need to check for it.

This change makes hover style invalidation go faster on Discord where
with this change we spend 4-5% in `should_reject_with_ancestor_filter()`
instead of 20%.
2025-02-20 19:48:27 +01:00
Aliaksandr Kalenik
0f17ad9ebc LibWeb: Use fast CSS selector matching in default matches() code path
Before this change, checking if fast selector matching could be used was
only enabled in style recalculation and hover invalidation. With this
change it's enabled for all callers of SelectorEngine::matches() by
default. This way APIs like `Element.matches()` and `querySelector()`
could take advantage of this optimization.
2025-02-03 10:28:08 +01:00
Aliaksandr Kalenik
482e5deb85 LibWeb: Further optimize :hover style invalidation
Previously, we optimized hover style invalidation to mark for style
updates only those elements that were matched by :hover selectors in the
last style calculation.

This change takes it a step further by invalidating only the elements
where the set of selectors that use :hover changes after hovered element
is modified. The implementation is as follows:
1. Collect all elements whose styles might be affected by a change in
   the hovered element.
2. Retrieve a list of all selectors that use :hover.
3. Test each selector against each element and record which selectors
   match.
4. Update m_hovered_node to the newly hovered element.
5. Repeat step 3.
6. For each element, compare the previous and current sets of matched
   selectors. If they differ, mark the element for style recalculation.
2025-01-04 20:32:35 +01:00
Totto16
d21bfda900 LibWeb: Handle special cases of PseudoElement::Type correctly
There are some special values for CSS::Selector::PseudoElement::Type
which are after `KnownPseudoElementCount` and therefore not present in
various arrays of pseudo elements, this leads to some errors, if a type
after `KnownPseudoElementCount` is used without checking first. This
adds explicit checks to all usages
2024-12-19 19:35:57 +00:00
Luke Warlow
b17bbe6d1f LibWeb: Implement ::details-content pseudo element
Details' contents matches a new details-content pseudo element.

Further work is required to make this pseudo-element behave per spec.

This pseudo should be element-backed per
https://drafts.csswg.org/css-pseudo/#element-backed
2024-12-06 07:16:41 +00:00
Luke Warlow
fdee82d203 LibWeb: Implement ::file-selector-button pseudo element
The button for a file input now matches `::file-selector-button`.
2024-12-05 10:49:57 +00:00
Sam Atkins
da31c10ce1 LibWeb/CSS: Allow Selector::absolutized() to return null
It's possible for absolutizing a selector to return an invalid selector
(eg, it could cause `:has()` inside `:has()`) so we need to be able to
express that.
2024-11-14 19:51:45 +01:00
Sam Atkins
3a43fa9e35 LibWeb/CSS: Tag forgiving selector lists while parsing 2024-11-14 19:51:45 +01:00
Sam Atkins
7f803c5c3d LibWeb/CSS: Disallow :has() and pseudo-elements in :has() when parsing 2024-11-14 19:51:45 +01:00
Sam Atkins
5a1eb9e220 LibWeb/CSS: Keep invalid parts of <forgiving-selector-list>s around
Attempt 2! Reverts 2a5dbedad4

This time, set up a different combinator when producing a relative
invalid selector rather than a standalone one. This fixes the crash.

Original description below for simplicity because it still applies.

---

Selectors like `:is(.valid, &!?!?!invalid)` need to keep the invalid
part around, even though it will never match, for a couple of reasons:

- Serialization needs to include them
- For nesting, we care if a `&` appeared anywhere in the selector, even
  in an invalid part.

So this patch introduces an `Invalid` simple selector type, which simply
holds its original ComponentValues. We search through these looking for
`&`, and we dump them out directly when asked to serialize.
2024-11-14 13:20:01 +01:00
Andreas Kling
2a5dbedad4 Revert "LibWeb/CSS: Keep invalid parts of <forgiving-selector-list>s around"
This reverts commit 698dd600f2.

This caused multiple tests to crash on macOS:
https://github.com/LadybirdBrowser/ladybird/pull/2317#issuecomment-2474725826
2024-11-13 21:37:34 +01:00
Sam Atkins
698dd600f2 LibWeb/CSS: Keep invalid parts of <forgiving-selector-list>s around
Selectors like `:is(.valid, &!?!?!invalid)` need to keep the invalid
part around, even though it will never match, for a couple of reasons:

- Serialization needs to include them
- For nesting, we care if a `&` appeared anywhere in the selector, even
  in an invalid part.

So this patch introduces an `Invalid` simple selector type, which simply
holds its original ComponentValues. We search through these looking for
`&`, and we dump them out directly when asked to serialize.
2024-11-13 20:38:12 +01:00
Timothy Flynn
93712b24bf Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Andreas Kling
13d7c09125 Libraries: Move to Userland/Libraries/ 2021-01-12 12:17:46 +01:00
Andreas Kling
bbcc71fec4 LibWeb: Parse :before and :after pseudo-elements
Note that this is the old CSS2 syntax, we don't support the CSS3 syntax
just yet. Also we don't actually implement the pseudo-elements, this is
really just to make the selectors distinct from the same ones without
these pseudo-elements.
2020-12-01 16:53:10 +01:00
Andreas Kling
1f008c95b6 LibWeb: Move CSS classes into the Web::CSS namespace 2020-07-26 20:05:15 +02:00
Andreas Kling
ebf326a98c LibWeb: Fix build after Specificity.h removal 2020-06-25 20:59:00 +02:00
Andreas Kling
49dd4b7e8a LibWeb: Compress specificity into a 32-bit unsigned int
Instead of storing the three-part specificy for every selector,
just mash them together into a 32-bit value instead.
This saves both space and time, and matches the behavior of other
browser engines.
2020-06-25 16:43:49 +02:00
Andreas Kling
483b371a7b LibWeb: Parse and match the :visited pseudo-class (always fails)
If we don't do this, something like "a:visited" is parsed as "a" which
may then take precedence over a previous "a:link" etc.
2020-06-13 00:23:30 +02:00
Andreas Kling
65c4e5cacf LibWeb: Parse and match basic "contains" attribute selectors (~=) 2020-06-10 15:43:41 +02:00
Linus Groh
7bfd24ca76 LibWeb: Support the :root pseudo class 2020-05-14 08:49:51 +02:00
Linus Groh
055e955a1c LibWeb: Recognise :focus pseudo-class
It's still only a dummy as LibWeb doesn't have focused elements yet, but
at least now we don't treat "selector:focus" as just "selector".

This fixes an issue on google.com which was mostly grey - coming from
some menu item focus styles :^)
2020-05-05 13:16:33 +02:00
Andreas Kling
7309642ca8 LibWeb: Use FlyString for Element tag names
This makes selector matching a lot more efficient, and also reduces the
number of strings on the heap.
2020-03-22 19:12:10 +01:00
Andreas Kling
830a57c6b2 LibWeb: Rename directory LibHTML => LibWeb
Let's rename this to LibWeb since it aims to provide more parts of the
web platform than just HTML. :^)
2020-03-07 10:32:51 +01:00
Renamed from Libraries/LibHTML/CSS/Selector.h (Browse further)