New CSS3 selectors and how to use them

CSS3 gives incredible power for selecting elements within a page. You may not think this sounds very glitzy but trust me, it will make your life easier and you'll love CSS3 for it! I'd better qualify that bold claim…

CSS3 attribute selectors

You've perhaps used existing CSS attribute selectors to target rules. For example, consider the following rule:

img[alt] {
  border: 3px dashed #e15f5f;
}

This would target any image tags in the markup which have an alt attribute:

<img class="oscarMain" src="img/oscar.png" alt="atwi_oscar" />

You can also narrow things down by specifying what the attribute value is. For example, consider the following rule:

img[alt="atwi_oscar"] {
  border: 3px dashed #e15f5f;
}

This would only target images which have an alt attribute of atwi_oscar. So far, so big deal we could do that in CSS2. What is CSS3 bringing to the party? Principally, three new "substring matching" attribute selectors…

CSS3 substring matching attribute selectors

CSS3 lets us select elements based upon the substring of their attribute selector. That sounds complicated. It isn't! We can now select an element, based on the contents of the attribute. The three options are whether the attribute is:

  • Beginning with the prefix
  • Contains an instance of
  • Ends with the suffix

Let's see what they look like.

The "beginning with" substring matching attribute selector

The "beginning with" substring matching attribute selector has the following syntax:

Element[attribute^="value"]

In practical use, if I want to select all images on the site that had an alt attribute that began with film, I would write the following rule:

img[alt^="film"] {
border: 3px dashed #e15f5f;
}

The key character in all this is the ^ symbol which means "begins with".

The "contains an instance of" substring matching attribute selector

The "contains an instance of" substring matching attribute selector has the following syntax:

Element[attribute*="value"]

In practical use, if I want to select all images on the site that had an alt attribute that contained film I would write the following rule:

img[alt*="film"] {
  border: 3px dashed #e15f5f;
}

The key character in all this is the * symbol which means "contains".

The "ends with" substring matching attribute selector

The " ends with " substring matching attribute selector has the following syntax:

Element[attribute$="value"]

In practical use, if I want to select all images on the site that had an alt attribute that ended with film I would write the following rule:

img[alt$="film"] {
  border: 3px dashed #e15f5f;
}

The key character in all this is the $ symbol which means "ends with".

A practical, real world example

How can these substring attribute selectors actually help? Let me give you an example where I often use CSS3 attribute selectors. If I build a website with a Content Management System (for example, Wordpress, Concrete, or Magento), it often gives the client the ability to add new pages. For example, perhaps they are adding a piece of news about their company or a product update. Each time they add a page in the CMS, the generated HTML will include an ID value for the <body> or other relevant tag, which helps distinguish the page, markup wise, from others. For example, one client was involved in Motorsport and had a "Racing History" section with yearly reports. Each <body> tag would have an ID for the year:

<body id="2003">

Tip

IDs can start with numbers in HTML5

If you're not used to coding in HTML5, you might assume that an ID beginning with a number is invalid, as it was in HTML 4.01. However, HTML5 removes that restriction, the only things to remember with ID names in HTML5 is that there should be no spaces in the ID name and it must be unique on the page. For more information visit http://dev.w3.org/html5/spec/Overview.html#the-id-attribute.

I needed the navigation bar link for "Racing History" to be highlighted when any of these yearly pages were viewed, as they related to the "Racing History" section. However, rather than write a style rule covering every future year, I was able to write a defensive (they are sometimes referred to as "defensive" rules as they try and safeguard against future events) CSS3 rule:

body[id^="2"] .navHistory { color: #00b4ff; }

This means that any element with a class of .navHistory, that is a descendant of a body with an ID beginning with 2 (for example, 2002, 2003, 2004, and on) will be colored with the hex value of #00b4ff. One simple rule covers all eventualities. Unless of course the website is still in its current form by the year 3000—in which case, chances are, even if I eat and exercise well, I won't be able to continue its upkeep…

CSS3 structural pseudo-classes

The more often you code websites, the more often it's likely you'll need to solve the same problem again and again. Let's consider a typical example. Horizontal navigation bars are often made up of a number of equally spaced <li> links. Suppose we need margin to the left and right side of each list item, except for the first and last list item. Historically, we have been able to solve this problem by adding a semantically superfluous classname to the first and last <li> elements in the list, as shown in the highlighted lines in the following code snippet:

<ul>
  <li class="first"><a href="#">Why?</a></li>
  <li><a href="#">Synopsis</a></li>
  <li><a href="#">Stills/Photos</a></li>
  <li><a href="#">Videos/clips</a></li>
  <li><a href="#">Quotes</a></li>
  <li class="last"><a href="#">Quiz</a></li>
</ul>

And then by adding a couple of rules in the CSS, we can amend the margin for those two list items:

li {
  margin-left: 5%;
  margin-right: 5%;
}
.first {
  margin-left: 0px;
}
.last {
  margin-right: 0px;
}

This works but isn't flexible. For example, when building a website built on a CMS system, list items for linking new content might be added automatically, so it might not be a simple task to add or remove the last or first class to the correct list item in the markup.

The :last-child selector

CSS2.1 already had a selector applicable for the first item in a list:

li:first-child

However, CSS3 adds a selector that can also match the last:

li:last-child

Using these selectors together, we don't need any additional classes in our markup.

We'll fix up our And the winner isn't... site navigation using this and a combination of the display: table property. The following screenshot shows how things look currently:

The :last-child selector

Now, let's take a look at the graphic mockup:

The :last-child selector

The navigation bar links span the full width of the design, which we need to replicate. Our markup for the navigation looks like this:

<nav role="navigation">
  <ul>
    <li><a href="#">Why?</a></li>
    <li><a href="#">Synopsis</a></li>
    <li><a href="#">Stills/Photos</a></li>
    <li><a href="#">Videos/clips</a></li>
    <li><a href="#">Quotes</a></li>
    <li><a href="#">Quiz</a></li>
  </ul>
</nav>

First, we'll set the nav element to be a table:

nav { 
  display: table; 
  /* more code... */ 
}

Then the <ul> to be displayed as a table-row:

nav ul {
  display: table-row;
  /* more code... */
}

And finally the list-items to display as table-cells:

nav ul li { 
  display: table-cell;
  /* more code... */
}

This means that if extra list items are added, they will automatically space themselves accordingly. Finally, we'll use our CSS selectors to align the text to the right and left of the first and last list items:

nav ul li:last-child {
  text-align: right;
}

nav ul li:first-child {
  text-align: left;
}

Then in the browser, our navigation is approaching our original composite:

The :last-child selector

Tip

Don't worry; these tables are only for display!

You may be wondering what on earth I'm thinking of, to suggest that we use a table for the navigational layout. However, don't forget, these tables are only presentational. That means they exist only in the CSS and are nothing to do with the markup. We are merely telling the browser we want those elements to appear and behave as if they were a table, not actually be a table. Displaying the markup in this manner also doesn't preclude us from using a different layout type for a different viewport, for example, display: inline-block for viewports below 768 px.

The nth-child selectors

But what about those alternate colors shown in the navigation bar links of the original composite? Again, CSS3 has a selector that can solve this problem for us without the need for additional markup:

:nth-child(even)

Let's use this selector to fix the problem and then we can look at some of the many ways that nth-child can solve problems that previously required extra markup. I'll add alternate red links in the navigation bar by adding the following style rule:

nav ul li:nth-child(even) a {
  color: #fe0208;
}

And now we have alternate colors in the navigation links:

The nth-child selectors

How about that? Not a line of jQuery in site and no extra markup! What did I tell you? CSS3 selectors are great!

Understanding what nth rules do

Amongst frontend web developers and designers, nothing makes mathematics weaklings tremble quite like the nth-based rules (well, you know, except maybe someone asking you to code a little PHP or give them a hand with some REGEX expressions). Let's see if we can make sense of the beast and gain a little respect from those backend wizards.

When it comes to selecting elements in the tree structure of the DOM (Document Object Model or more simplistically, the elements in a page's markup) CSS3 gives us incredible flexibility with a few nth-based rules—:nth-child(n), :nth-last-child(n), :nth-of-type(n), and :nth-last-of-type(n). We've seen that we can use (odd) or (even) values (as we have to fix our navigation above) but the (n) parameter can be used in another couple of ways:

  • Used as an integer; for example, :nth-child(2)—would select the second item
  • Used as a numeric expression; for example, :nth-child(3n+1)—would start at 1 and then select every third element

The integer based property is easy enough to understand, just enter the element number you want to select. The numeric expression version of the selector is the part that can be a little baffling for mere mortals. Let's break it down. For practicality, within the brackets, I start from the right. So, for example, if I want to figure out what (2n+3) will select, I start at the right (from the third item) and know it will select every second element from that point on. I've amended our navigation rule to illustrate this:

nav ul li:nth-child(2n+3) a {
  color: #fe0208;
}

As you can see, the third list item is colored and then every subsequent second one after that (if there were 100 list items, it would continue selecting every second list item):

Understanding what nth rules do

How about selecting everything from the second item onwards? Well, although you could write :nth-child(1n+2), you don't actually need the first number 1 as unless otherwise stated, n is equal to 1. We can therefore just write :nth-child(n+2). Likewise, if we wanted to select every third element, rather than write :nth-child(3n+3), we can just write :nth-child(3n) as every third item would begin at the third item anyway, without needing to explicitly state it.

The expression can also use negative numbers for example, :nth-child(3n-2) starts at minus 2 and then selects every third item. Here's our navigation amended with the following rule:

nav ul li:nth-child(3n-2) a {
  color: #fe0208;
}

And here's what it gives us in the browser:

Understanding what nth rules do

Hopefully, that's making perfect sense now?

The child and last-child differ in that the last-child variant works from the opposite end of the document tree. For example, :nth-last-child(-n+3) starts at 3 from the end and then selects all the items after it. Here's what that rule gives us in the browser:

Understanding what nth rules do

Finally, let's consider :nth-last-of-type. Whilst the previous examples count any children regardless of type, :nth-last-of-type let's you be specific about the type of item you want to select. Consider the following markup:

<ul>
  <li class="internal"><a href="#">Why?</a></li>
  <li><a href="#">Synopsis</a></li>
  <li class="internal"><a href="#">Stills/Photos</a></li>
  <li class="internal"><a href="#">Videos/clips</a></li>
  <li class="internal"><a href="#">Quotes</a></li>
  <li class="internal"><a href="#">Quiz</a></li>
</ul>

Note that the second list item doesn't have the internal class added to it.

Consider the following rule:

nav ul li.internal:nth-of-type(n+2) a {
  color: #fe0208;
}

You can see that we are telling the CSS, "From the second matching item, target every <li> item with a class called internal. And here's what we see in the browser:

Understanding what nth rules do

Tip

CSS3 doesn't count like jQuery!

If you're used to using jQuery you'll know that it counts from 0 upwards. For example, if selecting an element in jQuery, an integer value of 1 would actually be the second element. CSS3 however, starts at 1 so that a value of 1 is the first item it matches.

The negation (:not) selector

Another handy selector is the negation pseudo-class selector. This is used to select everything that isn't something else. For example, keeping the same markup as the previous example, if we change our rule as follows:

nav ul li:not(.internal) a {
  color: #fe0208;
}

You can see that we are opting to select every list item that doesn't have the internal class . So in the browser, we see this:

The negation (:not) selector

So far we have looked primarily at what's known as structural pseudo-classes (full information on this is available at http://www.w3.org/TR/selectors/#structural-pseudos). However, CSS3 has many more selectors. If you're working on a web application, it's worth looking at the full list of UI element states pseudo-classes (http://www.w3.org/TR/selectors/#UIstates), as they can; for example, help you target rules based on whether something is selected or not.

Amendments to pseudo-elements

Pseudo-elements have been around since CSS2 but the CSS3 specification revises the syntax of their use very slightly. To refresh your memory, until now, p:first-line would target the first line in a <p> tag. Or p:first-letter would target the first letter. Well, CSS3 asks us to separate these pseudo-elements with a double colon to differentiate them from pseudo-classes. Therefore, we should write p::first-letter instead. Note that however Internet Explorer 8 and lower versions don't understand the double colon syntax; they understand only the single colon syntax.

Is :first-line handy for responsive designs?

One thing that you may find particularly handy about the :first-line pseudo-element is that it is specific to the viewport. For example, if we write the following rule:

p::first-line {
  color: #ff0cff;
}

As you might expect, the first line is rendered in an awful shade of pink (I was thinking of Moulin Rouge at the time):

Is :first-line handy for responsive designs?

However, on a different viewport, it renders a different selection of text:

Is :first-line handy for responsive designs?

So, without needing to alter the markup, with a responsive design, there's a handy way of having the first visual (as the browser renders it, not as it appears in the markup) line of text appear differently than the others.

Hopefully this brief foray into CSS3 selectors illustrates how they help keep a responsive design and code base free of additional markup. It the past, I've needed to use a JavaScript library such as jQuery to make complicated selections but CSS3 often negates that need. It's also comforting to know that the CSS3 selectors module is already at the W3C Recommendation status; so it's a very mature module that's unlikely to change much from here on.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.59.145