complete css guide

Descendant selectors

Browser support

Explanation

The first selector we saw, the type selector, gives developers control over the appearance of their web pages, but it isn't a very fine tuned control. It's all or nothing, every paragraph or none.

Class selectors give us control over how different kinds, or classes of elements will appear.

Descendant selectors give us fine tuned control over the appearance of HTML elements depending on their relationship with other HTML elements in what is referred to as the HTML containment hierarchy.

figure 2: the HTML containment hierarchy

If you are familiar with standards based HTML and XHTML, as taught in our course HTML and XHTML for CSS, you'll know that it's useful to visualize an HTML document as a series of containers. From this, you can think of the containers in terms of family relationships. So, looking at figure 2

the <body> element is the parent of both the <h1> element and the <p>

the <h1> element and the <p> elements are both the children of the <body> element

the <h1>, <p>, <img> and <a> elements are all descendants of the body element

A descendant selector selects an element only when it is the descendant of another specified element. It's probably easiest to get a grip on this by looking at some concrete examples. You may or may not use the emphasis or the strong emphasis elements (<em> and <strong>), preferring the italic and bold tags instead. If you keep in mind the golden rule, separate style from content, you'll see that the former elements are to be preferred. So for this example, I'll talk about these logical rather than presentational tags.

Let's suppose we want to follow typographical conventions and make <strong> elements appear in bold. To do this using a type selector, we'd add the following statement to our style sheet:

strong {font-weight: bold}

But what if we want to use the <strong> element in a heading, and our headings are already bold? With the above statement, the strong text will appear the same as the text around it. What we would like is to have a <strong> appear differently when it is in a heading. This is what descendant selectors let us do.

Syntax

The descendant selector is simply a list of other selectors, each separated by a space. You can think of the order of the selectors as being from the outside to the inside of the containment hierarchy. For example, the selector for strong elements inside level 1 headings would look like this

h1 strong

This statement selects any strong element inside a heading of level 1, and draws it underlined.

You can create descendant selectors of any depth, for instance

ul li strong

selects <strong> elements only when they are inside list items which are inside unordered lists.

Descendant selectors do not distinguish how far elements are separated from each other in the containment hierarchy. For example the following selector

p img

will obviously select the <img> element in this example, where it is the child of the <p> element.

<p>Here is the red pill <img src="red_pill.gif" /></p>

But it will also select it in this next example, where it is not a child, merely a descendant.

You'll see this distinction more clearly once you start working with child selectors, which are a kind of even more finely tuned descendant selector.

Descendant selectors can in fact be used with selectors other than type selectors. So for example, if you only want to select <strong> elements which are inside paragraphs of class question, you would use

p.question strong

As we are about to see, there are a number of other types of selector, all of which can be used with descendant selectors in a similar way.

The descendant selector gives us much finer control over the appearance of a page. You may not find yourself using it frequently at first, but it can be very valuable.

The most immediately obvious way in which descendant selectors are useful is referred to above: when a selected element is going to be contained by another selected element you may want it to have a particular appearance.

There is another, less obvious, but extremely useful way of using descendant selectors. You can select very particular elements with them without having to make a single change to the HTML. Often, when your first idea might be to use a class selector (and therefore you'd have to go and put classes throughout the HTML), you can just as easily create a descendant selector and give it the properties you want. For example, if you want to get rid of those unsightly borders that browsers sometimes place around linked images, all you need do is create a descendant selector that selects images inside links, and give this selector a border of none. Descendant selectors then can save you a lot of coding.