Targeting Specific Elements Without Using IDs or Classes CSS3

Just like attribute selectors, pseudo-classes and pseudo-elements can be used to select specific elements in the HTML without assigning those elements IDs or classes, keeping your markup cleaner. Pseudoclasses and pseudo-elements target pieces of HTML that either don’t exist as standalone elements, or do exist but have a unique characteristic that you can’t target with the other simple selectors. For instance, you can use the :first-line pseudo-element to format the first line of a paragraph, even though that first line doesn’t have HTML tags wrapped around it. In this way, some pseudo-classes and pseudoelements are even more powerful than attribute selectors, because they allow you to target elements that could never have an ID or class added to them to begin with.

Pseudo-classes and pseudo-elements as a whole are not new, or particular, to CSS3, but CSS3 added several individual pseudo-classes that allow us even more precise control over what parts of the document we want to target. Many of these new selectors are structural pseudo-classes.

New Structural Pseudo-classes
CSS3 introduces the concept of “structural pseudo-classes” to target elements in the document tree based on unique characteristics of the elements, such as relative placement. For instance, the :first-child pseudo-class targets an element that is the first child element of its parent element. This child element is a standalone HTML element in the document tree, but what makes it unique is that it’s first, and it’s this unique characteristic that we want to be able to select by, without having to add a class or ID.

All of the structural pseudo-classes are based on the document tree, also called the document object model (DOM), so let’s have a quick refresher on what that is. The document tree is the hierarchical structure of the HTML page, made up of elements, attributes, and text, each called a node. It contains multiple levels because elements are nested inside each other (Figure below). Elements nested directly inside other elements are called children of those outer elements; they’re also descendants, along with elements that are nested further down. The outer elements are called parents (if one level up) or ancestors (if two or more levels up). Elements that are nested at the same level with each other—in other words, they have the same parent—are called, predictably, siblings. An element can be many or all of these things at once, just like you can be someone’s child and someone else’s parent at the same time; the terms are all relative to where a certain element is in relation to a certain other element.

A sample document tree, showing ancestor, descendant, parent, child, and sibling elements

A sample document tree, showing ancestor, descendant, parent, child, and sibling elements

Now that we’ve gotten all that terminology down, we can see all the ways we can establish relationships among the elements. Table below shows the structural pseudo-classes.

Structural pseudo-classes

Structural pseudo-classes

Other than the :first-child pseudo-class, which is part of CSS , all of these structural pseudo-classes are new to CSS3. They offer us a whole host of new ways to target elements very precisely.

Back to the Speech Bubbles: Alternating Colors
We can use the :nth-child() pseudo-class to make every other speech bubble in our comments page have a different background color. And we’ll do this without using classes or JavaScript.

HOW :nth-child() WORKS
One of the most powerful and useful structural pseudo-classes is :nth-child(). I already mentioned that it selects an element based on its position within the list of its parent’s children; in other words, it selects an element based on how many siblings it has before it.

You write the position number of the element you want to select inside the parentheses of the selector, such as li:nth-child(5). This selector would match the fifth li element in a list. In addition to numbers inside the parentheses (the selector’s argument), you can also use the keyword odd or even to select every other element in a row, such as the second, fourth, sixth, and so forth. But where :nth-child() gets really powerful is when you use a formula as its argument, allowing you to create more complex alternating patterns or even select specific blocks of sequential children at a time. The formula has the syntax an+b, where a is a cycle size that you pick, n is a counter starting at zero, and b is an offset value that you pick. Here’s an example:

li:nth-child(3n+1)

Since n starts at zero and then increases by one each cycle, this selector would match:

And so on!

While you could certainly add classes to the first, fourth, seventh, and tenth list items, it’s time-consuming to do so, easy to forget to do, adds to the weight of your pages, and—probably most importantly— is a pain to maintain. If you ever want to add another list item in between existing ones, you have to re-class all the list items from that point forward, as their position numbers will have all changed.

Using the :nth-child() pseudo-class that keeps track of the position numbers for you and matches accordingly is far more efficient and mistake-proof.

Don’t let the math scare you off from using :nth-child(). There are some great online tools that can help you get a better sense for how :nth-child() works by letting you play around with values to see how they affect the styles of the page immediately. My favorite of these tools is at http://leaverou.me/demos/nth.html, by Lea Verou, which allows you to test not only :nth-child() but also :nth-last-child(), :nth-of-type(), and :nth-last-of-type().

ZEBRA STRIPING
One of the most ubiquitous uses of :nth-child() is to make every other row of a table a different color. This is commonly called “zebra striping.” It can often be more than just an aesthetic enhancement; it can increase usability by making it easier to scan across a long table without losing your place.

Without :nth-child(), you zebra stripe a table by applying a class to every other row, called something like “even” or “alt”, and then give this class a different background color. You have to either apply these classes manually or have a piece of JavaScript do it for you. Neither solution is as efficient as :nth-child().

You can use :nth-child() formulas to zebra stripe; the formula 2n would match all the even rows, for instance. But the keywords even and odd are shortcuts that are easier to use. We’ll use the even keyword in our blog comments page to make every other speech bubble a different color. To get started, download the exercise files for this chapter at www. stunningcss3.com and open alternate_start.html in your code editor of choice. Its CSS is contained in a style element in the head of the page. This is the same page used in Chapter 2, so you can also use your final page from Chapter 2 as your starting point here.

Right now, all the speech bubbles in this page are the same shade of greenish-blue . This color has the value hsla(182,44%,76%,.5). Since we’re using HSLA, it’s easy to tweak the values to get a slightly different shade for our alternating color. Remember that hue values run from 0 to 360, along the spectrum from red to purple. So if you wanted to make the alternating color a little more green, you simply use a slightly lower hue value, such as 160 instead of 182. If you wanted to make the alternating color a little more blue, use a higher hue value, such as 200.

All of the comments have the same greenish-blue background color.

All of the comments have the same greenish-blue background color.

Let’s use a bluer shade for our alternating color. I’ll use 210 for the hue value to make the color difference more obvious. Add this new rule to the CSS in the head of the page:

Save the page, and view it in an up-to-date browser. You’ll see that the second and fourth comments are blue, while the first and third are still greenish-blue .

The evennumbered speech bubbles now have a muted blue background color.

The evennumbered speech bubbles now have a muted blue background color.

This new shade of blue doesn’t look as good at the same muted saturation level that the greenish-blue shade uses, so let’s bump up the saturation value to brighten it, and also increase the lightness value a bit to improve the contrast with the black text:

Now the alternate color is a brighter shade of blue . HSLA made it easy to pick a complementary color, and :nth-child() made it easy to apply that color to every other speech bubble. While alternating the color of blog comments like this doesn’t really have a usability benefit, as zebra striping table rows often does, you can see how efficient it is to use :nth-child() for selecting elements in a pattern.

nth-child() browser support

nth-child() browser support

Quickly tweaking the HSLA values results in a brighter shade of blue on the even-numbered speech bubbles.

Quickly tweaking the HSLA values results in a brighter shade of blue on the even-numbered speech bubbles.

WORKAROUNDS FOR IE
IE 8 and earlier do not support :nth-child(); IE 9 does. In this case, the alternating colors are a minor visual enhancement that users of IE 8 and earlier can do without. IE simply ignores the new rule and keeps all the speech bubbles the same color as before. Nothing looks broken, incomplete, or ugly.

If you do want to provide a workaround for IE 8 and earlier, however, you’ll need to use JavaScript. If you’re zebra striping, there are a myriad of scripts that will add the alternating classes for you. The one that will be best for you will depend on your project, so Google “zebra stripe JavaScript” or “zebra stripe PHP” or whatever suits your needs.

Alternately, you can use a script that adds support for advanced selectors to IE, and then simply use those selectors to accomplish whatever effect you want, including but not limited to zebra striping. One such script is Dean Edwards’ IE7.js that we used, but you have to upgrade to the IE9.js version of the script in order to get pseudo-classes to work; the IE7.js version only makes attribute selectors and a few other selectors work. Another great script that adds pseudo-class support is Selectivizr, but as mentioned in Chapter 4 it also requires the use of one of several separate JavaScript libraries like jQuery, MooTools, or DOMAssistant in order to work. Both of these scripts make IE identify the selectors present in your CSS and render whatever styles they define.

Also many JavaScript libraries have advanced selectors like :nth-child() built in, which you can write into your own scripts to get :nth-child() functionality in IE. This route wouldn’t take into account the :nth-child() selectors already present in your CSS; you’d have to recreate them in your script.

Back to the Photos: Random Rotation
Right now, all the photos are rotated in order to make them appear more realistic. But since they’re all rotated the same amount, they look very uniform . It would be nice to be able to use :nth-child() to rotate different photos different amounts to enhance the appearance of randomness and realism.

All the photos are rotated slightly to the right.

All the photos are rotated slightly to the right.All the photos are rotated slightly to the right.

However, if you used the selector img[src*=photos]:nth-child(even) to rotate all the even-numbered images to the left instead of the right, you might be surprised to find that the last two images both rotate right, instead of alternating. This is because the :nth-child() pseudo-class selects all children of the same parent. The img elements are siblings with all the p and h2 elements, so all of these elements are counted for :nth-child(). Even though img is included in the selector, all that the selector is saying is “Find all the images that have ‘photos’ in their src attribute. Then apply these styles to the ones that are even-numbered children.” If you count all the img, p, and h2 elements in the parent div, you’ll find that the second-to-last photo is child number 29 of the div, and the last photo is child number 37. Thus, the :nth-child() rule selecting even-numbered children doesn’t apply to either of them, and they stay rotated to the right.

What we really need is a selector like :nth-child() but that counts only elements of a particular type. Lucky for us, CSS3 provides such a selector:

the :nth-of-type() pseudo-class. It works exactly the same as :nthchild(), but it counts only whatever element you specify in front of it.

Let’s put it to use in our page. Open rotate_start.html from the exercise files for this chapter. Add the following new rule to the styles in the head of the page:

Save your page, and view it in a browser to see that every other photo is now rotated to the left instead of the right . The last two images aren’t angled the same way; they alternate rotation.

The photos now alternate between left and right rotation, to look more realistic.

The photos now alternate between left and right rotation, to look more realistic

You might notice in Figure below that the first, third, and fifth photos are rotated to the left, even though the selector says to rotate evennumbered ones to the left. That’s because there’s another img element before all the photos on the page: the map thumbnail. This img element makes the first, third, and fifth photos the second, fourth, and sixth images overall. The :nth-of-type() pseudo-class only cares about the element type when doing its counting—in this case, that element type is img. What the full selector is saying is “Find all the images
that have ‘photos’ in their src attribute. Then apply these styles to those that are even-numbered img element children.”

nth-of-type() browser support

nth-of-type() browser support

There’s no way in CSS3 to make the browser count only img elements that have particular attributes. Any other img elements mixed in with the photos are going to be used for counting and calculating the child number. In the case of our page, we’re just trying to make the photos look random, so having other images interrupt our pattern isn’t a bad thing. The :nth-of-type() pseudo-class works for our purposes, even if it can’t select exactly what we might like.

In fact, let’s make the photos look even more random by adding another :nth-of-type() rule:

This makes every third image angled to the right by one degree. The photos have a fairly random-looking pattern of rotation now: the first is rotated negative -2deg, the second 1deg, the third negative -2deg, the fourth 2deg, and the fifth 1deg.

The rotation is now more varied, to look more random and realistic.

The rotation is now more varied, to look more random and realistic.

Even though the :nth-of-type() selector may not do exactly what you expect and want, it still provides a heap of control over what elements you want to target without having to resort to classes or IDs.

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

CSS3 Topics