Where can a number appear in a selector? - css

When looking into yet another question about a class name starting with a digit that didn't work as expected, the thought suddenly hit me that I don't know what goes wrong.
Here's a simple example:
.123 {color:blue;}
<div class="123">This is something 123</div>
This doesn't make the output blue.
And the reason is: .123 is not a valid CSS selector, because it looks like a number.
Yeah, but, why? Why would a CSS parser be looking for numbers in a selector? Is there actually a reason for selectors to contain numbers? Can anybody provide an example of such a selector?
Edit: As per the comments, arguments inside parentheses and brackets can be numbers; for example nth-child(2) or [colspan=2], so my question is about numbers outside of those.

The simplest answer is probably, that the CSS Selector Spec doesn't allow it and (most) browsers seem to honor this, even though it was probably technically possible to allow leading numbers (or hyphens):
https://www.w3.org/TR/css3-selectors/#lex
A very simplified explanation: A Selector consists of an (optional) type selector (e.g. # for ids, . for classes) a "nmstart" and optional "nmchar" parts. The "nmstart" part doesn't allow numbers, while the "nmchar" part does:
nmstart [_a-z]|{nonascii}|{escape}
nmchar [_a-z0-9-]|{nonascii}|{escape}

As MattDiMu has already pointed out in their answer, the place to find out how selectors should be validated is within section 10 of the CSS Selectors specification: The grammar of Selectors, which itself is a clone of the CSS2.2 specification's Grammar section with a few bits ommitted.
It's in the CSS2.2 specification that we're told why numbers are not valid at the start of CSS selectors:
In CSS1, a class name could start with a digit (".55ft"), unless it was a dimension (".55in"). In CSS2, such classes are parsed as unknown dimensions (to allow for future additions of new units). To make ".55ft" a valid class, CSS2 requires the first digit to be escaped (".\35 5ft")
So in short, it's to avoid confusion. .1px is a valid unit which could easily be mistaken for a class of "1px", however we can use numbers at the start of a selector like this if we escape it. In the below example, I'm able to target the div element whose class is "1px" by escaping the 1 within the class selector (as .\31 px):
.\31 px {
color: red;
}
<div class="1px">Hello, world!</div>

For people who are still interested in this subject, I found one situation where selectors can look like numbers, indeed, where selectors are numbers. That is inside a #keyframes at-rule.
Example:
#keyframes anim {
.6% {color:white;}
100% {color:red;}
}
They really are percentages (they won't work without the % sign), but they start with a digit or even a period and a digit, so these are actual examples of selectors that could confuse parsers if .6% for class "6%" would be allowed.

Related

How to consistently override component's style properties in Nativewind? [duplicate]

Researching specificity I stumbled upon this blog - http://www.htmldog.com/guides/cssadvanced/specificity/
It states that specificity is a point-scoring system for CSS. It tells us that elements are worth 1 point, classes are worth 10 points and IDs are worth 100 points. It also goes on top say that these points are totaled and the overall amount is that selector's specificity.
For example:
body = 1 point
body .wrapper = 11 points
body .wrapper #container = 111 points
So, using these points, I expect the following CSS and HTML to result in the text being blue:
#a {
color: red;
}
.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o {
color: blue;
}
<div class="a">
<div class="b">
<div class="c">
<div class="d">
<div class="e">
<div class="f">
<div class="g">
<div class="h">
<div class="i">
<div class="j">
<div class="k">
<div class="l">
<div class="m">
<div class="n">
<div class="o" id="a">
This should be blue.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Why is the text red when 15 classes would equal 150 points compared to 1 ID which equals 100 points?
Apparently the points aren’t just totaled; they’re concatenated. Read more about that here - http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html
Does that mean that the classes in our selector = 0,0,15,0 OR 0,1,5,0?
(my instincts tell me it’s the former, as we KNOW the ID selector’s specificity looks like this: 0,1,0,0)
Pekka's answer is practically correct, and probably the best way to think about the issue.
However, as many have already pointed out, the W3C CSS recommendation states that "Concatenating the three numbers a-b-c (in a number system with a large base) gives the specificity." So the geek in me just had to figure out just how large this base is.
It turns out that the "very large base" employed (at least by the 4 most commonly-used browsers*) to implement this standard algorithm is 256 or 28.
What this means is that a style specified with 0 ids and 256 class-names will over-ride a style specified with just 1 id. I tested this out with some fiddles:
255 classes are not enough to override 1 id
...but 256 classes are enough to override 1 id
...and 256 tag-names are enough to override 1 class-name
...but, alas 256 ids are not enough to override 1 inline style (Updated 2012/8/15 -- you'll have to use !important)
So there is, effectively, a "point system," but it's not base 10. It's base 256. Here's how it works:
(28)2 or 65536, times the number of ids in the selector
(28)1 or 256, times the number of class-names in the selector
(28)0 or 1, times the number of tag-names in the selector
This isn't very practical for back-of-the-envelop exercises to communicate the concept.
That's probably why articles on the topic have been using base 10.
***** [Opera uses 216 (see karlcow’s comment). Some other selector engines use infinity — effectively no points system (see Simon Sapin’s comment).]
Update, July 2014:
As Blazemonger pointed out earlier in the year, webkit browsers (Chrome, Safari) now appear to use a higher base than 256. Perhaps 216, like Opera? IE and Firefox still use 256.
Update, March 2021:
Firefox no longer uses 256 as a base.
Good question.
I can't tell for sure - all the articles I manage to find avoid the example of multiple classes, e.g. here - but I assume that when it comes to comparing the specifity between a class selector and an ID, the class gets calculated with a value of 15 only, no matter how detailed it is.
That matches my experience in how specificity behaves.
However, there must be some stacking of classes because
.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o
is more specific than
.o
the only explanation I have is that the specificity of stacked classes is calculated only against each other but not against IDs.
Update: I half-way get it now. It is not a points system, and the information about classes weighing 15 points is incorrect. It is a 4-part numbering system very well explained here.
The starting point is 4 figures:
style id class element
0, 0, 0, 0
According to the W3C explanation on specificity, the specificty values for the abovementioned rules are:
#a 0,1,0,0 = 100
classes 0,0,15,0 = ... see the comments
this is a numbering system with a very large (undefined?) base.
My understanding is that because the base is very large, no number in column 4 can beat a number > 0 in column 3, the same for column 2, column 1 .... Is this correct?
I'd be interested whether somebody with a better grasp at Math than me could explain th numbering system and how to convert it to decimal when the individual elements are larger than 9.
The current Selectors Level 4 Working Draft does a good job of describing Specificity in CSS:
Specificities are compared by comparing the three components in order: the specificity with a larger A value is more specific; if the two A values are tied, then the specificity with a larger B value is more specific; if the two B values are also tied, then the specificity with a larger c value is more specific; if all the values are tied, the two specifities are equal.
This means that the values A, B and C are completely independent of each other.
15 classes doesn't give your selector a specificity score of 150, it gives it a B value of 15. A single A value is enough to overpower this.
As a metaphor, imagine a family of 1 grand parent, 1 parent and 1 child. This could be represented as 1,1,1. If the parent has 15 children, that doesn't suddenly make them another parent (1,2,0). It means that the parent has an awful lot more responsibility than they had with just 1 child (1,1,15). ;)
The same documentation also goes on to say:
Due to storage limitations, implementations may have limitations on the size of A, B, or c. If so, values higher than the limit must be clamped to that limit, and not overflow.
This has been added to tackle the problem presented in Faust's answer, whereby CSS implementations back in 2012 allowed specificity values to overflow into each other.
Back in 2012, most browsers implemented a limitation of 255, but this limitation was allowed to overflow. 255 classes had an A,B,c specificity score of 0,255,0, but 256 classes overflowed and had an A,B,c score of 1,0,0. Suddenly our B value became our A value. The Selectors Level 4 documentation completely irradiates that problem by stating that the limit can never be allowed to overflow. With this implementation, both 255 and 256 classes would have the same A,B,c score of 0,255,0.
The problem given in Faust's answer has since been fixed in most modern browsers.
I am currently using the book CSS Mastery: Advanced Web Standards Solutions.
Chapter 1, page 16 says:
To calculate how specific a rule is, each type of selector is assigned
a numeric value. The specificity of a rule is then calculated by
adding up the value of each of its selectors. Unfortunately,
specificity is not calculated in base 10 but a high, unspecified, base
number. This is to ensure that a highly specific selector, such as an
ID selector, is never overridden by lots of less specific selectors,
such as type selectors.
(emphasis mine) and
The specificity of a selector is broken down into four constituent
levels: a, b, c, and d.
if the style is an inline style, then a = 1
b = the total number of id selectors
c = the number of class, pseudo-class, and attribute selectors
d = the number of type selectors and pseudo-element selectors
It goes on to say that you can often do the calculation in base-10, but only if all columns have values less than 10.
In your examples, ids are not worth 100 points; each is worth [0, 1, 0, 0] points. Therefore, one id beats 15 classes because [0, 1, 0, 0] is greater than [0, 0, 15, 0] in a high-base number system.
I am fond of comparison of Specificity ranking to Olympic Games medal table (gold first method — based first on the number of gold medals, then silver and then bronze).
It works also with your question (huge number of selectors in one specificity group). Specificity considered each group separately. In real world I've very rarely seen case with more than a dozen selectors).
There is also quite good specificity calculator available here. You can put your example (#a and .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o) there and see the results.
Example of Rio 2016 Olympic Games medal table looks like
I don't believe that the blog's explanation is correct. The specification is here:
http://www.w3.org/TR/CSS2/cascade.html#specificity
"Points" from a class selector can't add up to be more important than an "id" selector. It just doesn't work like that.
I would say that:
Element < Class < ID
I think they only stack into depending what you get if it is multiple of the same.
So a Class will always overide the element and ID always over the Class but if it is down to which of 4 elements where 3 is to blue and 1 is to red it will be blue.
For Example:
.a .b .c .d .e .f .g .h .i .j .k .l
{
color: red;
}
.m .n .o
{
color blue;
}
Should turn out red.
See Example http://jsfiddle.net/RWFWq/
"if 5things say red and 3 say blue well Ima go red"

Why doesn't min() (or max()) work with unitless 0?

I've searched around for an answer to this, but couldn't find any useful information. I'm trying to set the top property of an element in CSS to max(0, 120vh - 271px). I've tried several variations of this:
top: max(0, 120vh - 271px);
top: max(0, (120vh - 271px));
top: max(0, calc(120vh - 271px));
Is there something wrong with my syntax? I keep getting Chrome telling me that this is an invalid property error.
In practice, I'm actually using CSS variables for the numbers. so 120vh is actually var(--height) or something like that. When I use CSS variables, the line just doesn't do anything. It doesn't apply the style, and I don't get any warnings. What am I doing wrong here?
I'm using the newest version of Chrome (83 I believe), so this should be supported.
You need to add a unit to 0 otherwise it's confusing for the browser to handle the comparison between a uniteless value (a <number>) and a value with unit (a <length>) and the top property accept a <length> not a <number>
top: max(0px, 120vh - 271px)
To understand this, you need to follow the specification:
The min() or max() functions contain one or more comma-separated calculations, and represent the smallest (most negative) or largest (most positive) of them, respectively.
Then for calculations:
A calc() function contains a single calculation which is a sequence of values interspersed with operators, and possibly grouped by parentheses (matching the <calc-sum> grammar),
So the content of min()/max() is treated like the one of calc() then from the type checking
A math function can be many possible types, such as <length>, <number>, etc., depending on the calculations it contains, as defined below. It can be used anywhere a value of that type is allowed.
and
Note: Altho there are a few properties in which a bare <number> becomes a <length> at used-value time (specifically, line-height and tab-size), <number>s never become "length-like" in calc(). They always stay as <number>s.
You may get surprised but using top:0 is valid while top:min(0) or top:max(0) is not. To make them valid you need to add the unit.
But you can use opacity: min(0) for example since opacity accept a number as argument.
Worth to note that the same also apply to clamp() since it's equivalent to max(MIN, min(VAL, MAX))
Related: Why doesn't css-calc() work when using 0 inside the equation?

Why must a + or - be surrounded with whitespace from within the Calc() method?

Recently I've started using the calc(...) method within CSS. I quickly learned that code such as: width: calc(100%-2) will not work, though adding white-space before and after the - operator will fix the problem and the calc method will function properly.
After doing a bit of research I found multiple blog posts reference that the white-space is required and many have even pointed to the specification (CSS3 8.1.1) which states:
In addition, whitespace is required on both sides of the + and -
operators. (The * and / operaters can be used without whitespace
around them.)
Now, clearly, the spec tells us that these operators must be wrapped in white-space, but why? I've read further within the spec (through sections 8.1.2-4) and if it's explained in these additional portions, I'm not understanding the reasoning.
In simple terms, could someone explain why it was specified that calc(100% - 1) or even calc(100%/2) is acceptable syntax but not calc(100%-1)?
The - character is one of the allowed characters in CSS idents. Judging by the resolution given here, it seems they wanted to prevent syntactic ambiguities that could arise from using - without whitespace, especially with keyword values such as min-content (although AFAIK keyword values aren't yet allowed within calc() — correct me if I'm wrong).
Not everyone agrees with this resolution, though.
The Mozilla Developer Network explains it quite well:
Note: The + and - operators must always be surrounded by whitespace. The operand of calc(50% -8px) for instance will be parsed as a percentage followed by a negative length, an invalid expression, while the operand of calc(50% - 8px) is a percentage followed by a minus sign and a length. Even further, calc(8px + -50%) is treated as a length followed by a plus sign and a negative percentage.
The * and / operators do not require whitespace, but adding it for consistency is allowed, and recommended.
I think you should first consider how do CSSs identify a length. A length is defined as an optional sign followed by a module and an optional unit of measure (although many properties actually require it):
<CSSlength> := [<sign>]<module>[<unit>]
So, for example, valid CSS lengths are:
-3px
100em
+10pc
0
91
5%
Defining a length like this, the CSS engine parses the following:
calc(100% -1px);
as a length followed by another length. In this case it would be 100% followed by -1px, which doesn't make sense to calc() at all. This is also explained in the relative MDN documentation page.
In order to put two lengths in relation you need to use a distinct operator, therefore, following the above logic, you'll need to use whitespaces:
calc(100% - 1px);

Specifying a list of arbitrary children (no pattern) for nth-child and nth-of-type

So I've now read enough about various funky nth-child and nth-of-type patterns to have the seventh son of the seventh son fly a space-ship backwards to Pluto and back. But I still haven't come across a way to simply provide a list of specific children in a concise way. It'd work like so:
td:nth-child(1,3,7,10) { text-align: center; ... }
The above syntax would obviously be mighty convenient for example when styling table cells. That something like this would exist, seems like a no-brainer to me. Of course I can always use:
td:nth-child(1), td:nth-child(3), td:nth-child(7), td:nth-child(10) { ... }
But that's just so much redundant repetition and clutter in my CSS. Particularly when I need to also have a class name specified before the td. Then it becomes as bloated as this, for example:
.study_references td:nth-child(1), .study_references td:nth-child(3), .study_references td:nth-child(7), .study_references td:nth-child(10) { ... }
I'd really like to have my CSS look a bit more elegant, concise, and readable. Is there really no way to provide a specific list of nth-s to the selector in one shot? (Not looking for a preprocessor fix.)
Unfortunately there isn't. Neither Selectors 4 nor CSS Syntax 3 have extended the An+B notation to allow a list of such expressions as in your 1,3,7,10 example either, though I wonder if it may be worth suggesting as it seems pretty doable. In fact, I just went ahead and suggested this (I couldn't find any earlier proposals using either the mailing list search, or Google).
The closest to a solution that Selectors 4 offers is via the :matches() pseudo, which makes it so that the only bit you have to repeat is :nth-child(...):
.study_references td:matches(
:nth-child(1), :nth-child(3), :nth-child(7), :nth-child(10)
) { ... }
But this is still far from ideal, and is not yet implemented anyway.
If you can suss out at least part of a pattern from most of the numeric indices you're looking for, you could modify this pattern as necessary using :not() and/or additional :nth-child()/:nth-last-child() and still pick up the right elements. See this answer of mine where I refactor [9, 11, n+12] into [n+9 except 10]. However this is likely more trouble than it's worth, and the resulting selector will almost always be far from elegant unless you get really lucky as I did above.
When CSS lacks a feature, Sass can help. You can try a formula like this one in Sass. It's not the most elegant solution, but perhaps you can improve on it.
$children: 1,3,7,10;
#each $child in $children {
td:nth-child(#{$child}) {
...
}
}

Why is there two different CSS attribute selector namely, [att|=val],[att^=val] selector for same work?

From w3c.org, these two CSS attribute selectors:
[att|=val]
[att^=val]
search for attribute value which starts with val or exactly val.
If I am right why, is there two different selector for the same work?
What is the difference between those two selectors?
They both work the same, but att|=val was developed to select something like language codes or if you're following the naming convention where you split words with - (e.g. simple-attribute-name), you can make sure just to select the part you're looking for.
An example where both won't work the same:
You have 2 elements:
<span att="simple-attribute-name">
<span att="simpleattributename">
att|="simple" will match the first span element, but won't match the second one, because simple is not followed by a -.
att^="simple" will match both elements, because both att values start with simple.
This JSFiddle shows an example that this works:
att^="simple" makes both texts bold but
att|="simple" selects only first text and makes it red.
I can't come up with an attribute value that |= matches that ^= does not. The specifications say
[att|=val]
Represents an element with the att attribute, its value either being exactly "val" or beginning with "val" immediately followed by "-" (U+002D). This is primarily intended to allow language subcode matches (e.g., the hreflang attribute on the a element in HTML) as described in BCP 47 ([BCP47]) or its successor. For lang (or xml:lang) language subcode matching, please see the :lang pseudo-class.
So it seems like |= was developed for a specific purpose. You would want to use it in cases where you want to match val- but not value.
|= existed in selectors level 2.1. ^= did not.

Resources