CSS4 Preview – Selectors

By  on  

CSS is one probably the best bridge between web designers and developers so updates to the CSS spec are very exciting. The W3C recently posted an update to the working Selectors Level 4 spec, and there are many useful updates to be found. Let's have a look at what new CSS selectors and features will be available to us in future browsers!

$E > F

This exciting selector syntax allows for styling of a parent element ($E) based on its child element (F). One example would be:

/* style the LI element */
ul > $li > p { border: 1px solid #ccc; }

In the case above, the LI element is styled, not the P element! This is a much needed improvement to CSS and we will finally have it! This selector does leave room for confusion; consider the following:

$ol > li:only-child {
	list-style-type: none;
}

The example above styles an OL element with a unique LI child element. It will be interesting to see how often developers use the $ syntax; hugely useful but potential for misuse.

Location Pseudo-Classes - :any-link and :local-link

These pseudo-classes will be used for location-based elements. The :any-link pseudo-class is used for general links, while :local-link is used to identify links targeted within the same host (as opposed to external href's).

To add an icon to all internal links within your sidebar:

#sidebar a:local-link {
	background: url(internal.png) 0 0 no-repeat;
}

To add another icon to all external links:

:not(:local-link) {
	background: url(external.png) 0 0 no-repeat;
}

These pseudo-classes are welcomed additions, as link styling and communicating location is very important.

Linguistic Pseudo-Class - :dir

The :dir pseudo-class identifies left-to-right or right-to-left text displays:

p:dir(ltr) { /* left to right */
	
}

div:dir(rtl) { /* right to left */

}

Another welcomed addition, especially for those who code for multiple languages.

Reference Combinators

Reference combinators introduce slashes to the fun, mapping out association between compound selectors. Between the slashes are CSS qualified names. Here's an example:

label:matches(:hover, :focus) /for/ input {
	box-shadow: #fffea1 0 0 8px
}

The example above highlights an INPUT element when its LABEL is focused or hovered-over; the association is made by the for attribute of the label. As you can probably tell, the id is implied by the LABEL element's for attribute.

Good Enough?

I'm very encouraged by the new $ syntax and the new location :-link functionalities, and the language-based improvements will surely be helpful to some. I find the new reference combinator interesting, mostly because of the incorporation of the slash syntax. What do you think of these new features? What would you like to see added?

Recent Features

  • By
    CSS @supports

    Feature detection via JavaScript is a client side best practice and for all the right reasons, but unfortunately that same functionality hasn't been available within CSS.  What we end up doing is repeating the same properties multiple times with each browser prefix.  Yuck.  Another thing we...

  • By
    Page Visibility API

    One event that's always been lacking within the document is a signal for when the user is looking at a given tab, or another tab. When does the user switch off our site to look at something else? When do they come back?

Incredible Demos

  • By
    Create a Dynamic Flickr Image Search with the Dojo Toolkit

    The Dojo Toolkit is a treasure chest of great JavaScript classes.  You can find basic JavaScript functionality classes for AJAX, node manipulation, animations, and the like within Dojo.  You can find elegant, functional UI widgets like DropDown Menus, tabbed interfaces, and form element replacements within...

  • By
    MooTools Image Preloading with Progress Bar

    The idea of image preloading has been around since the dawn of the internet. When we didn't have all the fancy stuff we use now, we were forced to use ugly mouseover images to show dynamism. I don't think you were declared an official...

Discussion

  1. M.Amin

    that’s so cool ! wow.
    tnx david ,

  2. I have to say I don’t like the new reference combinator, but I don’t know that I could think of a better substitute. I like that they have an “nth-match”, which is repeated twice, which I’m guessing is a mistake, the second probably being “nth-last-match”. I also have to say that I initially thought the way they implemented parent selecting was stupid, but it’s beginning to grow on me, it could be an incredibly useful tool.

  3. I agree. I’m excited for the $ syntax. It seems that with the latest CSS4 spec that the bridge between CSS and JavaScript is closing. Not sure if that is a good thing though :-/

    • Brunoais

      No no no no no no no.
      What’s happening is a great thing!
      This great thing is that more and more javascript is is only meant to create dynamic pages and they are removing the presentational job from the javascript. Javascript is becoming careless about presentation and that is soo cool! We won’t have as much designers making trash out of javascript!

    • This syntax could get a little messy with SASS.

  4. The :lang() pseudo-class is actually part of Selectors level 3 so you can use it today.

    • My mistake Rouven — I’ll update my post shortly.

    • Thanks. BTW the same is true for :target() as well.

  5. I saw the spec last week but the W3C is a little hard to parse for casual reading. Thanks for posting this.
    What kind of timelines are there for CSS4?

  6. I’m dying for the ability to apply a style *every* nth child. In other words, something like li:every-nth-child(3) -or- support a modulus operator like li:nth-child(n%3). This would be super helpful for making grids.

    • What’s wrong with :nth-child()?

      From the selectors level 3 spec:

      tr:nth-child(2n+1) /* represents every odd row of an HTML table */
      tr:nth-child(odd) /* same */
      tr:nth-child(2n+0) /* represents every even row of an HTML table */
      tr:nth-child(even) /* same */

      /* Alternate paragraph colours in CSS */
      p:nth-child(4n+1) { color: navy; }
      p:nth-child(4n+2) { color: green; }
      p:nth-child(4n+3) { color: maroon; }
      p:nth-child(4n+4) { color: purple; }

  7. Emiel

    I always thought that “selection on child or following elements” was not supported in CSS3 due to the fact that this ‘limit’ allows for direct evaluation of the applicable css-rules when parsing a html/xml document (without looking ‘ahead’ to child elements, perhaps only to attribute nodes).

    If this is correct, CSS4 will definitely make stuff a little more complex for browser (engine) vendors.

  8. Still no variables :)

  9. rajkamal

    nice post. IE should implement that correctly, else, again one more compatibility issue for us. :-)

  10. Petah

    Now what browsers support these alrdy?

    • Except for :lang() and :target() (which are both CSS3 which is supported in all current browsers including IE9) AFAIK none of them are currently implemented in browsers. This is a very early draft.

  11. This is good… But I would really like to see LESS or SCSS like syntax to be incorporated into CSS itself….

  12. Man, I’ve needed most of these. Badly. Well, except for the :any-link. Got any good use cases for that?

    I feel like the reference combinator deals mostly with edge cases, but I know I’ve wanted to be able to do the exact example you showed! So maybe it’s not. :)

    — J

    • Eric

      :link was for links that were not visited, and :visited was for the opposite. Thus, instead of needing :link, :visited, :any-link would select both. Simply for ease of use.

      What’s confusing to me is that :any-link is listed as a CSS level 1 selector, when I’ve seen nothing of it until the level 4 draft came out. It seems logical that it would be a level 1 selector, alongside :visited and :link, but as far as I know it was introduced in 4. I’d only assume that they listed it as 1 for consistency.

  13. Personally, I still much prefer MooTool’s (or rather, Slick’s) reversed combinators. Where (using this syntax), I would write $.parent > .item:hover, reversed combinators would let me write .item:hover !> .parent.

    There are two big wins with this approach, to my mind:
    1. You preserve the natural reading order of CSS selectors — that is, the element to which the rules are applied is always determined by the right-most part of the selector.
    2. You gain a lot more power, by applying the ability to reverse any combinator: !~, !+, !, !>, etc.

    I’m not sure if any other selector engines implement a similar feature. If they do, then their syntax should definitely be considered before standardising on a new, unfamiliar syntax.

    Anyway, that’s just my opinion. However this is implemented, it’ll be a boon for styling!

    • Barryvan … are you saying…MooTools FTW?

    • Pretty much… :D Although in discussion on the w3 style lists, I’m actually starting to lean towards a :has() syntax, as being a suitable (and sensible!) compromise between the $ syntax and reversed combinators.

    • Eric

      The only issue I can see with that is that you’re adding reverse selection ordering, which can get confusing to some users.
      $.parent > .item:hover would be a more logical solution, because you have a selector hierarchy, and a placeholder for the selected element in that hierarchy. Also, noting that :has was under consideration, that’s actually a fairly annoying one too, given that for larger selectors, you could have a very good amount of nested parentheses.
      div > ?ul > li > a > .class > [blah] > .class2
      Would become
      div > ul:has(li:has(a:has(.class:has([blah]:has(.class2)))))
      And what would you do with this:
      div > ul:has(li) > li > a:has(.class) > .class > blah:has(.class2)
      The current consideration for the spec seems to be the most widely accepted and logical solution.
      Just my two cents, though.

  14. MATH!

    We need math! 50% -5px
    It’s stupid having to do things like this in JS. It’s a style, not an interaction

    I think we need better ways to layout pages. Having users use absolute positioning or floats is crazy. Why cant I have 2 columns that sit side by side and properly taken into consideration when calculating element height?

    Inline-blocks get us close, but we could do much better.

    • For math Internet Explorer 9 and Firefox 4 support calc(), so far vendor prefixed. (http://www.w3.org/TR/css3-values/#calc) I’m sure Webkit and Opera will follow soon.

      For two columns of the same height CSS2 tables are often a solution and are supported everywhere including Internet Explorer 7.

    • agreed on all points!

  15. Andrew Roberts

    Looks confusing enough to me! :P

  16. I’d like to see things like variables introduced personally. Maybe even introduce some of the maths based color and opacity changes that LESS et al allow.

  17. Eric

    The latest editor’s draft is showing that $element has been changed to ?element for subject selectors.

  18. Eric

    Also, it looks like :any-link will have a different name sometime soon.

  19. I like how it is getting easier to select some classes/children which we couldn’t do earlier but i also dislike that it is getting harder to read, like a javascript. Not a big issue for me, but i will have to see how clients will react.

    By the way, i have noticed that there is a new effect “background-image: cross-fade” in CSS4, i wonder if there are some more that are announced already?

  20. MAYBE

    whoa whoa, whoa.

    we haven’t even adopted all of the specs for CSS3 in all browsers, and we’re already talking about CSS4? let’s see to it that we can properly transform and transition things in EVERY browser before we add some more fancy, albeit cool, selectors.

    • I don’t think that’s a good idea to wait the full support of CSS3 specs for all browsers before starting anything new!
      It could takes some time : p

  21. Why not use a reverse syntax for parent selection? Like this:

    ol < li {}

    That way it would correspond with the direct child selection. We would lose the “any descendant” since this would demand that the parent is directly one level above the element to the right in the selector chain.

    But it would make the code pretty straight forward, I think.

    • I agree completely!

    • Or how about a combination of this with Barryvan’s comment earlier:

      li < ol { }

      This way you still get the implicit nature of the code saying “This child has this direct parent ” (whereas normally you would read the direct child selector as “This parent has this direct child”). Importantly as per Barry’s comment, this also keeps the element that actually has the style applied to it on the right of the selector as per everywhere else in CSS :-)

    • You wouldn’t have to completely lose the any descendant abilities, but you would lose the ability to not specify the exact family tree, eg:

      nav < ol < li { } could select the nav

      But I think the current implementation is actually better just because it is more flexible.

    • @John V

      Great suggestion. That would definitely make the code even more readable and straight forward.

      It might even be possible to do something like:

      span << ol {}

      to introduce an “any ancestor”-like functionality. A double less-then sign could have that meaning. A corresponding “any descendant” (>>) would preferably be introduced as well.

    • I like more the jQuery-way …

      li:has(ol) { }

  22. Thanks for this post!

    I’d really like to see a :text or :content selector, to grab just the inline stuff inside a block element.

  23. Mike

    This use of $ clashes with Sass variables.

    It would have been pretty easy to coordinate with the Sass folks so that those who want the features Sass provides and CSS has always failed to do could have them.

    Too bad they made this syntax choice for a much needed facility

  24. Hey David,

    Great post! I’d love to hear from you (or others…) when we can start using some of this stuff?

  25. Jake Archibald

    I think your external links selector should be :any-link:not(:local-link)

  26. Jan Hocevar

    This sounds great!

    When will use of this be possible?

  27. Jan Hocevar

    This sounds great! The local and external link are great stuff!

    When will we get to use it? :)

  28. Still no support for variables? LESS is better.

  29. Yes! It’s great, The external url is smart.

  30. ehhhh

    I have better idea, first we need 100% css3 compatible browsers – all of them, and then let’s think about css4… there is enough mess now. And this time listen to carefully to developers community.

  31. What would be the specificity level of the parent selector ($)?
    As you all know, now we have: inline, id, class, property, general selector. (in that order).
    This confuses me about how it would override existing rules….

  32. With css4 i’ll know your battery level!

  33. Targeting parent elements?! Wow!!! Great start!

  34. YES! Let’s make a jump forward!

    $vars could be a big help for non-programmers too…
    But it’s a MarkupLanguage and so I think it has to be a MarkupLanguage and not expanding to something between html and Javascript/PHP.

    $ makes not a programming language it just looks like one ;)

  35. Ian Sutherland

    It’s great to have new toys to play with, but.. And it’s a big but… We simply can’t use half the stuff because the age old x browser blah blah. Let’s please concentrate on getting everyone on the same page in css3 first. It’s more a case of having time to make everything work x browser when a project deadline is tight( and they generally are) than it not being doable. We seem to have moved on from CSS hack to vendor prefix, JavaScript polyfill,, and ‘use with caution’. In the front line trenches what we need is ‘use with confidence’.

    • Mike Francis

      Hit the nail on the head. It’s bad enough not being able to use CSS2 selectors in IE8. I totally agree, there are some amazing advancements being made but until the playing field is levelled, new tech is going to limited for bleeding edge work or demos.

  36. Sweet! I love the parent selectors. I would also like to see a selector for selecting the element selected by the anchor. For example, if you had a URL like this: http://www.myblog.com/post/1#comment-12345, then you could use the anchor selector to automatically select the comment with the id “comment-12345”.

  37. CZ

    Looking forward to being able to use these.

    BTW, to make a word like “element” plural you don’t add an apostrophe and an “s”, you just add an “s” to the end.

  38. LESS is better for now, no support for variables available yet :/

  39. With css4. I wanna complete learning my web designing. Hope this site will help me.

  40. Chuck

    I was expecting to read about nested rules, kind of like LESS, but native. Maybe in CSS5?

  41. Sorry, Eric
    I’m confused.
    CSS4?
    I thought this is the module 4 of the selectors, not the level 4 of Css:
    “Selectors Level 4”

    • Kseso?

      Sorry
      I wanted to say David.

  42. Brilliant! I’m so glad to finally see this idea being supported

  43. Fantastic! I have been hoping for a parent selector and ‘$’ seems like it will be very powerful.

  44. So is there someplace you know off hand that shows current browser support for the level 4 selectors?

  45. Matthew

    Great conversation going on here.

    I’m not as familiar with the new CSS as most of you, and perhaps this isn’t a good CSS idea, but here it goes…

    When using the same HTML for both a mobile device and a normal web page, sometimes we run into the difficulty of ordering (sorting) elements. For example, what if one had a logo that’s at the top of a page on the normal website, but wanted it to be after content, at the bottom of the page on the mobile version.

    What if there was some type of CSS child-index attribute which could move the logo element to position 2 rather than position 1 within its parent element, while moving the content from position 2 to position 1?

    Any elements having the same child-index would still appear with their sibling elements in the order they appear in the HTML, and items without a child-index may appear after all sibling elements with a defined child-index.

    This is a simple example, and may be possible with other methods of using today’s CSS, but it could get more advanced, such as repositioning the elements within a list to use a different order.

    This would be the same as changing the HTML layout, but using CSS instead of javascript.

    There are probably several drawbacks to this and pitfalls I’m not thinking of, but I thought I’d put the idea out there.

  46. WOW!! really cool information.

  47. Aut0 Mart1n

    Of course this is 2 years old – the standard has changed by a lot. Apparently W3C couldn’t make up their mind, since now they’ve decided to try using ! as the subject selector:
    table#main > tr! > td > .highlighted

    They’ve also included stuff on namespaces:

    @namespace ns url(http://www.w3.org/2000/svg)
    ns|g > circle

    or something like that…
    They’ve also got a bunch of other things, but just check out the link to see what’s being considered.

  48. To be clear, there is no such thing as CSS4. There are modules of CSS that are numbered as 4 (such as selectors), but anything after CSS3 is module based and each module will have a different version number than the next.

  49. the parent selektor is what i’m waiting so long for. But i think that $ Sign is a littlebit missleading – the long suggested E! > F would be the better code for that i guess. But anyway it will be nice to have it now in future.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!