Reputation: 26444
I have the following code
<style type="text/css">
.el3 { font-family: Arial, sans-serif; }
.el1, .el3 { font-family: Tahoma, sans-serif; }
.el1, .el2, .el3 { font: Helvetica; }
</style>
<div class="el3">Text</div>
When I load up my browser and inspect the element with class el3
I find that the font-family is Tahoma, sans-serif
.
I know that I didn't add the classes .el1
and .el2
to my HTML, but I still expected the result to be Helvetica
. When I inspect the element, that ruling is crossed out.
There are two reasons why the font should be Helvetica.
The specificity formula is as follows
The score is typically measured in bracket notation. In my example, the three rules would be given these three specificity scores
.el1 => {0,0,1,0}
.el1,.el2 => {0,0,2,0}
.el1, .el2, .el3 => {0,0,3,0}
It shouldn't make a difference whether .el1
and .el2
are defined. 3 class selectors should have higher precedence than 2 class selectors.
The second reason is that even if they both had the same precedence, the tiebreaker would go to rule 3 because it appears last.
It also can't possibly be because for the first two rules I used the font-family
property and for the last one I used font
.
Based on the precedence rules, the font should clearly be Helvetica
.
Upvotes: 1
Views: 270
Reputation: 37065
The issue isn't specificity, it's validity. With the given rules:
.el3 { font-family: Arial, sans-serif; }
.el1, .el3 { font-family: Tahoma, sans-serif; }
.el1, .el2, .el3 { font: Helvetica; }
The last one isn't applied because it's treated as invalid. You can confirm by testing:
.el3 { font: Arial, sans-serif; }
.el1, .el3 { font: Tahoma, sans-serif; }
.el1, .el2, .el3 { font: Helvetica; }
Where none of the font-families are applied. This seems to be related to how shorthand properties (like font
) are validated. If I change the second set of test rules to:
.el3 { font: 1em Arial, sans-serif; }
.el1, .el3 { font: 1em Tahoma, sans-serif; }
.el1, .el2, .el3 { font: 1em Helvetica; }
Then the last rule gets applied. This seems contrary to the CSS spec on shorthand properties which actually warn that using a shorthand without specifying all properties will result in the property being treated as set to the initial value for the property:
When values are omitted from a shorthand form, unless otherwise defined, each “missing” sub-property is assigned its initial value.
This means that a shorthand property declaration always sets all of its sub-properties, even those that are not explicitly set. Carelessly used, this might result in inadvertently resetting some sub-properties. Carefully used, a shorthand can guarantee a “blank slate” by resetting sub-properties inadvertently cascaded from other sources. For example, writing background: green rather than background-color: green ensures that the background color overrides any earlier declarations that might have set the background to an image with background-image.
But I think since the rule isn't being applied at all, the client (browser) is instead treating the shorthand property with only one single-property being set as invalid outright.
I'm not sure what their source is, but the MDN doc on the font property does mention this issue explicitly:
Note: There are a few caveats when using the CSS font shorthand. If these conditions are not met, the property is invalid and is entirely ignored.
- Except when using a keyword, it is mandatory to define the value of both the font-size and the font-family properties.
- Not all values of font-variant are allowed. Only the values defined in CSS 2.1 are allowed, that is normal and small-caps.
- Though not directly settable by font, the values of font-stretch, font-size-adjust and font-kerning are also reset to their initial values.
- The order of the values is not completely free: font-style, font-variant and font-weight must be defined, if any, before the font-size value. The line-height value must be defined immediately after the font-size, preceded by a mandatory /. Finally the font-family is mandatory and must be the last value defined (inherit value does not work).
If you look at the font
property specification, it has the following:
Value: [ [ <'font-style'> || <'font-variant'> || <'font-weight'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
which for anyone who can sight-read EBNF (not me) can see means that the shorthand requires either (a keyword) or (font-size and font-family) to be set in order be considered valid. The grammar above looks kinda like:
[
[ <'font-style'> || <'font-variant'> || <'font-weight'> ]
?
<'font-size'> [ / <'line-height'> ]
?
<'font-family'>
]
| caption | icon | menu | message-box | small-caption | status-bar | inherit
Upvotes: 3