I was just recently asked if attribute selectors must use quotes around the value. In other words, are both the following two selectors legal?
a[href="http://www.meyerweb.com"] {font-weight: bold;}
a[href=http://www.complexspiral.com] {font-style: italic;}
“No, they’re optional,” I said with assurance. And then the doubts started to gnaw at me. What if they actually weren’t, which might make sense given that you can require the exact match of a space-separated list of attribute values? By this, I mean that if you declare:
div[class="this is a test"] {color: orange;}
…then the selector will match any div
element whose class
attribute is exactly this is a test
, in that order, and with nothing else in the attribute value. Or so I’ve always been given to understand. In that case, if you left off the quotes, couldn’t that somehow be confusing to the browser? Maybe not, but it still bothered me.
So I went digging through CSS2.1, Appendix G and found the grammatical definition of an attribute selector.
attrib
: '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S*
[ IDENT | STRING ] S* ]? ']'
;
You all understood that, right? Uh-huh. Me either. (This is one of those hostile-to-outsiders posts I mentioned a while back.)
I never liked grammar in school, and I still don’t, but it is sometimes sadly necessary. So here goes. When you run down the definitions of the all-caps words (I think those are tokens) you find that IDENT is an identifier, which is sort of a catch-all bin for things like selectors, property names, values, and such. Fine. STRING, on the other hand, is a collection of symbols and other fun stuff, again including the non-ASCII range but not the ASCII range. But then it includes the entirety of Unicode. I’m not sure how much sense that makes, but whatever.
So the whole point of this is: if quotes around an IDENT are optional, wouldn’t it have made more sense to say this?
attrib
: '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S*
[ STRING? IDENT STRING? ] S* ]? ']'
;
Or even:
attrib
: '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S*
[ '"'? IDENT '"'? ] S* ]? ']'
;
It’s the [ IDENT | STRING ]
from the original definition that has me befuddled. It seems like it’s saying you can include an IDENT or a STRING but not both, and since IDENT doesn’t include quotes, that implies that you can either drop in an identifier, or a string with quotes. Why is this a good idea? Does it mean that any identifier has to be unquoted? Does it mean that there’s no practical distinction between a STRING and an IDENT in this situation? Does it mean that quotes prevent the inclusion of anything useful? Somebody let me know.