CSS attribute selector and case sensitivity with the "type" attribute vs. made-up attributes
Asked Answered
F

1

9

I'm trying to style an OL based on its type attribute. The list-style attributes for all ULs and OLs have been wiped out previously by another CSS stylesheet which I cannot really modify, and I need to re-style the list-style, taking the type into account, i.e. if the OL should use Roman characters or alphanumerics, etc.

That's easy, I thought; I'll just use the attribute selector to target the OLs based on the value of the type attribute. The attribute selector is case sensitive, so this should be easy, right?

Wrong - at least when you try to use the standard "type" attribute.

Here's an example (which works):

/* Remove default list style */
ul, ol { list-style:none; }

/* This works, using a non-standard foo attribute. The selector is case sensitive, so I can target 'i' and 'I' separately */
ol[foo='i'] {
  list-style-type:lower-roman;
}

ol[foo='I'] {
  list-style-type:upper-roman;
}
<ol foo="i">
  <li>Styled with lower case roman</li>
  <li>Styled with lower case roman</li>
</ol>

<ol foo="I">
  <li>Styled with uppercase roman</li>
  <li>Styled with uppercase roman</li>
</ol>

Now, replace foo with type and try again:

/* Remove default list style */
ul, ol { list-style:none; }

/* Trying to use the standard type attribute, the selector is no longer case sensitive, so I cannot style 'i' and 'I' individually .... */
ol[type='i'] {
  list-style-type:lower-roman;
}

ol[type='I'] {
  list-style-type:upper-roman;
}
<ol type="i">
  <li>Should be lower-case roman</li>
  <li>Should be lower-case roman</li>
</ol>

<ol type="I">
  <li>Should be upper-case roman</li>
  <li>Should be upper-case roman</li>
</ol>

Now it's like the selector is no longer case-sensitive and both lists are affected, and both use upper-case Romans.

I've not been able to find any information whether this is the correct behaviour or not, that is, when using a known attribute such as 'type' v.s using non-standard attribute like 'foo'. The fact that this happens both in Chrome and Firefox makes be believe that it's not a bug.

Any ideas?

Here is a CodePen to mess with: https://codepen.io/haukurhaf/pen/NOQYOz

Frentz answered 1/11, 2018 at 10:47 Comment(2)
“Any ideas?” - only for a workaround to make dealing with this situation a little less painful: You could perhaps copy the content of the type attribute into a data-type or something (either via JavaScript that runs over the content, or via server-side pre-processing of the data), and then have your CSS rules target that one instead …Tonsure
@Tonsure Yeah, actually thought about doing something like that as a workaround, if required. Thanks.Frentz
M
7

This, and the broader use case of forcing attribute selectors to match case-sensitively, has been addressed by the introduction of a case-sensitive attribute selector flag s:

ol[type='i' s] {
  list-style-type:lower-roman;
}

ol[type='I' s] {
  list-style-type:upper-roman;
}

Now we await implementations...


The HTML spec seems to suggest that the behavior of the type attribute of ol is incorrect, but its use of certain keywords makes this less than 100% clear. Section 4.16.2 uses "must":

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)

All other attribute values and everything else must be treated as entirely case-sensitive for the purposes of selector matching.

And points to section 14.3.8, which uses "expected" as described in the abstract of section 14 (tl;dr: a browser is not necessarily in violation of the spec if it chooses not to follow what is stated as "expected" behavior):

The following rules are also expected to apply, as presentational hints:

@namespace url(http://www.w3.org/1999/xhtml);

ol[type="1"], li[type="1"] { list-style-type: decimal; }
ol[type=a], li[type=a] { list-style-type: lower-alpha; }
ol[type=A], li[type=A] { list-style-type: upper-alpha; }
ol[type=i], li[type=i] { list-style-type: lower-roman; }
ol[type=I], li[type=I] { list-style-type: upper-roman; }
ul[type=none i], li[type=none i] { list-style-type: none; }
ul[type=disc i], li[type=disc i] { list-style-type: disc; }
ul[type=circle i], li[type=circle i] { list-style-type: circle; }
ul[type=square i], li[type=square i] { list-style-type: square; }

In the above style sheet, the attribute selectors for the ol and li elements are expected to be treated as case-sensitive.

Given that the expected behavior as described in the latter is more in line with author expectations than actual browser behavior, I'm going to say that this is indeed incorrect behavior despite the permissiveness of the word "expected".

Militia answered 1/11, 2018 at 11:24 Comment(2)
On closer inspection, it looks like the exception applies only to UA stylesheets, making the behavior you're seeing correct for author CSS. This blows my mind, because all that does is prevent authors from applying custom uppercase/lowercase counter styles for no good reason other than "it's interop and nobody is interested in changing it".Militia
@HaukurHaf: I just filed an issue at WHATWG: github.com/whatwg/html/issues/4158 (I also linked back to this question, though your situation is better suited to list-style: revert in an ideal world where that is widely supported.)Militia

© 2022 - 2024 — McMap. All rights reserved.