Skip to content

feat: [#2390] support the :required CSS pseudo-class - #2391

Open
marciomazza wants to merge 1 commit into
capricorn86:masterfrom
marciomazza:feat/pseudo-class-required
Open

feat: [#2390] support the :required CSS pseudo-class#2391
marciomazza wants to merge 1 commit into
capricorn86:masterfrom
marciomazza:feat/pseudo-class-required

Conversation

@marciomazza

Copy link
Copy Markdown

Description

Resolves #2390

The :required CSS pseudo-class is never matched — SelectorItem.matchPseudoItem
has no required case, so any :required selector silently returns nothing.

document.body.innerHTML = `<input id="a" required><input id="b">`;
document.querySelectorAll(':required').length; // happy-dom: 0 — real browsers: 1

Fix: add a required case mirroring the existing disabled one — it matches when
the element has a required content attribute.

Deviation left on purpose: this also matches <input type="hidden" required>
(the check is 'required' in element, not whether the attribute is applicable to
the element's current type), where browsers do not. The existing :disabled case
is equally loose; tightening both is out of scope here.

Tests

Added 1 test: :required matches <input> / <select> / <textarea> carrying
the attribute and skips an <input> without it. Fails before / passes after.
Full npm test passes.

AI

I used Claude Code to write this, over multiple iterations. I guided and reviewed
it myself at every step.

Before submitting the PR, please make sure you do the following:

  • Read the contributing guidelines.
  • It's really useful if your PR references an issue where it is discussed ahead of time.
  • Please check Allow edits by maintainers to make review process faster. Note that this option is not available for repositories that are owned by Github organizations.

Tests

  • Make sure to add tests for your changes. Run your test in a real browser to make sure that the test tests what a real browser would do (e.g. by running the code in the browser console).
    • Ran the repro in Chrome 152 (headless): :required matched <input required>, <select required>, <textarea required>, and did not match <input type="hidden" required>. The test asserts the first three.
  • Run the tests with npm test locally to make sure that all tests pass before submitting the PR.

Title

  • The title of the pull request should be in the format of "type: [#issue] description". The type can be feat, fix, chore or BREAKING CHANGE. The issue is optional and can be omitted if the pull request does not relate to an issue.
  • The title should be concise and descriptive. The title will be used when generating release notes. Make sure that the title is easily understood by users of the library.

AI tools

  • Please disclose in the PR description that you used AI tools to generate code. This is important for transparency and to ensure that the generated code meets the quality standards of the project.

:required matches any form control carrying a required attribute (input,
select, textarea), mirroring the existing :disabled handling in SelectorItem.
@marciomazza
marciomazza force-pushed the feat/pseudo-class-required branch from e97d548 to ec1d044 Compare September 8, 2026 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

:required CSS pseudo-class is never matched by querySelector

1 participant