The HTML standard lists a set of legacy attribute names whose values are matched ASCII case-insensitively by CSS attribute selectors. Per the spec this only happens for an HTML element in an HTML document:
"Attribute selectors on an HTML element in an HTML document
must treat the values of attributes with the following names as ASCII
case-insensitive: accept, align,
bgcolor, type, ... vlink."
Blink only checked the "in an HTML document" half of that condition, so SVG elements (and empty-namespace elements) wrongly got case-insensitive value matching too. The fix adds the missing "is an HTML element" check.
Each row sets a legacy attribute to a mixed-case value (FOO) and
checks el.matches('[attr=foo]') -- the lowercase selector value.
An HTML element should match (case-insensitive); SVG and empty-namespace
elements should not (case-sensitive).
| Element | Attribute | Selector | Result | Expected | Status |
|---|
In third_party/blink/renderer/core/css/selector_checker.cc:
const bool case_insensitive =
selector.AttributeMatch() ==
CSSSelector::AttributeMatchType::kCaseInsensitive ||
(selector.LegacyCaseInsensitiveMatch() &&
+ element.IsHTMLElement() &&
IsA<HTMLDocument>(element.GetDocument()));
The element identity is only known at match time, so the
"is an HTML element" half of the spec condition has to live in the
matchers (the parse-time LegacyCaseInsensitiveMatch bit only
knows the attribute name). There are three such match-time decision points,
all fixed with the same element.IsHTMLElement() gate:
selector_checker.cc — matches() and complex selectors
selector_checker-inl.h (EasySelectorChecker) — style application via rule collection (the path this issue is about)
selector_query.cc (MatchCompound) — querySelectorAll fast path
The attribute substring pre-filter (CanIgnoreEntireList) stays
case-insensitive on purpose: it only ever rejects candidates, and the final
decision is always made by the checkers above, so it cannot mask a
case-sensitive result. This makes the pre-existing WPT
values.window.js all-pass (46 failures removed) and a new
style-application test pass for SVG.