Advanced CSS Selectors

Development

It’s my firm belief that between CSS and jQuery, there’s nothing on a page that I can’t manipulate.  CSS is amazing in that (as long as the proper hooks are in place) you can use it to manipulate elements with granular precision.  What most people don’t realize, however, is that you can use so much more than IDs or classes to select the various page elements.  Learning how to do this effectively means that you open your designs up to a lot more flexibility (and some really cool effects too)!

Here are some of the more advanced ways to select elements in CSS (along with a few of my favorite tips and tricks!).

The Basic CSS Selectors: IDs and Classes

I do want to start from the beginning because I see a lot of new developers misusing these.  To break it down to its simplest form:

  • A class is an element that you will reuse, or one that is part of a looped statement.
  • An ID is unique and special – there’s only one of them on the page. Period.

So, an example:

<div id="content">
    <article class="post">
        ...
    </article>
    <article class="post">
        ....
    </article>
</div>

What we have here is a typical content layout.  There’s only one “content” area.  That means it’s selected with an ID.  There are, however, multiple articles inside of that content area.  Those are marked by classes.  If you want to change the look of every article, it’s easy to do so by calling the article class inside of CSS.

JSFiddle Example: http://jsfiddle.net/studionashvegas/vYr7R/1/

Advanced Element Selectors

Now that the basics are established, let’s move onto some of the more advanced ones.

Element > Element

You can use the > symbol to specify the exact nested relationship of elements.  In the above example, you could target ONLY articles in the region by using:

#content > .article{
   ...
}

This would allow articles OUTSIDE of that content area to remain unformatted – very useful if you have multiple sections with separate formatting.

JSFiddle Example: http://jsfiddle.net/studionashvegas/49Qwx/

Element + Element

This allows elements that are sequentially positioned to be targeted, allowing you to specify different styles for elements adjacent.  For example: you want to give the <p> tags that are immediately following <H2> tags a special font size (as a leader paragraph).  The code…

h2 + p{
   ...
}

…would allow that to happen.  Any <p> tag immediately following a <h2> tag gets the benefit.

JSFiddle Example: http://jsfiddle.net/studionashvegas/gJ9HX/

Attribute-Based CSS Selectors

I love attribute-based  CSS selectors because they let you become extremely granular, but give you the flexibility of having just the code you need to get the job done.  Attributes, for the unaware, are things that are not css based: ‘src’, ‘href’, ‘title’, and ‘target’ are the more well known CSS selectors.  And, we can use those as hooks for CSS code.

[attribute=”value”]

A selector that allows you to select any tag that has exactly the determined value.  Did you know that you can signify if a link has a “blank” target (or opens in a new window)?

a[target="_blank"]{ border: 2px dashed red; }

A red 2px dashed border gets applied to any links that do not open in the same tab.  Pretty handy if you’re trying to make sure your outbound links are all opening off-tab!

JSFiddle Example: http://jsfiddle.net/studionashvegas/J3Gzn/

[attribute*=”value”]

Does a boolean search inside of the attribute.  If the word is found, even in the middle of other words, the style is applied.

a[title*="cap"]{ border: 2px dashed red; }

The above would work on titles such as “cap”, “captain”, “marketcap”, “encapsule”, and various other words that contain the letters c-a-p.

JSFiddle Example: http://jsfiddle.net/studionashvegas/HagT8/

[attribute~=”value”]

If this phrase is found (whole word, separated by spaces), the style is applied.

a[title~="cap"]{ border: 2px dashed red; }

The above code would work if the title was “my blue cap”, since cap is the requested selector.  It would not work, however, if it was “my-blue-cap”, since it would consider that phrase an entire word.

JSFiddle Example: http://jsfiddle.net/studionashvegas/m9Txj/1/

[attribute^=”value”]

The attribute’s first characters are the value.  This allows you to select any phrase that starts with that value.  My favorite use of this is to change hyperlinks based on their top-level domain.

a[href^="https://mitchcanter.me"]{
  background: url(../img/nashvegas.png) no-repeat left center;
  padding-left: 26px;
}

a[href^="http://www.binarychurch.com"]{
  background: url(../img/binary.png) no-repeat left center;
  padding-left: 26px;
}

a.rsswidget[href^="https://mitchcanter.me/blog"],
a.rsswidget[href^="https://www.mitchcanter.me/blog"]{
  background: url(../img/mitchblog.png) no-repeat left center;
  padding-left: 26px;
}

The above sets a special icon background based on the TLD of the domain.

I built a really nifty RSS feed that combines all of the blogs I do online into one.  This allows me to specify the icon based on which site it links out too (I also use jQuery to automatically target these links to a new window, which makes it a basic lifestream of the blogging I do).

JSFiddle Example: http://jsfiddle.net/studionashvegas/tB5rz/

[attribute$=”value”]

Same as above, but this lets you specify how the attribute ends.  The best use for this: links to files of a certain extension get special icons.

a[href$=".pdf"]{
  background: url(../img/pdf.png) no-repeat left center;
  padding-left: 26px;
}

Now, any PDF links you include automatically get a PDF icon to signify to users that’s what they’re clicking on.

JSFiddle Example: http://jsfiddle.net/studionashvegas/Uw3qZ/1/

Pseudo Selectors

These CSS selectors are special, as they are dependent on positioning, number, and order.  If the order changes, so does the element that is modified.

element:hover

This one is the most popular.  If you hover over the element, the style is applied.

JSFiddle Example: http://jsfiddle.net/studionashvegas/LcxA7/

:before, :after

This one, not so much known.  Did you know that you can insert content using CSS?

a.read-more-link:before{
content:"Read this: ";
}

Any link with the class of “read-more-link” now has the words “Read This: ” put before it.

div.last:after{
content:" ";
display: block;
clear: both;
}

This puts a “clearing div” after the last column (useful for clearing out any weirdness that occurs due to the nature of CSS floats).  This allows you to keep the HTML extremely clean on the template side.

JSFiddle Example: http://jsfiddle.net/studionashvegas/9gvFu/1/

:not

Every element BUT the one in question.

p:not(.special){
...
}

This selects all paragraphs except the one with the class of “special”.

JSFiddle Example: http://jsfiddle.net/studionashvegas/ZLZCD/

:nth-child(x)

Ah, algebra.  The last selector we cover today is one that’s extremely reliant on math skills.  This selector allows you to select any element that matches the formula you insert.

Odd/Event

p:nth-child(odd){ color: red; }
p:nth-child(even){ color: blue; }

This code makes all odd paragraphs (1,3,5,7) red, and the even ones (2,4,6,8) blue.

JSFiddle Example: http://jsfiddle.net/studionashvegas/Gprju/1/

an + b

You can select any numbers based on the formula you input.

Some examples:

  • (3n+0): every third element (3,6,9)
  • (2n+3): every second element, offset by 3 (5,7,9)
  • (4n-1): every fourth element, offset negatively by 1 (3,7,11)

JSFiddle Example: http://jsfiddle.net/studionashvegas/58yLX/1/

Final Notes

You can hook CSS selectors together (even the pseudo and attribute based ones) to gain even more flexibility.  For example:

 a[href^="mitchcanter.me"]:not(.orange){
    ...
}

…would allow you to select all links to this site (but not the ones with the “orange” class).

What’s your favorite selector?  And what’s the coolest thing you’ve gotten CSS selectors to do.  Tell me your story in the comments below!