left-icon

CSS3 Succinctly®
by Peter Shaw

Previous
Chapter

of
A
A
A

CHAPTER 3

New Selectors

New Selectors


In the previous chapter you saw a brief refresher of the most common types of selectors used in CSS. These three types are known as the class, ID, and descendant selectors, and were all that was available before version 3 of CSS. Now that CSS3 is here, it has brought many new selectors as part of its new functionality.

We won't be covering every new selector in this chapter, but you'll see rather quickly the sheer flexibility now available to target your HTML elements in ways you might never even have imagined.

Many of these new selectors are implemented as pseudo-selectors (selectors that act as an extension to another selector, such as hover), and you could easily write an entire book just on the subject of selectors alone.

In this chapter, we'll look only at the most important of the new selectors available, along with a basic demonstration of their uses. For the rest, I strongly advise you to read many of the excellent resources available on the internet. Aside from the other links I've already mentioned, a great place to start purely for CSS topics is the CSS pages on the Mozilla Developer Network. The handy thing about MDN is the compatibility guides, which will tell you at a glance which selectors work with which browsers, and which ones will give you problems.

The Universal Selector (*)

The target all selector does exactly what it says: it targets everything it can in the space in which it is operating.

That means if you have it inside an ID-based selector, then everything that falls under the control of that ID selector will be affected.

Using the * symbol tells you straight away that it behaves like a wild card, being as greedy as possible and selecting as much as possible. At first, this may seem like a great thing, until you suddenly realize just how much it slows your page down on a mobile device, or on a page with millions of nested elements.

The universal selector is designed primarily to make sweeping changes as part of an initial setup, such as setting a pages entire CSS model to a known set of defaults (like 0-pixel margins and no borders).

Typically it's used in CSS resets to start at a known state. Many of the well-known, front-end UI frameworks make extensive use of it to put your page into a known state before applying any custom styles they may provide.

The universal selector should be used sparingly, and its sphere of influence should be made as minimal as possible so as not to cause any drastic performance bottlenecks.

If you wanted to make sure that the margins and padding were set to 0 on every element in your document, then you might apply this selector as shown in Code Listing 13.

*

{

  margin: 0;

  padding: 0;

}

Code Listing 13: Using the universal selector

After including this somewhere near the top of your style file, you can be sure that immediately after it, none of your rules will have any margins or padding applied to them.

The Adjacent Sibling Selector (+)

One of the simpler selectors to understand, the adjacent selector selects elements that are immediately next to each other, and does so only once for each occurrence.

Imagine you have the following HTML markup:

<div>

    <h1>Heading</h1>

    <p>Text line 1</p>

    <p>Text line 2</p>

    <h1>Heading</h1>

    <p>Text line 1</p>

    <p>Text line 2</p>

</div>

Code Listing 14a: HTML markup to demonstrate the adjacent selector

If you then applied the following CSS rule to this markup:

h1 + p 

{

  color: red;

}

Code Listing 14b: CSS rule to demonstrate the adjacent selector

Only the p element immediately following the h1 element would be changed to a red color. The second line of text (and any others that might follow) will remain unchanged, as will the h1 elements themselves, as Figure 6 shows:

The expected result of Code Listing 14

  1. The expected result of Code Listing 14

One of the places that the adjacent sibling selector is most useful is in the creation of lead or opening paragraphs. Consider the following example.

<!doctype html>

<html>

<head>

    <title>Basic HTML 5 document</title>

    <link href="styles.css" rel="Stylesheet" type="text/css" />

</head>

<body>

    <section>

        <article>

            <h1>Monstrous Inbox</h1>

            <p>Today in local news, a monstrous email inbox was discovered belonging to Mr Jones of durham.</p>

            <p>The email inbox was ruomoured to have 11ty billion unread emails in it, but scientists say that calculating the actual amount is going to be almost impossible.</p>

            <p>Mr. Jones had no comment, but he did let slip that he had no idea how his inbox grew so large and so fast.</p>

        </article>

        <article>

            <h1>Jelly Table Legs</h1>

            <p>Furniture Watchdogs are today warning all people to be on the lookout for tables with Jelly legs.</p>

            <p>In recent months there have been a spate of fake tables released into the global furniture market, these fake tables are exceptionally dangerous and could wobble over at any moment.</p>

            <p>People should exercise extreme caution when buying new tables, if you’re unsure call a professional table tester to ensure you’re getting a genuine product.</p>

        </article>

    </section>

</body>

</html>

Code Listing 15: Fake news listing

The code in Listing 15 represents what could be a set of news articles. I've marked the code up so that it's using the new semantic tags in HTML 5 to help define document structure and layout. Please note that you don't need to type in all the text found inside the <p> elements; I've included a large amount just for demonstration purposes.

If you render the output as is without any styling, you'll get something that looks like the following:

Unstyled news article example produced by Code Listing 15

  1. Unstyled news article example produced by Code Listing 15

With the help of the adjacent sibling selector, and some help from the descendant selector, we can easily style this output using a very minimal set of style rules.

The following CSS code shows how we might use the adjacent sibling selector to ensure that our first paragraph stands out from the rest in each article.

section

{

      font-family: sans-serif;

      font-size: 12pt;

}

section h1

{

      color: green;

      border-bottom: 1px solid green;

      font-size: 15pt;

}

section p

{

      color: grey;

}

section h1 + p

{

      color: black;

      font-size: 14pt;

      font-style: italic;

}

Code Listing 16: CSS code to style the news articles in Code Listing 15

As you can see in Code Listing 16, the CSS used is very simple, and what's more, it’s driven from the section tag, which means any header or paragraph combinations that are NOT inside a containing section tag can still safely be used, and will not be changed to match the styles in Listing 16.

If we refresh the HTML output with the new styles, and do a little text editing, we should now see something like this:

Code Listing 15 with the CSS rules in Code Listing 16 applied

  1. Code Listing 15 with the CSS rules in Code Listing 16 applied

The Direct Child Selector (>)

As you've already seen, the descendant selector allows you to target child elements down the chain of elements in your markup.

If you want to target paragraph tags that reside inside a div with a class type of news, for example, then a selector of div.news p will do the job. There is, however, one drawback: the descendant selector is greedy.

When we say a selector is greedy, we mean that it will attempt to match as much as it possibly can (anyone who has any experience with regular expressions will know what I'm talking about).

What this means in practice is that not only will the elements at the first level of selection be selected, but any that match below that will too.

The direct child selector solves this by being less greedy, and going no further than the first level below the root selector.

Consider the following HTML markup:

<div class="test">

    <p>Paragraph 1</p>

    <p>Paragraph 2</p>

    <div>

        <p>Paragraph 3</p>

    </div>

    <p>Paragraph 4</p>

</div>

Code Listing 17: HTML markup to demonstrate the direct child selector

If we render Code Listing 17 in our browser, we'll get four simple paragraph elements.

HTML rendered using Code Listing 17

  1. HTML rendered using Code Listing 17

You'll notice from the markup that paragraph 3 is inside a nested div element; if we style this block using a standard descendant selector, we'll get the following output:

div.test p

{

  color: red;

}

Code Listing 18: CSS Rule to style the code in Listing 17 using a descendant selector

Output produced when combining the HTML in Code Listing 17 with the rule in Code Listing 18

  1. Output produced when combining the HTML in Code Listing 17 with the rule in Code Listing 18

At first glance, this output might seem ok, and in general may actually be what you wanted to achieve. Consider this, however: why is paragraph 3 being embedded in a further div element?

It may have been created that way with the intention of styling it differently than the other paragraph elements in the block.

Let’s change our rule, so it uses a direct child selector as follows:

div.test > p

{

  color: red;

}

Code Listing 19: CSS Rule to style the code in Code Listing 17 using a direct child selector

You should now see that it skips the paragraph in the nested element, but continues to style the others as expected.

Output produced when combining the HTML in Listing 17 with the rule in Listing 19

  1. Output produced when combining the HTML in Listing 17 with the rule in Listing 19

This comes in handy when creating things like pop-up menus, where you might like all the top-level elements to take on an unselected look and feel, but where nested items forming sub-menus need to be left alone when a parent element is selected.

The General Sibling Selector (~)

The general sibling selector, like its close cousin the adjacent sibling selector, is used to select elements that follow a parent of a given type. However, unlike its cousin, it attempts to select more than one match in the markup hierarchy.

The adjacent sibling selector will at most (as you saw previously) select only the first occurrence of a given match; the general sibling selector, however, will attempt to select that match, as long as the hierarchy continues to match.

If we build two unordered lists as follows:

<p>List 1</p>

<ul>

    <li><a href="#">Link 1a</a></li>

    <li><a href="#">Link 2a</a></li>

    <li><a href="#">Link 3a</a></li>

    <li><a href="#">Link 4a</a></li>

</ul>

<ul>

    <li><a href="#">Link 1b</a></li>

    <li><a href="#">Link 2b</a></li>

    <li><a href="#">Link 3b</a></li>

    <li><a href="#">Link 4b</a></li>

</ul>

<p>List 2</p>

<ul>

    <li><a href="#">Link 1a</a></li>

    <li><a href="#">Link 2a</a></li>

    <li><a href="#">Link 3a</a></li>

    <li><a href="#">Link 4a</a></li>

</ul>

<ul>

    <li><a href="#">Link 1b</a></li>

    <li><a href="#">Link 2b</a></li>

    <li><a href="#">Link 3b</a></li>

    <li><a href="#">Link 4b</a></li>

</ul>

Code Listing 20: HTML markup to demonstrate the sibling selector

As with the rest of the examples, if we first render this with no styling, we'll get the default standard rendering:

Output produced by the HTML in Code Listing 20 with no style rules applied

  1. Output produced by the HTML in Code Listing 20 with no style rules applied

To illustrate the difference, we’re first going to style the list using the adjacent sibling selector you saw earlier, using the following rule.

p + ul a

{

  color: red;

}

Code Listing 21: Adjacency selector for Code Listing 20

When we render Code Listing 20, using the rule in Code Listing 21, we get the following output:

Output produced by Code Listing 20 with the adjacency selector applied

  1. Output produced by Code Listing 20 with the adjacency selector applied

If you've been following along with the code, this shouldn't come as a surprise. The first group is styled, the second is not.

If we now switch our code to use the general sibling selector, however:

p ~ ul a

{

  color: red;

}

Code Listing 22: Sibling selector for Code Listing 20

We should see a difference in the selection:

Output produced by Code Listing 20 with the sibling selector applied

  1. Output produced by Code Listing 20 with the sibling selector applied

While the adjacent sibling selector stops at the first match, the general sibling selector does not; the general sibling selector will continue down the chain, matching anything in the rule as long as the element before it matches.

The difference between adjacency and descendancy

At this point you might be wondering why we have two ways of achieving apparently the same thing. It's important to remember that while we have styled similar scenarios so far in this chapter, we've done this in rather different ways.

When we talk about elements that are adjacent to each other, we mean these elements are rather like neighbors in a street of houses. If you were to draw a line down the alignment of each house, you’d see that everything was at the same level. In the following code, each of the div elements with a class attribute of house are adjacent to one another:

<div class="street">

    <div class="house"></div>

    <div class="house"></div>

    <div class="house"></div>

    <div class="house"></div>

    <div class="house"></div>

</div>

Code Listing 23: Adjacent elements

When we talk about elements being descendants of each other, we’re talking about a parent-to-child-like relationship. If we apply this to our street example in Code Listing 23, we might have “tenants” who occupy each house.

<div class="street">

    <div class="house"><p class="tenant"></p></div>

    <div class="house"><p class="tenant"></p></div>

    <div class="house"><p class="tenant"></p></div>

    <div class="house"><p class="tenant"></p></div>

    <div class="house"><p class="tenant"></p></div>

</div>

Code Listing 24: Descendant elements

As you can see in Code Listing 24, we now have a tenant inside each house. Tenants are not adjacent to each other because you have to leave the house, move down, and then enter into the next house to reach the next tenant.

However, since you can reach a tenant from a house, then a tenant becomes a descendant of a house.

Child and grandchild terminology are defined as a specialist case of descendancy. Just like in a family tree, a tenant in our example might have children, and those children might have grown up and had children of their own.

A child of a child would still be a descendant of a tenant, but it would not be a child of a tenant; it would be a grandchild, something like the following:

<div class="street">

    <div class="house">

        <div class="tenant">

            <div class="tenantsChild">

                <div class="childsChildButTenantsGrandChild"></div>

            </div>

        </div>

    </div>

</div>

Code Listing 25: Code showing child relation to dependency

If you were to create more div elements with a class of tenantsChild next to each other within the confines of the tenant, those tenantsChild elements, like the houses, would be adjacent to each other.

It takes a little bit of practice until you get into the habit of thinking this way, but if you think about HTML in its native form as a specialist, XML-based language, then you see that the nesting starts to make sense. Once the nesting makes sense, the flow and layout of the selectors start to fall into place too.

Don't worry if you struggle to make sense of it straightaway. It took me a long time to unravel it all too, and even now I still get it wrong sometimes.

So far we've covered the main base selectors. If you want to read up on the rest of them, you can find the official documentation on the W3C site.

I do think a warning is in order here, though. While the official W3C documentation is the official source of all things HTML, it's also a very difficult site to read.

There are easier sources of information, such as Mozilla and HTML Dog. I would strongly advise you digest those first, then visit the W3C site once you have a better understanding of the topic.

Attribute Selectors

To finish this chapter off, we’re going to take a look at something that’s been massively expanded on in CSS3: attribute selectors.

There has been some minimal effort to introduce a very small subset of this type of selector in previous versions, but it went largely unnoticed, so most developers never stopped to look at what it had to offer.

In CSS3 however, attribute selectors are all-powerful, and allow you to do some rather smart styling of elements.

First off, we need to define what an attribute selector actually is.

Unlike the selectors you've seen so far, an attribute selector is not a single character construct that sits between two targets; it's a multi-character appendage to a parent rule, which contains its own internal processing rules.

In a small way, attribute selectors are a little bit like having a custom set of search expressions, specifically for hunting out elements based on the value (or part of) of an attribute attached to them.

Take a look at the following HTML markup.

<ul>

    <li><a href="#" rel="external">External Link 1</a></li>

    <li><a href="#" rel="internal">Internal Link 1</a></li>

    <li><a href="#" rel="internal">Internal Link 2</a></li>

    <li><a href="#" rel="external">External Link 2</a></li>

    <li><a href="#" rel="external">External Link 3</a></li>

</ul>

Code Listing 26: HTML markup with custom attributes

In Code Listing 26, you can see I've created a fairly standard, unordered list containing items with anchor elements in them. It’s nothing unusual, and something you'll often see in navigation links in HTML documents.

What I've done, however, is to use the rel attribute to mark up the relation of the link, specifying if it's an external or an internal link.

If we wanted to style the two different types in different ways, we could, in theory, just add a class such as .internal or .external. However, there may be times that HTML markup is generated inside a process over which you have no control, so you may not be able to add classes to the output in this manner.

This is where the attribute selector comes in. You can use it to target a specific named attribute within the element, and as you'll see in just a moment, you can use it to not only target a full string, but part of a string too.

First, let's have a look at how we might apply it to our previous links example. Add the following style rules to your style sheet (assuming you've already added the preceding HTML to your document):

a[rel="external"]

{

      color: red;

}

a[rel="internal"]

{

      color: green;

}

Code Listing 27: Attribute Selector rules for Code Listing 26

If you render this in your browser, you should see something like the following:

Code Listing 26 with the CSS rules in Code Listing 27 applied to them

  1. Code Listing 26 with the CSS rules in Code Listing 27 applied to them

Just by using two different rules, we've easily targeted the two different types of links, simply because of the difference in the rel attribute.

A real-world example might look something like the following; change the code in Listing 26 to read as follows:

<ul>

    <li><a href="#">Link 1</a></li>

    <li><a>Link 2</a></li>

    <li><a>Link 3</a></li>

    <li><a href="#">Link 4</a></li>

    <li><a href="#">Link 5</a></li>

</ul>

Code Listing 28: HTML markup modified from Code Listing 26

By default, most browsers won't make a link clickable that has no href attribute, and for the default styling at least, they won't be styled using the usual blue underlining.

Output from Code Listing 28 with no styling.

  1. Output from Code Listing 28 with no styling.

However, in many cases (especially if you’re using a larger framework), you might find that anchor tags in general have been given a uniform style to maintain a consistent look and feel.

For example:

a

{

  text-decoration: none;

  color: green;

}

Code Listing 29: Possible rule to give a uniform look and feel to an anchor

This code might be used to apply that uniform style, and would make our list look as follows:

Code Listing 28 with a uniform style applied to the anchor element

  1. Code Listing 28 with a uniform style applied to the anchor element

You can immediately see that you've lost any contextual information that might suggest to you a link has no destination, and as a site user, you have no idea which links are good, and which are bad.

You could go through your code and add a class="nodestination" to each link with a missing href, but what if someone then added links to the database, and all of a sudden the link then has a valid destination? In this case, you’re faced with the task of finding all those links that didn't have an href, and now do, so you can remove the class name and restore normality.

The other way to address this problem is to use just the attribute selector with no extra content on its own, as follows:

a[href]

{

  text-decoration: none;

  color: green;

}

Code Listing 30: Attribute rule to target only anchors that have an href attribute

When we now refresh our page, we should see that we now get different styling than we did before:

Code Listing 28 with a uniform style, only applied to anchors with valid destinations

  1. Code Listing 28 with a uniform style, only applied to anchors with valid destinations

Now in order to have the links styled correctly, all you have to do is let your web application platform generate links with href attributes, and leave the href attributes out of anything that does not yet have a link.

There is one question remaining, however.

What if we also want to style the remaining elements that don't have the href attribute, for example, to make them a lighter color so they perhaps look disabled?

CSS3 also has this covered with a pseudo selector. We'll learn more about the new pseudo selectors in the next chapter; for now, we can solve the styling of anchor tags with missing href  attributes quite simply by using the following attribute/pseudo-styling rule:

a:not([href])

{

  text-decoration: none;

  color: silver;

}

Code Listing 31: Attribute rule to target only anchors that don’t have an href attribute

If we re-render our document after changing our style rule to match Code Listing 31, we should get the following:

Code Listing 28 with an inverted attribute style

  1. Code Listing 28 with an inverted attribute style

The following rules take advantage of the cascading nature of CSS, and combine things logically:

a

{

  text-decoration: none;

}

a[href]

{

  color: green;

}

a:not([href])

{

  color: silver;

}

Code Listing 32: Combined rules to style links with missing href attributes automatically

In theory, we could actually reduce that further, and just add the green color to the base anchor rule. This would apply the green as a default, but change it to silver if no href existed. The idea here is just to show what's going on in the simplest possible terms, and expanding things out often makes concepts clearer to understand.

If we render this now, we should see something like the following:

Code Listing 28 with the combined styles applied

  1. Code Listing 28 with the combined styles applied

The main advantage to take away from this example is that you now no longer have to worry about making sure that a specific class is applied to a given link, making maintenance of the document much easier and less error-prone. If you're running under a CMS such as Umbraco or WordPress, then all you have to care about is whether links have valid destinations or not.

Note: I've previously used an attribute selector in this fashion inside normal paragraph text to automatically highlight links that are in-line with the general text once they become active, and to make them look exactly like the paragraph text when they aren’t active.

I mentioned earlier that attribute selectors can also match on partial contents in a given attribute. There are additions to the main selector that allow you to check if an attribute’s value begins with, ends with, or contains a given substring.

This can be very useful in the case of external and internal links.

Think back to the code we saw in Code Listing 26; we used the rel attribute to define an internal or external relationship on an anchor element.

In terms of the W3C specifications, this was probably not the best way to do this, and quite likely, the HTML would fail to validate if it were tested with an HTML 5 validation tool.

This doesn't mean we have to go back to using a class attribute, however.

Imagine for a moment that all your external links had a fully qualified URL, and all your internal links just had a relative page leaf. In this case, Code Listing 26 might now be re-written as follows:

<ul>

    <li><a href="http://external.com/link1">External Link 1</a></li>

    <li><a href="internal/link1">Internal Link 1</a></li>

    <li><a href="internal/link2">Internal Link 2</a></li>

    <li><a href="http://external.com/link2">External Link 2</a></li>

    <li><a href="http://external.com/link3">External Link 3</a></li>

</ul>

Code Listing 33: Code Listing 26 rewritten to not use rel attributes

If you examine the difference in the href attributes, you'll see that all the external links start with “http://” and the internal ones do not.

If we use the “attribute value starts with” selector, we can now easily style the external ones with a different color.

We can set a uniform style for anchor tags in general, which would reflect the style for internal links by default, then be altered if it reflected an external link.

To use the starts with attribute selector, we specify a ^= between attribute name and value, as the following rule shows:

a[href^="http:"]

{

  color: red;

}

Code Listing 34: CSS style rule to change the color of attributes that start with “http”

If we apply that to the HTML markup in Code Listing 33, and then render it in the browser, we should get the following:

HTML from Code Listing 33 with the rule in Code Listing 34 applied to it

  1. HTML from Code Listing 33 with the rule in Code Listing 34 applied to it

Now if we add in a uniform rule as we did previously, so that links are green by default, we end up with output that looks like the following:

HTML Code Listing 33 with the final styling in place

  1. HTML Code Listing 33 with the final styling in place

I'm sure you can quickly realize how easily this could be combined with the rules to detect the presence of the attribute and make further choices on links with no href attributes, too.

The remaining parts of the attribute selector are the “ends with” and “contains” selectors.

“Ends with” comes in handy if you want to style links based on file type. For example, you could do the following:

<ul>

    <li><a href="photo1.png">Photo 1</a></li>

    <li><a href="photo2.png">Photo 2</a></li>

    <li><a href="sound1.mp3">Sound 1</a></li>

    <li><a href="sound2.mp3">Sound 2</a></li>

    <li><a href="document.pdf">Document</a></li>

</ul>

Code Listing 35: Code listing 33 rewritten to list file links

Then, create the following rules using the $= attribute selector as follows:

a[href$=".png"]

{

  color: red;

}

a[href$=".mp3"]

{

  color: green;

}

a[href$=".pdf"]

{

  color: blue;

}

Code Listing 36: Ends With attribute rules to style based on file type

When rendered, it should give the following:

Code Listing 35 showing the output from the “ends with” attribute selector

  1. Code Listing 35 showing the output from the “ends with” attribute selector

The final attribute-based selector is the contains selector, and does exactly as it says on the tin.

If an attribute value contains the given substring, then *= will match it.

For example, take a look at the following set of anchor tags:

<ul>

    <li><a href="/admin/users/list">List Users</a></li>

    <li><a href="/admin/personal/settings">Your Account Settings</a></li>

    <li><a href="/admin/users/edit">Edit Users</a></li>

    <li><a href="/admin/users/report">Users Report</a></li>

    <li><a href="/admin/personal/profile">Your Profile</a></li>

</ul>

Code Listing 37: Code Listing 35 rewritten to demonstrate “contains” attribute selector

With the following rules:

a[href*="users"]

{

  color: red;

}

a[href*="personal"]

{

  color: green;

}

Code Listing 38: Contains string attribute rules to style based on substring

This will produce the following output:

Output produced by Code Listing 37 with the rules in Code Listing 38 applied

  1. Output produced by Code Listing 37 with the rules in Code Listing 38 applied

What we've covered here hasn't even scratched the surface of the potential available, especially when it comes to attribute selectors.

Under HTML 5 there's a new attribute type called a data-attribute. This new attribute takes the form of:

data-

followed by a custom name, for example:

data-username

data-recordindex

You can use these data attributes on any element, for any purpose, and when combined with the correct selectors, they allow you use HTML 5 to describe its own intentions and style easily.

Summary

In this chapter we took a fairly deep dive into the main new selectors added in CSS3. We've seen how we’re no longer limited in how we can target our elements to style, and how we no longer have the restrictions we used to have, allowing almost limitless expression in our rules.

In the next chapter we'll take a closer look at the new pseudo selectors, which, when combined with what we've learned so far, will take the capabilities we have to new heights.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.