1

I'm restyling a third-party platform (MindTouch 4). While doing so, I'm trying to declare all the various styling properties as broadly as possible, to prevent the unintentional proliferation of natively-styled areas on the page.

The platform has a custom SELECT control, using markup like this:

<div class="mt-site-nav">
    ...
    <span class="quick-more">
        <span class="drop-link">Current Value</span>
        <ul class="dropdown">
            <li>
                <a href="...">Option 1</a>
            </li>

            <li>
                <a href="...">Option 2</a>
            </li>
        </ul>
    </span>
</div>

I wish to style the option text with font-size 14px; the native default is 12px.

So, I wrote this CSS rule:

body#myid .mt-site-nav .quick-more .dropdown { font-size: 14px; }

However, their native rule still wins when rendering the links in the menu:

@media screen { .dropdown li a { font-size: 12px; } }

In Chrome, I can see that both rules are considered when rendering links in the menu, but their rule (which is declared earlier than mine) wins. I was confused by this, since I thought I had a pretty good handle on specificity. So, I checked my understanding of the rules and manually calculated the weight of both rules.

Mine has specificity 0131 (0 inline style, 1 ID, 3 classes, 1 element name).

Native has specificity 0032 (0 inline style, 0 IDs, 1 class, 2 element names). (I am uncertain how to calculate the contribution of the media selector in the native rule.)

I don't care what base you're using for your math, "0131" is greater than "0032". So, my rule should win.

Yes, I could easily duplicate the element chain that appears in the native rule (i.e. ".dropdown li a"), but I think that's a fragile approach, and I feel it's important to set styling properties as broadly as possible, to facilitate scalability and as a preventative against native styling peeking out between the cracks.

Any help sorting this out is appreciated. I obviously have workable alternatives, so what I'm asking for here is an academic explanation of how these two rules fare in CSS weighting systems.

Thanks very much.

2
  • Have you checked your understanding of the media queries, may be that is where their specificity wins over yours Commented Sep 20, 2013 at 15:07
  • 2
    @AkshayKhandelwal Media queries don't add any specificity at all.
    – cimmanon
    Commented Sep 20, 2013 at 15:11

2 Answers 2

2

The subject of your selector is .dropdown:

body#myid .mt-site-nav .quick-more .dropdown

The subject of the selector within the @media screen rule is a:

.dropdown li a

Since each selector is matching a different element, specificity does not come into play. Your rule applies to the .dropdown element, and the native default applies to the a elements inside it. That's why you see that both rules are being applied. And since the font-size values are in pixels, the a elements will continue to have a 12-pixel font size.

Duplicating the li a portion is not fragile; it's a proper solution (if not the only one) to this sort of problem. Cascading happens on a per-element basis, and if you're not dealing with relative values or inheritance, then targeting the wrong elements isn't going to work as you expect.

Also, screen is a media type (and more extensively a media query), not a selector, and @media rules do not affect the cascade other than to enable or disable the rules inside them depending on whether the media applies to the browser.

6
  • In the absence of any other rules, font settings applied to .dropdown would cascade down to all interior elements. The fact is that I wish all text nodes within the dropdown to use a font-size of 14px, not just text nodes that happen to be inside As inside LIs. This is the issue I mentioned about proliferation of natively-styled areas peripheral to my explicitly styled areas. But, setting aside our differences re: best practices, my analysis of selector specificity tells me that my broad rule should trump the narrow native rule, and it's not clear to me that you have shown otherwise.
    – Tom
    Commented Sep 20, 2013 at 16:07
  • 1
    @Tom: I missed that bit about applying the font size to text nodes, sorry. In that case, you have an easy solution: create another rule body#myid .mt-site-nav .quick-more .dropdown li a { font-size: 1em; } and it'll inherit (not cascade) the 14-pixel size from your existing rule.
    – BoltClock
    Commented Sep 20, 2013 at 16:12
  • 1
    @Tom: As for specificity, the key sentence is, "Since each selector is matching a different element, specificity does not come into play." In other words, specificity is only relevant when you have more than one rule targeting the exact same element, which is not the case here.
    – BoltClock
    Commented Sep 20, 2013 at 16:17
  • So, your analysis is that I'm trying to apply font-sizing through inheritance, and that tactic is being overridden by a targeted selector that has no explicit rivals. That makes sense. And I like your 1em approach; couldn't I use inherit as well? A little unclear on the difference between cascading and inheriting, now, but I'll look them up.
    – Tom
    Commented Sep 20, 2013 at 18:05
  • 1
    @Tom: Yes, you could. The term "cascading" is really counter-intuitive, but this part of the spec sums up each one nicely.
    – BoltClock
    Commented Sep 20, 2013 at 18:10
1

As far as I am aware, the correct syntax for the media query is:

@media screen { .dropdown li a { font-size: 12px; } }

This should solve your problem.

See these fiddles, the first uses the correct media query syntax:

http://jsfiddle.net/SE6fP/

The next uses the incorrect syntax used by your example

http://jsfiddle.net/SE6fP/1/


In additon, here is a little on CSS specifity for anyone who isn't sure how it works:

CSS specifity follows a ruleset and produces a score for each selector.

There are calculator tools available which will explain the specifity value for any give rule.

http://www.w3.org/TR/CSS21/cascade.html#specificity says that the following rules are used:

A selector's specificity is calculated as follows:

  • count 1 if the declaration is from is a 'style' attribute rather than a rule with a selector, 0 otherwise (= a) (In HTML, values of an element's "style" attribute are style sheet rules. These rules have no selectors, so a=1, b=0, c=0, and d=0.)
  • count the number of ID attributes in the selector (= b)
  • count the number of other attributes and pseudo-classes in the selector (= c)
  • count the number of element names and pseudo-elements in the selector (= d)

The specificity is based only on the form of the selector. In particular, a selector of the form "[id=p33]" is counted as an attribute selector (a=0, b=0, c=1, d=0), even if the id attribute is defined as an "ID" in the source document's DTD.

6
  • I never knew we had some specificity calculator. Great Commented Sep 20, 2013 at 15:10
  • @Tom also referenced a specificity calculator in his question when he wrote "calculated" Commented Sep 20, 2013 at 15:16
  • So he did (not sure if I missed that or whether it appeared with an edit) Commented Sep 20, 2013 at 15:17
  • Is it just me or is that calculator bugged? Why is it counting pseudo-classes and pseudo-elements the same? .class:pseudo-class::pseudo-element reports as (0, 0, 1, 2) on Firefox on my PC when it should be (0, 0, 2, 1).
    – BoltClock
    Commented Sep 20, 2013 at 15:22
  • I've changed the link to the one that Tom linked to. Commented Sep 20, 2013 at 15:25

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.