in
the document is either the parent or the child of another element, and it's often both.
Figure 2-14. A document tree structure
An element is said to be the parent of another element if it appears directly
above that element in the document hierarchy. For example, in Figure 2-14 , the first
p
element is parent to the
em
and
strong
elements, while
strong
is parent to an
anchor
element, which is itself parent to another
em
element. Conversely, an element is the child of another element if
it is directly beneath the other element. Thus, the anchor element in Figure 2-14 is a child of the
strong
element, which is in turn child to the
p
element, and so on.
The terms parent and child are specific applications of the terms ancestor and descendant . There is a
difference between them: in the tree view, if an element is exactly one level above
another, then they have a parent-child relationship. If the path from one element to
another continues through two or more levels, the elements have an
ancestor-descendant relationship, but not a parent-child relationship. (Of course, a
child is also a descendant, and a parent is an ancestor.) In Figure 2-14 , the first
ul
element is parent to two
li
elements, but the first
ul
is also
the ancestor of every element descended from its
li
element, all the way down to the most deeply nested
li
elements.
Also, in Figure 2-14 , there is an
anchor that is a child of
strong
, but also a
descendant of
paragraph
,
body
, and
html
elements. The
body
element is an ancestor of everything that
the browser will display by default, and the
html
element is ancestor to the entire document. For this reason, the
html
element is also called the root
element .
Descendant Selectors
The first benefit of understanding this model is the
ability to define descendant selectors (also known as contextual selectors ).Defining descendant selectors is the act of creating
rules that operate in certain structural circumstances but not others. As an example,
let's say you want to style only those
em
elements
that are descended from
h1
elements. You could put
a
class
attribute on every
em
element found within an
h1
, but that's almost as time-consuming as using the
font
tag. It's obviously far more efficient to declare
rules that match only
em
elements that are found
inside
h1
elements.
To do so, write the following:
h1 em {color: gray;}
This rule will make gray any text in an
em
element that is the descendant of an
h1
element.
Other
em
text, such as that found in a paragraph
or a block quote, will not be selected by this rule. Figure 2-15 makes this clear.
Figure 2-15. Selecting an element based on its context
In a descendant selector, the selector side of a rule is composed of two or more
space-separated selectors. The space between the selectors is an example of a combinator . Each space combinator can be translated as "found
within," "which is part of," or "that is a descendant of," but only if you read the
selector right to left. Thus,
h1 em
can be
translated as, "Any
em
element that is a
descendant of an
h1
element." (To read the
selector left to right, you might phrase it something like, "Any
h1
that contains an
em
will have the following styles applied to the
em
.")
You aren't limited to two selectors, of course. For example:
ul ol ul em {color: gray;}
In this case, as Figure 2-16 shows,
any emphasized text that is part of an unordered list that is part of an ordered list
that is itself part of an unordered list (yes, this is correct) will be gray. This is
obviously a very specific selection criterion.
Figure 2-16. A very specific descendant selector
Descendant selectors can be extremely powerful. They make possible what could
never be done in HTML—at least not without oodles of
font
tags. Let's consider a common example. Assume you have a document
with a sidebar and a main area. The sidebar has a blue background, the main area has
a