CSS Selectors

As explained earlier, the purpose of the selector is to select elements to be affected by various CSS rules. Selectors always appear before a { in a CSS rule.

I’ll use quite a few properties you haven’t seen before, but their names are pretty much self-explanitory.

While there are several selectors, only 3 are are universal to all browsers that support CSS:

  • type selectors (which select according to the element name),
  • class selectors (which select elements according to the value of the class attribute,
  • and id selectors (which select according to the value of the id attribute).

Other selectors are rarer because they are not universal to all browsers or are rarely needed. They are:

  • Attribute selectors (which select elements according to the presence of attributes and optionally their value)
  • The universal selector (which selects all elements)
  • Pseudo-classes and pseudo-elements

All other selectors are combinations of the above.

Basic CSS Selectors

Type, class, and id selectors are far and away the most common selectors; you can create quite a good style sheet using just these.

Type Selectors

A type selector selects elements according to their type — that is, their element name. For example, the type of element selected could be a third-level header; therefor the type would be h3. The desired effect: To display third-level headers by using a different font than what’s used on the computer, centering the text and making it larger, and having a black solid line 1 pixel thick above and below the the header. Here are the declarations:

Set the font:
font-family:"Copperplate Gothic Light", serif; 1
Center the text:
text-align:center;
Make the text larger:
font-size:150%; 2
Put a black solid line 1 pixel thick above and below the header (aka: a border)
Make the border a solid line:
border-style:solid;
Color the border black:
border-color:black;
Make the border along the top 1 pixel thick:
border-top-width:1px;
Make the border along the bottom 1 pixel thick:
border-bottom-width:1px;
No border on the left side:
border-left:0;3
No border on the right side:
border-right:0;3

Notes:

  1. To use a specific font on your computer, it is wisest to put the font name in quotations so that the spaces in the font’s name don’t confuse the browser. serif is simply a Plan B for the browser in case the computer does not have Copperplate Gothic Light installed. You may have as long a list of fonts as you like in this context.)
  2. This means 150% the size of the text in the parent element. Be careful, or you may end up with some very large text indeed.
  3. When you’re using 0 in the context of borders, it means that you don’t want a border to appear at all. Therefore, you don’t need to refine the property to specify width.

This set of rules will therefore look like this:

{font-family:"Copperplate Gothic Light", serif; text-align:center; font-size:150%; border-style:solid; border-color:black; border-top-width:1px; border-bottom-width:1px; border-left:0; border-right:0;}

Now, you might be thinking that what’s between { and } looks a lot like the contents of the style attribute. It certainly should: the style attribute, by definition, contains CSS. In fact, using the style attribute is called inline styling.

It is common practice to put multiple declarations on seperate lines for the sake of readabilty:


{
font-family:"Copperplate Gothic Light", serif;
text-align:center;
font-size:150%;
border-style:solid;
border-color:black;
border-top-width:1px;
border-bottom-width:1px;
border-left:0;
border-right:0;
}

Now, to specify that it’s the h3 element you want this rule to apply to, the selector should be h3. Do not use the < or > symbols, just the element name.


h3{
font-family:"Copperplate Gothic Light", serif;
text-align:center;
font-size:150%;
border-style:solid;
border-color:black;
border-top-width:1px;
border-bottom-width:1px;
border-left:0;
border-right:0;
}

And the results are so:

First-, second-, and fourth-level headers are left unstyled, but third-level headers have the appearance above.

Below is the code of the page in its entirety:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Styled Third-Level Headers</title>
<style type="text/css">
h3{
font-family:"Copperplate Gothic Light", serif;
text-align:center;
font-size:150%;
border-style:solid;
border-color:black;
border-top-width:1px;
border-bottom-width:1px;
border-left:0;
border-right:0;
}
</style>
</head>
<body>
<h1>First-level header is ignored</h1>
<h2>So is the second-level header</h2>
<h3>Third-level header gets the fancy look</h3>
<h3>So does this one</h3>
<h4>Fourth-level header is ignored, too</h4>
<h3>But all third-level headers are affected by this rule.</h3>
</body>
</html>

Now, wouldn’t you agree that this is a lot better than:

<h3 style="font-family:"Copperplate Gothic Light", serif; text-align:center; font-size:150%; border-style:solid; border-color:black; border-top-width:1px; border-bottom-width:1px; border-left:0; border-right:0;">

repeated every time you wanted a third-level header?

Class Selectors

The class selector takes focus off the element name and concentrates on what group the element is a part of, which is defined by the class attribute. The selector in this case consists of a period followed by the class name.

So say we have two classes that describe how loudly someone is speaking. The classes are:

  • whisper
  • yell

The contents of an element with the "whisper" class is to be in small text, while the contents of an element with the "yell" class should be large. Therefore, we set up the classes like this:


.whisper{font-size:80%;}
.yell{font-size:110%;}

In this case, I have the entire rule on one line since it saves space without sacrificing readability.

Whispered text is smaller than normal, yelled text is larger.

The code of the page looks like this:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Whisper and Yell Classes</title>
<style type="text/css">
.whisper{font-size:80%;}
.yell{font-size:110%;}
</style>
</head>
<body>
<p><big class="whisper">"Sorry, I lost my voice,"</big> she whispered.</p>
<p><small class="yell">"Speak up! I can't hear you"</small> he replied.</p>
</body>
</html>

Now, it would have been more semantic to use a q element or at least a span element, but I wanted to make a point about presentational markup. Look closely, and you’ll see that, using CSS, I completely reversed the functions of the big and small elements by putting them in the .whisper and .yell classes, respectively — which puts paid to any use they might have.

Another example would be found in the code I used to describe the div element. Here is the original code:

Original Code

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Example "div" Elements</title>
</head>
<body>
<div id="Part_3-Chap_18-Lorem_Ipsum">
<h1>Lorem Ipsum</h1>
<p>The <span class="foreign" style="font-style:italic;">Lorem Ipsum</span> text is essentially pseudo-latin text that is used as a placeholder for actual text. Since it is semi-readable nonsense, the eye generally skips over it, and looks at the page design instead.</p>
<div id="Part_3-Chap_18-Lorem_Ipsum_Example">
<h2>Example Lorum Ipsum Text</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>
</body>
</html>

Here, I can put the foreign class to work by deciding that all elements with the foreign class are in italics, allowing me to remove the style attribute (which cuts down on code).


.foreign{font-style:italic;}
. . .
<span class="foreign">Lorem Ipsum</span>

I also want the paragraph that holds the Lorem Ipsum text to be in italics for the same reason, so I add the foreign class to that paragraph as well. Note that I’m not adding this class to the paragraph containing the Lorem Ipsum text because I want it in italics; I want the Lorem Ipsum text in italics because the text is not in English. Therefore, semantic meaning is preserved.


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Example "div" Elements</title>
<style type="text/css">
.foreign{font-style:italic;}
</style>
</head>
<body>
<div id="Part_3-Chap_18-Lorem_Ipsum">
<h1>Lorem Ipsum</h1>
<p>The <span class="foreign">Lorem Ipsum</span> text is essentially pseudo-latin text that is used as a placeholder for actual text. Since it is semi-readable nonsense, the eye generally skips over it, and looks at the page design instead.</p>
<div id="Part_3-Chap_18-Lorem_Ipsum_Example">
<h2>Example Lorum Ipsum Text</h2>
<p class="foreign">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>
</body>
</html>

And here is the result:

The words 'Lorem Ipsum' and the dummy text are now in italics, thanks to the styling of the 'foreign' class.

ID Selectors

This, by far, is the most specific selector of all. Because of how the id attribute works, this selector specifies one element. This type of selector is usually used for layouts, selecting elements that are given highly specialized roles.

While class-based selectors are preceded by a period, id-based attributes are preceded by a hash mark (#).

In this case, I’m going to use an example from Chapter 10, in which I demonstrated div elements.

Around the div element with the id of Lorem_Ipsum_Example, I want to put a 1-pixel solid black border. Therefore, I add the following rule:


#Lorem_Ipsum_Example{
border-color:black;
border-style:solid;
border-width:1px;
padding:5px;
}

I don’t need to specify top, bottom, left or right since this border will go all the way around. padding creates space between the border and the content.

For good measure, let’s round off this demonstration of basic selectors by saying that the text of the h1 element should be underlined.


h1{text-decoration:underline;}
The example 'Lorem Ipsum' text is now inside a black border.

The final code for all of this is:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Example "div" Elements</title>
<style type="text/css">
h1{text-decoration:underline;}
.foreign{font-style:italic;}

#Lorem_Ipsum_Example{
border-color:black;
border-style:solid;
border-width:1px;
padding:5px;
}

</style>
</head>
<body>
<div id="Part_3-Chap_18-Lorem_Ipsum">
<h1>Lorem Ipsum</h1>
<p>The <span class="foreign">Lorem Ipsum</span> text is essentially pseudo-latin text that is used as a placeholder for actual text. Since it is semi-readable nonsense, the eye generally skips over it, and looks at the page design instead.</p>
<div id="Part_3-Chap_18-Lorem_Ipsum_Example">
<h2>Example Lorum Ipsum Text</h2>
<p class="foreign">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>
</body>
</html>

Other Selectors

There are a number of other selectors aside from type, class, and ID. They are less common, mostly because they aren’t supported by all browsers or there is rarely a use for them.

The Universal Selector

The universal selector selects everything, and its symbol is *. It’s not commonly used, but if you want every single element to have a black, solid border one pixel in width all the way around, this would be the selector to use.

Universal Selector In A Rule That Gives All Elements A Margin, Padding And A Black Border

*{
border-width:1px;
border-style:solid;
border-color:black;
padding:2px;
margin:5px;
}

Behold the result:

Elements with borders.

This has the bonus of being a very nice demonstration of nesting.

Attribute Selectors

Other attributes can be specified in selectors but rarely are for one major reason: Internet Explorer has a long history of getting its knickers in a twist over a lot of things and this is one of them. To put it shortly, while Firefox, Opera, Safari, and other browsers have supported such methods for years, it wasn’t until Internet Explorer 7 (released in 2006) that Internet Explorer supported this as well. Considering earlier versions of Internet Explorer are reasonably popular (nearly 20% of all people who use a browser use IE4 – 6), it is still likely that someone will be using one of those browsers, and therefore won’t be able to view a page styled using these selectors properly.

The syntax for this selector is a little more complex than what we’ve seen so far. This selector MUST be contained within square brackets, like this:

[attribute]

This is important. If you, say, want to select all elements with a title attribute, but forgot the brackets, the browser would instead select the title element. There’s not much you can do with a title element, but that’s what the browser would select. On the other hand, if you intended to select an h3 element, but had h3 inside square brackets, it would look for elements with an h3 attribute — an attribute that does not exist in HTML.

Selecting By Attribute Presence

It is possible to select elements by the mere presence of a specific attribute.

In the following example, all quotes with a lang attribute are in italics:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Using the Language Attribute</title>
<style type="text/css">
[lang]{font-style:italic;}
</style>
</head>
<body>
<p>The Latin phrase <q lang="la">cogito ergo sum</q> translates to <q lang="en">I think, therefore I am</q>.</p>
</body>
</html>

Thus, all elements with a lang attribute will be in italics. It is total coincidence that in this case, both such elements are q elements.

The quoted text is in italics

Selecting By Attribute Value

Wnat if I don’t want English phrases to be in italics, because English is not (to me) a foreign language? In short, I want all elements with a lang attribute to be in italics, except when that attribute specifies English as the language? I can, in this case, make an exception for all attributes with the exact value of en, which is the code for English.

As before, the selector is contained within square brackets ([ ]). And, as before, you use the attribute name (in this case, lang). However, you would follow lang with an equal sign and the value of the attribute in quotations. Below is the selector in its entirety (the part that specifies the value en is highlighted):

[lang="en"]

Since this is intended to be an exception to the rule, it would follow the more general rule pertaining to all elements containing a lang attribute.


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Using the Language Attribute</title>
<style type="text/css">
[lang]{font-style:italic;}
[lang="en"]{font-style:normal;}
</style>
</head>
<body>
<p>The Latin phrase <q lang="la">cogito ergo sum</q> translates to <q lang="en">I think, therefore I am</q>.</p>
</body>
</html>

This means that every element that has a lang attribute with the exact value of en will be displayed normally.

The quoted text is in italics, except where it is in English
Variants

There are variations of this, all depending on what symbol accompanies the equal sign.

=
[lang="en"]

The lang attribute has a value of exactly en.

|=
[lang|="en"]

The value en begins a hyphen-seperated list of values. This allows for values of en-CA, en-UK, or en-US (Canadian, British, or American English, respectively) as well as en alone.

~=
[lang~="en"]

The value en is one of a space-seperated list of values (for example, lang="fr en de", or is on its own. This selector works a lot like the class selector (and indeed, class selectors could be written this way), but this is universal to all attributes. On the downside, this is not universal all browsers.

Pseudo-classes and Pseudo-elements

Pseudo-classes and pseudo-elements select things that aren’t actually in the HTML document. Instead, the browser uses the document to infer what is being selected by the pseudo-class or -element. Because of the way these work, these are almost always used as part of a compound selectors.

These are different from other selectors, since all of the above can select any element, id, class, attribute, or attribute value, even if the specified element or attribute is not part of HTMLCSS was designed to be used with all markup languages. Pseudo-classes and pseudo-elements, on the other hand, are explicitly defined in the CSS specification.

Both pseudo-classes and pseudo-element selectors are preceded by a colon (:).

Pseudo-Classes

Pseudo-classes select elements according to characteristics that are not specified in their attributes, element name, or their position in the document tree (remember that term from Chapter 2?). There are two exceptions, marked with an asterisk. The pseudo-classes are:

  • :first-child*
  • :lang()*
  • :link
  • :visited
  • :active
  • :focus
  • :hover
:first-child

This applies to any element that is the first child element of its parent element. Used alone like this, it will first apply to the first child of the body element, then the first child element of every element within the body, their first child elements, and so on.

This will not apply to the body element because the body element is not the first child of the html element — that’s head. The html element, of course, isn’t a child element at all.

Below is the code of a page that puts a border around every element that is the first child of another element.

First Child Elements In Bold
First Child Elements Of First Child Elements In Dark Red

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Demonstrating :first-child</title>
<style type="text/css">
:first-child{
border-width:1px;
border-style:solid;
border-color:black;
padding:2px;
margin:5px;
}
</style>
</head>
<body>
<h1>A Demonstration of the <em>:first-child</em> Pseudo-class</h1>
<p>The style sheet of this page tells the browser to put a border around specific elements — in particular, the <strong>first child element</strong> of each element in the document body.</p>
<p>Since the <strong>h1</strong> element above is the first child element of the <strong>body</strong> element, it gets a border. These paragraphs, which come later, don't.</p>
<p>However, some elements nested in the <strong>p</strong> elements fit the requirements: they are the <strong>first child elements</strong> of those paragraphs, so <em>they</em> get a border as well — as does the sole (and thus first) child element of the <strong>h1</strong> element.</p>
<p>Please note that the text between start tags has no bearing on whether or not a child element is the <strong><em>first</em> child element.</strong></p>
</body>
</html>

The result is:

The first child element of each element gets a border.

:lang()

This is the other pseudo-class that can be inferred from the HTML document. It selects elements by their lang attribute — (As does the selector [lang|=""] but also selects their child elements as well.

This pseudo-class is a bit more complicated because it takes the following form:

:lang(X)

X must not be blank; it must have a value — even if it is not a legitimate language code.

In the example below, I fiddled with the Lorem Ipsum page to illustrate this. Since the text is based on Latin, but not in any actual language, I used the fake language code x-Lorem (x- means an experimental language).

So behold the code (CSS rule highlighted and langage attributes highlighted):


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Lang Pseudo-Class</title>
<style type="text/css">
:lang(x-Lorem){
border-color:black;
border-style:solid;
border-width:1px;
padding:5px;
}

</style>
</head>
<body>
<div id="Part_3-Chap_18-Lorem_Ipsum">
<h1>The Lorem Ipsum Text</h1>
<p>The <span lang="x-Lorem">Lorem Ipsum</span> text is essentially pseudo-latin text that is used as a placeholder for actual text. Since it is semi-readable nonsense, the eye generally skips over it, and looks at the page design instead.</p>
<div id="Part_3-Chap_18-Lorem_Ipsum_Example" lang="x-Lorem">
<h2>Lorum Ipsum</h2>
<p class="foreign">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>
</body>
</html>
All elements of the experimental language Lorem get a border.

Note that not only does the div element with the lang attribute get a border, but also its child elements, since they are assumed by the rule (and thus the browser) to be in the Lorem language. That is the difference between [lang|="X"] and :lang(X) — the former would put a border around the div element and ignore its children.

Dynamic Pseudo-Classes

The dynamic pseudo-classes allow for some interaction with the webpages beyond simply clicking on links.

Again, I’m giving these short shrift because you already have an idea of how pseudo-classes work.

:active
This is usually used with hyperlinks, but could be used with any element. An element is active between the time you press down the mouse button while the mouse cursor is over that element and the time you release the mouse button — in other words, when you are actually clicking on the element.
:focus
This one is usually used for form elements — and we haven’t discussed those because forms are absolutely useless without scripting, which lets you interact with the page (and is also the hairiest hocus-pocus website creation has to offer). We’ll get to forms when we get to scripting, but what :focus means is that the form element is ready to accept input from the keyboard.
:hover
Have you ever seen pages where you move the mouse cursor over a link, and the color or background image changes? This is the pseudo-class that allows you to do that.

Pseudo-Elements

While pseudo-classes control elements according to characteristics unrelated (for the most part) to the document tree, pseudo-elements tell a browser to add elements to the document tree. The pseudo-elements are:

  • :first-line
  • :first-letter
  • :before
  • :after

These not universal to all modern browsers.

:first-line and :first-letter

It is impossible to use HTML to specify the first line of a paragraph. People may use different screen resolutions or may not even have their browser maximized. However, sometimes you do want to bring attention to the first line. That is what the first-line pseudo-element is for. This rule depends entirely on the browser knowing where the first line ends.

The :first-letter selects only the first letter in an element, allowing further styling of one’s text. While you can specify the first letter using HTML, this rule saves you some coding.

Below is a webpage that uses both pseudo-elements in its style sheet.


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>:first-line and :first-letter</title>
<style type="text/css">
:first-line{
font-weight:bold;
font-variant:small-caps;
}
:first-letter{
font-size:3em;
display:block;
float:left;
margin:10px;
}

</style>
</head>
<body>
<p>The <q>:first-line</q> and <q>:first-letter</q> pseudo-elements cause a rule to only affect <em>some</em> of an elements contents — what part of those contents their names explain. In this case, I decided that the first line of a paragraph should be bold and in small capitals, and the first <em>letter</em> should be 3 times the size and have the text flow around it. There is no way that the HTML document can decide what will be the first line, since people have different screen resolutions, but the browser is able to figure it out for itself.</p>
</div>
</body>
</html>

Below is the result:

The first-line and first-letter elements demonstrated.

:before and :after

These two pseudo-elements are used to put little something extra on either side of an element (which side is described by the pseudo-element).

Below is a page that uses both rules:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>:first-line and :first-letter</title>
<style type="text/css">
:before{content:"(";}
:after{content:")"}
</style>
</head>
<body>
<h1>:before and :after</h1>
<p>The <q>:before</q> and <q>:after</q> pseudo-elements actually add content to a webpage. As they are not universal to all browsers, they should not be relied on for everything.</p>
<p>Come to think of it, CSS itself is not universal to all browsers.</p>
<p>In any case, the rules here put parentheses around each element that shows up in the browser window: <code>html</code>, <code>body</code>, <code>h1</code>, <code>p</code>, <code>q</code>, and <code>code</code>.</p>
</div>
</body>
</html>
The :before and :after pseudo-elements demonstrated.

Mix And Match

When you want to select paragraphs, the selector reads p. When you want to select elements of the foreign class, the selector reads .foreign.

But what if you want to select paragraphs of the foreign class?

To understand this next part, you have to understand that every class selector, to the browser, looks like this:

*.foreign

Remember the universal selector from earlier? When on its own, it selects everything, but now it selects everything with the foreign class. Notice there is no space between * and .foreign (this is important).

To specify a specific type of element, replace * with the element name you want. What this means is that the element must match in both name and class to be selected by the rule.

p.foreign

Do note: The element name must always come first. That is how CSS works; it selects elements by element type first, then narrows down the selection by attributes and their values. The attributes, IDs, classes, and pseudo-classes may be in any order, but pseudo-elements must come at the end.

Below, I will demonstrate several combinations that can be made by this means:

Element must belong to classes class1 and class2
Selector:
.class1.class2
Will be selected:
  • p class=”class1 class2″
  • p class=”class2 class1″
  • p class=”class1 class2 class3″
Will not be selected:
  • p class=”class1″
  • p class=”class2″

Do note that some browsers will be confused by selectors that use multiple classes like this, though, and will only select according to the last class listed.

Element must be of type p and belong to class class1
Selector:
p.class1
Will be selected:
  • p class=”class1″
  • p class=”class1 class2″
Will not be selected:
  • div class=”class1″
  • p class=”class2″
  • p
Element must be of type ul and have the ID Navigation
Selector:
ul#Navigation
Will be selected:
  • ul id=”Part_3-Chap_18-Navigation”
  • ul class=”class1″ id=”Part_3-Chap_18-Navigation”
Will not be selected:
  • div id=”Part_3-Chap_18-Navigation”

This may seem a little redundant; after all, there can be only one element within an HTML document with the ID Navigation. And, if used in an internal stylesheet, specifying the element type would indeed be redundant. But recall that the ID Navigation must be unique within the document, not within the website, and an external sheet can affect an infinite number of pages — and there could be as many elements with the ID Navigation as there are pages. Some of these elements might be of the element type ul (in which case the rule would apply), some might of another type (and would therefore be excluded).

Element must be of type q, have the class whisper, and a lang attribute
Selector:
q.whisper[lang]
Will be selected:
  • q class=”whisper” lang=”en”
  • q class=”whisper class1″ lang=”en”
Will not be selected:
  • q class=”whisper”
  • q lang=”en”
  • span class=”whisper” lang=”en”

These are just some of the combinations you can use to refine which elements are selected. There are only two combinations that you may not use: A combination of ID and ID and a combination of type and type. This is offset by the fact that each element may have only one ID and one type.

Selecting According To Nesting

Selectors can be made more exclusive by specifying not just element, class, ID, attribute, or so on, but also specifying your desired elements’ ancestors, parents, and siblings. In all cases of the following selectors, the last selector in the sequence is the subject of the rule.

Ancestor/Descendant

For example, a selector could specify span elements that are descendants h2 elements. Below is the selector:

h2 span

The selector first specifies h2 elements, then tells the browser to look for a span element within any h2 elements. It’s important when using these selectors to name the elements from the outside in. If the selector reads span h2, it won’t match anything — unless you’ve nested an h2 element within a span element, which you’re not supposed to do.

It’s important to remember that this selector specifies the descendant element, not the child element. This selector will match all span elements nested within an h2 element, no matter what else they are nested in or how many layers of nesting there are.

This means is universal to all browsers.

Parent/Child

What if you wanted to specify only span elements that were immediately nested inside h2 elements — that is, child span elements? A special symbol comes into play: >.

h2 > span

As before, the selector first specifies h2 elements, then tells the browser to look for a span element within any h2 elements — but this time, only to look as far as the children of the h2 elements. Grandchildren and so on are ignored.

This means is not universal to all browsers.

By Preceding Sibling

This selector selects elements that follow other elements. The sign to signify this is +. For example, if you wanted to target a paragraph that immediately followed a sixth-level header, the selector would be

h6 + p

In this case, the browser look for an h6 element and then looks for a following p element. Text between the two elements is not taken into account. However, if there is, say, a div element between an h6 element and the next p element, the rule will not come into effect.

This means is not universal to all browsers.

Below is a demonstration of how the above selectors work. Each instance of the words “span element” (or the plural thereof) is in a span element.

A Page With An Internal Style Sheet Demonstrating The Above Selectors

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Selecting By Nesting</title>
<style type="text/css">
span{color:red;}
div span{color:blue;}
div>span{color:green;}
span + span{color:olive;}
</style>
</head>
<body>
<p>The color rules set down by the stylesheet are thus:</p>
<ol>
<li>All <span>span elements</span> are red.</li>
<li>Exception to Rule 1: all <span>span elements</span> that are descendants of a <strong>div</strong> element are blue.</li>
<li>Exception to Rule 2: all <span>span elements</span> that are <em>children</em> of a <strong>div</strong> element are green.</li>
<li>Exception to all of the above: all <span>span elements</span> that are immediately preceded by a sibling <span>span element</span> (text between them does not count) are colored olive.</li>
</ol>
<p>This <span>span element</span> is not within a <strong>div</strong> element, so it is colored red.</p>
<div>
<p>The <span>span element</span> in this paragraph are child elements of a <strong>p</strong> element that is itself a child element of a <strong>div</strong> element, so they are colored blue. <em>This</em> <span>span element</span> is preceded by an <strong>em</strong> element, so it is also blue. Since a <strong>strong</strong> element precedes the next <span>span element</span> it, too, is blue, but the next two <span>span elements</span> are preceded by <span>span elements</span> so they are colored olive.</p>
This <span>span element</span> is a child of a <strong>div</strong> element and preceded by a <strong>p</strong> element, therefore it is green.
</div>
</body>
</html>

Pictured below is the result:

Spans colored according to nesting.

The example back in Chapter 10, which showed p elements nested within del and ins elements can be simplified by these simple rules:


del p{line-decoration:line-through;}
ins p{line-decoration:underline;}

What this means is every p element that is a descendant of a del element gets a line through its text, and any p element that is a descendant of an ins element is underlined.

It also means you can get rid of the style attributes used in the p elements:


<style type="text/css">
del p{line-decoration:line-through;}
ins p{line-decoration:underline;}
</style>
. . .
<del cite="G. W. Bush is no longer president" datetime="January 20, 2009"><p>Thus, President George W. Bush is the 43<sup>rd</sup> <em>President</em>, but only the 42<sup>nd</sup> <em>person</em> to hold that post.</p></del>
<ins cite="B. H. Obama is now president" datetime="January 20, 2009"><p>Thus, President Barack H. Obama is the 44<sup>th</sup> <em>President</em>, but only the 43<sup>rd</sup> <em>person</em> to hold that post.</p></ins>

The result is identical to the example in Chapter 10:

The deleted paragraph has a line through it, the added paragraph is underlined.

Now in the above examples, I specified ancestors by element name, but you can also specify them by attributes, class, ID, pseudo-class, or any combination of the above as seen in the Mix And Match section. The only thing you can’t use to specify ancestors, parents or siblings is a pseudo-element.

Multiple Selectors

While it is true each selector can have, at most, one rule (although you could have the same selector several times), a rule can have more than one selector. The symbol used to create a group of selectors is a comma, which tells the bowser to expect another selector.

For example, if you wanted all header elements to be centered, using one selector for each rule would look like this:


h1{text-align:center;}
h2{text-align:center;}
h3{text-align:center;}
h4{text-align:center;}
h5{text-align:center;}
h6{text-align:center;}

To save space and typing, you could also rewrite the above in this fashion:

h1, h2, h3, h4, h5, h6{text-align:center;}

You can join any number and any kind of selectors in this manner. Below is the of adding an internal stylesheet with the above rule to the header elements example from Chapter 10.

Centered header elements.

Final Notes

Just one more thing you should know. While selecting elements solely by their name, class, ID, or attributes causes the top-to-bottom hierarchy of a stylesheet fairly straight forward, more complex selectors can cause things to get more complicated. So don’t hesitate to make selectors more explicit to get the results that you want.

Now that you know how selectors work, I can now explain what you can do with them. The next few chapters will be all about CSS properties, their permitted values, and how you can use them.