Mozilla

Firefox 4: -moz-any() selector grouping

This is a re-post from David Baron’s blog. This feature has landed in Mozilla Central (trunk) and only available with a Firefox Nightly Build for the time being.

Last night I landed support for :-moz-any() selector grouping. This allows providing alternatives between combinators, rather than having to repeat the entire selector for once piece that’s different. For example, it allowed replacing this rule in our user-agent style sheet:

/* 3 deep (or more) unordered lists use a square */
ol ol ul,     ol ul ul,     ol menu ul,     ol dir ul,
ol ol menu,   ol ul menu,   ol menu menu,   ol dir menu,
ol ol dir,    ol ul dir,    ol menu dir,    ol dir dir,
ul ol ul,     ul ul ul,     ul menu ul,     ul dir ul,
ul ol menu,   ul ul menu,   ul menu menu,   ul dir menu,
ul ol dir,    ul ul dir,    ul menu dir,    ul dir dir,
menu ol ul,   menu ul ul,   menu menu ul,   menu dir ul,
menu ol menu, menu ul menu, menu menu menu, menu dir menu,
menu ol dir,  menu ul dir,  menu menu dir,  menu dir dir,
dir ol ul,    dir ul ul,    dir menu ul,    dir dir ul,
dir ol menu,  dir ul menu,  dir menu menu,  dir dir menu,
dir ol dir,   dir ul dir,   dir menu dir,   dir dir dir {
  list-style-type: square;
}

with this one:

/* 3 deep (or more) unordered lists use a square */
:-moz-any(ol, ul, menu, dir) :-moz-any(ol, ul, menu, dir) ul,
:-moz-any(ol, ul, menu, dir) :-moz-any(ol, ul, menu, dir) menu,
:-moz-any(ol, ul, menu, dir) :-moz-any(ol, ul, menu, dir) dir {
  list-style-type: square;
}

In theory, I could even have used:

/* 3 deep (or more) unordered lists use a square */
:-moz-any(ol, ul, menu, dir) :-moz-any(ol, ul, menu, dir) :-moz-any(ul, menu, dir) {
  list-style-type: square;
}

but this would have been slower since it no longer falls into the tag bucket. (If :-moz-any() turns out to be popular, we could add extra code so it’s just as fast, but I haven’t done so yet.)

:-moz-any() is allowed to contain selectors with multiple simple selectors (using the css3-selectors definition of simple selectors, not the CSS 2.1 definition), but it is not allowed to contain combinators or pseudo-elements. So you can write :-moz-any(p.warning.new, p.error, div#topnotice) or :-moz-any(:link, :visited).external:-moz-any(:active, :focus), but you can’t put “div p” or “div > p or “:first-letter” inside :-moz-any().

This has a -moz- prefix for two reasons. First, it’s just a proposal, and hasn’t made its way into any specification. And second, it isn’t quite ready for prime-time, though, since it doesn’t yet handle specificity correctly.

Note: This will be extremely valuable in an HTML5 context when it comes to sections and headings. Since section, article, aside, and nav can be nested, doing something like styling all h1 elements at different depths could be extremely complex.

/* Level 0 */
h1 {
  font-size: 30px;
}
/* Level 1 */
section h1, article h1, aside h1, nav h1 {
  font-size: 25px;
}
/* Level 2 */
section section h1, section article h1, section aside h1, section nav h1,
article section h1, article article h1, article aside h1, article nav h1,
aside section h1, aside article h1, aside aside h1, aside nav h1,
nav section h1, nav article h1, nav aside h1, nav nav h1, {
  font-size: 20px;
}
/* Level 3 */
/* ... don't even think about it*/

With -moz-any():

/* Level 0 */
h1 {
  font-size: 30px;
}
/* Level 1 */
-moz-any(section, article, aside, nav) h1 {
  font-size: 25px;
}
/* Level 2 */
-moz-any(section, article, aside, nav)
-moz-any(section, article, aside, nav) h1 {
  font-size: 20px;
}
/* Level 3 */
-moz-any(section, article, aside, nav)
-moz-any(section, article, aside, nav)
-moz-any(section, article, aside, nav) h1 {
  font-size: 15px;
}

27 comments

Comments are now closed.

  1. Warren Parsons wrote on May 18th, 2010 at 10:07:

    Wonderful idea! I really hope this takes off and other browser vendors pick it up down the road.

    IE? Maybe in version 13… Maybe.

  2. JD wrote on May 18th, 2010 at 10:51:

    I think there should be a feature to define a set of colors like:

    DEFINE(primaryColor:#CC3333);
    DEFINE(secondaryColor:#333333);

    .class{color:primaryColor;background:secondaryColor;}

    1. Magne Andersson wrote on May 18th, 2010 at 14:35:

      That’s been brought up many times before, under the name “CSS Variables”. It was decided, though, that this should not be part of the CSS standard, at least not CSS3 and below.

      (Presumably it’s because CSS is supposed to be a very easy and simple language, which is good, but still limits you in some areas.)

  3. Magne Andersson wrote on May 18th, 2010 at 12:38:

    It’s great indeed, and probably speeds up rendering a bit, but the one I have the highest expectations for is the -moz-cycle()/cycle() expression (https://bugzilla.mozilla.org/show_bug.cgi?id=363250) ;-)

  4. Andy L wrote on May 18th, 2010 at 14:29:

    Thank you for moz-any(), Mozilla!

    I hope Google Chrome / WebKit will implement it soon as well so I can use it in my webapp. (For IE I’ll be using Chrome Frame.)

    Magne Andersson:
    cycle() will be useful indeed! +1.

  5. Barryvan wrote on May 18th, 2010 at 17:01:

    I agree with Warren — it’d be great to see this functionality spread to the other browsers as well. What I particularly appreciate about it is that it makes writing CSS simpler — most of CSS3 is about making your page look prettier with less markup and better semantics, but little attention has been paid to making the CSS itself simpler, clearer, and more elegant.

    Nice work.

  6. semper wrote on May 19th, 2010 at 03:02:

    Thanks, great work (as always), but there’s one point…

    > First, it’s just a proposal, and hasn’t made its way into any specification.
    > And second, it isn’t quite ready for prime-time, though, since it doesn’t yet
    > handle specificity correctly.

    I wonder if these are real reasons for it to have a -moz- prefix? Compare

    /* Level 2 */
    section section h1, section article h1, section aside h1, section nav h1,
    article section h1, article article h1, article aside h1, article nav h1,
    aside section h1, aside article h1, aside aside h1, aside nav h1,
    nav section h1, nav article h1, nav aside h1, nav nav h1, {
    font-size: 20px;
    }

    with

    /* Level 2 */
    -moz-any(section, article, aside, nav)
    -moz-any(section, article, aside, nav) h1,
    -webkit-any(section, article, aside, nav)
    -webkit-any(section, article, aside, nav) h1,
    -o-any(section, article, aside, nav)
    -o-any(section, article, aside, nav) h1 {
    font-size: 20px;
    }

    Yes, second is still shorter, but you know what I mean. I agree the prefix is useful for something like gradients, where different interpretations and different syntaxes are possible, but here — isn’t it redundant?

    1. voracity wrote on May 19th, 2010 at 04:52:

      It would be great if you do the equivalent of “:any” on vendor prefixes. For example:

      /* Level 2 */
      -[moz,webkit,o,none]-any(section, article, aside, nav)
      -[moz,webkit,o,none]-any(section, article, aside, nav) h1 {
      font-size: 20px;
      }

      This would make life so much easier for a whole heap of things…

      1. voracity wrote on May 19th, 2010 at 04:56:

        Actually, extending this idea slightly:

        .box {
        border-[left,top]: white 1px solid;
        border-[right,bottom]: black 1px solid;
        }

        1. CyberSkull wrote on July 7th, 2010 at 22:11:

          I like your idea! That would simplify so many definitions! :D

    2. Magne Andersson wrote on May 19th, 2010 at 08:23:

      The prefix is required until a spec has reached Candidate Recommendation status, per CSS WG. We must have it on affected properties.

      1. zoe somebody wrote on August 28th, 2011 at 22:43:

        While working on implementing a new HTML5 default markup scheme I discovered the Firefox UA stylesheet is already actually using the any() selector to adjust the size of h1 tags nested in html5 sectioning container as posited in the article above (from html.css):


        h3, *:-moz-any(article, aside, nav, section) *:-moz-any(article, aside, nav, section) h1 {
        display: block;
        font-size: 1.17em;
        font-weight: bold;
        margin: 1em 0;
        }

        While testing my markup scheme before styling anything I discovered that the h1 tags were not all the same size in FF vs every other browser. Inded, the nested h1′s were being sized down to h3′s and h4′s.

        While I for one really appreciate the any() selector and would like to use it for this very reason, implementing this in the UA stylesheet is unfortunate because now it is yet another thing that needs normalized for between browsers.

        I would push for the any() selector to become a part of the spec, but I would NOT like any extra formatting applied by the browsers until that extra formatting is standardized.

        Just thought I would post this here since this was the first search that came up as I started figuring this out.

        1. Paul Rouget wrote on August 29th, 2011 at 02:24:

          This is not any extra formatting. This is part of the spec (nested headers are smaller). The fact we use :-moz-any doesn’t change anything. We could have used a more complex selector to achieve the same thing.

  7. semper wrote on May 19th, 2010 at 14:37:

    Is this a MUST in the sense of RFC 2119? Or what? I mean, what’s the real sense of it?
    For me, Web is so great because decisions here tend to be so much rational, not business-drived, or marketing-drived, or whatever-else-drived.
    The question of prefixes, btw, had been rised and actively discussed before (see http://www.quirksmode.org/blog/archives/2010/03/css_vendor_pref.html for example).

    1. Magne Andersson wrote on May 20th, 2010 at 00:59:

      It’s a CSS WG decision, so yes, it is a MUST.

  8. Giorgio wrote on May 19th, 2010 at 15:49:

    vendor prefixes are a good thing because not all the implementations shows the same result, especially on non-recommended features

    but if css provide a media query for browser sniffing

    @media user-agent matches(/blabla/) { }

    prefixes can be removed… i hate them, but now are the only solution

  9. Matzipan wrote on June 23rd, 2010 at 10:57:

    Why would you want to use this anyway? To me it’s a useless selector, why would you want to have combination lists? It’s the developer’s job to keep his css tidy, not the browser to add some more features and slow down.

  10. Pingback from -moz-any() 선택자(selector)를 이용한 그룹핑 ✩ Mozilla 웹 기술 블로그 on June 24th, 2010 at 08:30:

    [...] 원저자: Paul Rouget – 원문으로 가기 [...]

  11. ZhouQi wrote on July 8th, 2010 at 20:47:

    how about the performance?

  12. Steve wrote on December 23rd, 2010 at 09:23:

    I personally think that the any() selector would be great addition to CSS as long as it has no hits on page loading and rendering times. On the downside if it does get accepted I suppose it might get into IE15, maybe, and with bugs.
    Thanks for explaining so concisely.

  13. Pingback from Simplify Your CSS With the ‘any()’ Selector | t3knoDorKs on April 8th, 2011 at 01:20:

    [...] with category names is not ideal. To make life easier, and your CSS some-more readable, Mozilla proposed a -any() pseudo selector. Using -any() we could rewrite a formula above like [...]

  14. Anton Agestam wrote on April 11th, 2011 at 05:19:

    I’d like the syntax to be more intuitive, why not drop the entire key-word-stuff and put like this:

    (section|nav|aside) (section|nav|aside) h1{font-size:20px;}

  15. Lars Gunther wrote on June 29th, 2011 at 08:42:

    Isn’t the colons missing in front of -moz-any in the example code?

  16. Pingback from My CSS Wish List | Ascend Social Media Marketing on August 17th, 2011 at 22:45:

    [...] -moz-any() selector grouping has been introduced by Mozilla but it’s not part of any CSS specification (yet?); it’s [...]

  17. Poderwac wrote on October 3rd, 2011 at 06:21:

    thanks for these hacks, it’s exactly what I was looking for… I just hope that they are working with firefox 7 as well.

  18. Dave wrote on November 19th, 2011 at 09:57:

    That’s been brought up many times before, under the name “CSS Variables”. It was decided, though, that this should not be part of the CSS standard, at least not CSS3 and below.

    (Presumably it’s because CSS is supposed to be a very easy and simple language, which is good, but still limits you in some areas.)
    4G LTE Phones

  19. Pingback from Webstandards aktuell: CSS4 – Heute schon an morgen denken » t3n Magazin on February 13th, 2012 at 08:38:

    [...] des W3C[2] http://www.w3.org/TR/selectors4/Selectors Level 4, W3C Working Draft[3] http://hacks.mozilla.org/2010/05/moz-any-selector-grouping/Mozillas Vorschlag für den -moz-any()-Selektor[4] http://dev.w3.org/csswg/css4-text/Selectors [...]

Comments are closed for this article.