Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[selectors-4] Case-sensitive attribute selectors #2101

Closed
valtlai opened this issue Dec 10, 2017 · 21 comments
Closed

[selectors-4] Case-sensitive attribute selectors #2101

valtlai opened this issue Dec 10, 2017 · 21 comments

Comments

@valtlai
Copy link
Contributor

valtlai commented Dec 10, 2017

The Selectors spec says:

By default case-sensitivity of attribute names and values in selectors depends on the document language. To match attribute values case-insensitively regardless of document language rules, the attribute selector may include the identifier i before the closing bracket (]).

Could there be a similar flag for case-sensitive matching?

I needed to select <ol> with type=a or type=A and apply different styles to them.

@counter-style list-a {
    system: extends lower-alpha;
    suffix: ') ';
}

@counter-style list-A {
    system: extends upper-alpha;
    suffix: ') ';
}

ol[type=a] {
    list-style: list-a;
}

ol[type=A] {
    list-style: list-A;
}
<ol type="a">
    <li>foo</li>
    <li>bar</li>
    <li>baz</li>
</ol>

<ol type="A">
    <li>foo</li>
    <li>bar</li>
    <li>baz</li>
</ol>

The desirable result is:

a) foo
b) bar
c) baz

A) foo
B) bar
C) baz

But this doesn’t work because browsers match type attributes case-insensitively, so the second style rule overwrites the first one.

Thus the actual result is:

A) foo
B) bar
C) baz

A) foo
B) bar
C) baz
@SelenIT
Copy link
Collaborator

SelenIT commented Dec 11, 2017

That's very strange! Both HTML specs (WHATWG and W3C) state that the value of this attribute should be compared case-sensitively (and the Rendering section of the both specs repeats this). The DOM value of the type propery of the element, which "reflects" the value of the attribute, is also reported case-sensitively. Is this wrong case attribute selector matching a bug in all browsers?

@valtlai
Copy link
Contributor Author

valtlai commented Dec 11, 2017

Yeah, that feels very strange! The type attribute is always compared case-insensitively in other elements too.

A test case:

<style>
    p, foo {
        display: block;
        height: 2em;
    }

    [type=a] { background: blue; }
    [type=A] { background: green; }
</style>

<p type="a"></p>
<p type="A"></p>

<foo type="a"></foo>
<foo type="A"></foo>

All the boxes are green.

Tested with Chrome 63 (+ Canary 65), Firefox 57 (+ Nightly 59) and Safari 11 (+ Technology Preview 45).

@cork
Copy link

cork commented Dec 11, 2017

Just wanted to clarify that this is specifically the type attribute, ANY other attribute works fine https://jsfiddle.net/vhed285n/1
https://jsfiddle.net/vhed285n/2

@cpplearner
Copy link

https://html.spec.whatwg.org/multipage/semantics-other.html#case-sensitivity-of-selectors:

Attribute selectors on an HTML element in an HTML document must treat the values of attributes with the following names as ASCII case-insensitive, with one exception as noted in the rendering section:

  • [...]
  • type (except as specified in the rendering section)
  • [...]

The exception seems specific to user agent stylesheet.

@SelenIT
Copy link
Collaborator

SelenIT commented Dec 11, 2017

Well, while this probably technically explains the issue, implying that case-sensitivity of the value of this attribute is limited to the user agent stylesheet looks like a kind of self-contradiction in the spec. The note in the spec explicitly allows "to redefine the default CSS list styles used to implement this attribute in CSS user agents"; the values "A" and "a", "I" and "i" clearly have different semantics; impossibility to express this semantic in the author CSS while it is possible in the user agent CSS doesn't make much sense.

I admit that it might be not easy to differentiate the ol element's type attribute, which probably was intended to be compared case-sensitively, from, e.g., the input element's type attribute that clearly should be compared case-insensetively, in the selectors like *[type="..."]. Maybe, since list type values don't overlap any other type values, the exception should be made for the specific values (e.g. "the type attribute value is treated as ASCII case-insensitive, except the values "a", "A", "i", and "I", which are treated as ASCII case-sensitive")?

@upsuper
Copy link
Member

upsuper commented Dec 11, 2017

Maybe a bit offtopic, but in Gecko, we handle type attribute of list elements manually with a mechanism called "attribute mapping", and thus we don't do any case sensitive matching for that attribute in any case. What I want to say is that, stuff in rendering section isn't required to be presented as-is in browsers as far as browsers have conformant behavior, so rendering section in specs may always be able to use some magic which CSS itself doesn't really have, although I would agree there should be as little magic as possible.

I suppose that making type attribute in CSS matched case-insensitive has its historical reason, and making it case-insensitive in content may be the easiest approach (rather than, say, having single character case-sensitive, but case-insensitive otherwise).

@SelenIT
Copy link
Collaborator

SelenIT commented Dec 11, 2017

My understanding was that a general agreement has been to remove as much such browser-specific magic as possible, replacing it with CSS ways to express the same behavior, even for more complicated cases like the default behavior of the fieldset element. So I would rather try to find the CSS solution for this issue, too. If switching the case-sensitivity for the type attribute based on some heuristics would require too much complexity, I would be happy with the explicit case-sensitivity flag in addition to existing case-insensitivity flag, as @valtlai suggested above.

@tabatkins tabatkins added the selectors-4 Current Work label Dec 12, 2017
@Nadya678
Copy link

it works properly after changing to list-b from list-A. the [] selector is case sensitive inside double quotes.

BTW. For historical reasons selector "HtMl TABLE" is equivalent of "html table". The same manner for CSS: DISPLAY: TABLE works like display:table.

Many developer in history write HTML/CSS code with use of only capital letters. The code is less readable but... It is fact, the sites still works.

@Nadya678
Copy link

Nadya678 commented Dec 17, 2017

All the boxes are green.

Tested with Chrome 63 (+ Canary 65), Firefox 57 (+ Nightly 59) and Safari 11 (+ Technology Preview 45).

Looks like next quirks mode. Historical cause where "i" was not known for [] selector? Mainly for input[type...]?

If we delete the manner, the old sites stop to show properly. For example HTML:

<INPUT TYPE="SUBMIT" /> (capital letters)
or
<Input Type="Submit" />

and css

input [type="sumbit"] 
{
   background:green;
}

Here is evidence for my words:

https://jsfiddle.net/r7xm0dfx/

"disabled" works (in Cr, I don't tested FF and IE) in the same manner like "type".

The type, checked and disabled were historically often stylized but the "i" was not known in past.

@SelenIT
Copy link
Collaborator

SelenIT commented Dec 17, 2017

@Nadya678, you are explaining the general rule. However, the HTML spec (reference provided above by @cpplearner) contains one exception from this rule specifically made for a type attribute. And it's not clear from that spec if this exception should apply only to User Agent stylesheets or to CSS in general.

@Nadya678
Copy link

After particular reading of the cited spec I think there shall be issued a bug to Chromium, Mozilla Firefox and MSIE developers.

The case-insensitive checking of ol[type] selector blocks to style the numbered lists.

@therealglazou
Copy link
Contributor

I think this is therefore not a problem in the selectors-4 spec and the current issue should be closed.

@SelenIT
Copy link
Collaborator

SelenIT commented Jan 30, 2018

I believe that introducing the modifier to the attribute selector that makes the comparison always case-sensitive is a valid topic for [selectors-4]. Custom styling for different types of ordered lists appears to be a valid use case for it.

@beckiechoi
Copy link

Ran into the same issue as the OP. It'd be great to rely on type instead of needing to add a data attribute just to work around this issue.

@tabatkins
Copy link
Member

Yup, this is a valid issue. It's sad that HTML now has case-insensitive-by-default matching of some attributes, and that set happens to include the one attribute that specifically needs case-sensitive handling on one element, but hey, them's the breaks.

Per whatwg/html#4158 the HTML folks would like something like this, so Agenda+ for discussion.

@fantasai
Copy link
Collaborator

fantasai commented Nov 8, 2018

@tabatkins Umm, so why does that set include this attribute exactly? Not including it as case-insensitive seems to make the most sense?

@tabatkins
Copy link
Member

Backwards-compat reasons. type values on other elements need to match selectors case-insensitively by default (because they always have, for some reason), and it's too weird to separate the attribute's behavior on ol from its behavior on other elements.

@dbaron
Copy link
Member

dbaron commented Nov 14, 2018

Adding an flag here that does the opposite of the i flag (probably called s for "sensitive", since the i is for "insensitive", although I suppose one could argue for c for "case-sensitive") seems reasonable to me.

@fantasai
Copy link
Collaborator

fantasai commented Nov 14, 2018

@tabatkins Why is it weird? It doesn't seem weird to me. Only type on OL has values which are sensitive to case, so making it the only one that's case-sensitive makes sense to me.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed Case-sensitive attribute selectors, and agreed to the following:

  • RESOLVED: Add a Sensitive 's' flag
The full IRC log of that discussion <dael> Topic: Case-sensitive attribute selectors
<dael> github: https://github.com//issues/2101
<dael> TabAtkins: Turns out there's a couple of HTML attributes that must be matched case insensitive in selectors.
<dael> TabAtkins: We let UAs or Authors match case insensitive for UA stylesheet. Type attribute requires this.
<dael> TabAtkins: ol uses type in way that requires case sensitivity
<dael> TabAtkins: Because type elsewhere requires case insensitive it would be weird and bad if some were sensitive and some not. Just like we added i tag to allow authors to opt in, we can do opposite to force case sensitive.
<dael> TabAtkins: Put in a UA style sheet and in a few places where author needs to match against case sensitive they use that.
<dael> fantasai: I don't have obj to adding the flag. Confused as to why type attribute it's inherently case sensitive on ol
<dael> dbaron: It's per attribute, not attribute+element. attribute+element is a lto more complicated and this is only use case
<dael> TabAtkins: I like s as the flag. Insensitive = i, Sensistive=s
<florian> +1 to "s"
<dael> fantasai: Agreed
<dael> astearns: Obj to adding a Sensistive 's' flag?
<dael> RESOLVED: Add a Sensitive 's' flag
@verdy-p
Copy link

verdy-p commented Aug 29, 2021

Is there a way to support additional flags for matching qualities/inequalities?

Such as:

  • a 'n' flag for normalizing strings to compare (both to NFC, or equivalently NFD internally if this is more convenient to the implementation)
  • a 'k' flag (for NFKC, or NFKD): the result is also in NFC or NFD, but matching is more lenient (for example a "wide" Latin letter 'a' would match a Basic Latin letter 'a'; adding the 'n' flag to the 'k' flag would have no effect)
  • a 'f' flag for "Safe NFC" (or Safe NFD), i.e. ignoring extra "CGJ" added by the "safe normalization" to limit combining sequences to 30 characters for canonical equivalences/composition/decomposition: CGJ as splitting combining sequences into several ones ; note that the result "safely normalized" string is not necessarily "canonically equivalent", as canonical equivalence is bounded by characters with combing class 0 (including base charactrers, controls, and CGJ); using the 's' flag could be costly in terms of buffering as it may require long reordering if resulting strings are normalized by 'n' or 'k'.
  • possibly the inverse flags 'N', 'K', 'F' if one does not want to use browser's default behavior and the browser already applies some of the 3 normalizations above (all described in the Unicode Standard).

So there could be multiple flags before the closing ']', they coulld be speciified in any order, but if they contradict each other (e.g. 'i' and 's'; or 'n' and 'N'...), the last one takes place: flags are evaluated in order from left to right.

The idea is to support large values for attributes or pseudo-attributes containing arbitrary Unicode text (e.g. data from a large input form field or large text elements, including text fragments matched by pseudo-attributes).

Those flags could also apply to regexp matchings using operators with '~' instead of '='.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment