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-explanatory.
Three selectors have been around since the very beginning and are universal to all browsers that support CSS:
class attribute.id attribute.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; therefore 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 header. Here are the declarations:
font-family:"Copperplate Gothic Light", serif; 1text-align:center;font-size:150%; 2border-style:solid;border-color:black;border-top-width:1px;border-bottom-width:1px;border-left:0;3border-right:0;3Notes:
Serifis simply a
Plan Bfor the browser in case the computer does not have
Copperplate Gothic Lightinstalled. You may have as long a list of fonts as you like in this context.)
150% the size of the text in the parent element.Be careful, or you may end up with some very large text indeed.
0in the context of borders, it means that you don't want a border to appear at all. Therefore, you don't need to specify
border-left-width, -color, or -style (same goes for the border on the right). More on this when I talk about borders in Borders, Padding, And Margins: The CSS Box Model.This set of rules will therefore look like this:
It is common practice to put multiple declarations on separate lines for the sake of readabilty:
Now, to specify that you want this rule to apply to the h3 element, the selector should be h3. Do not use the <
or >
symbols, just the element name.
h3 Element)And the results are:
Below is the code of the page in its entirety:
Now, wouldn't you agree that this is a lot better than
repeated every time you wanted a third-level header?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;"
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:
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:
In this case, I have the entire rule on one line since it saves space without sacrificing readability.
The code of the page looks like this:
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:
By giving the big element the whisper class and the small element the yell class, their effects are completely reversed—which nullifies any use they might have.
Another example would be found in the code I used to describe the div element back in Block Elements. Here is the original code:
Here, I can put the foreignclass to work by deciding that all elements with the foreignclass are in italics, allowing me to remove the style attribute (which cuts down on code).
I also want the paragraph that holds the Lorem Ipsum
text to be in italics for the same reason, so I add the foreignclass 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, which gives the foreign class semantic meaning to go with its effect.
And here is the result:
This is the most specific selector of all—it specifies one and only one element, using that element's identity. Just to remind you, in (X)HTML, an element's identity is specified in its id attribute. 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, identity-based selectors are preceded by a hash mark (#
).
In this case, I'm going to use an example from Block Elements, in which I demonstrated div elements.
Around the div element with the identity Lorem_Ipsum_Example
, I want to put a 1-pixel solid black border. Therefore, I add the following rule:
I don't need to specify top
, bottom
, left
or right
since this border will go all the way around. The
property creates space between the border and the content.padding
For good measure, let's round off this demonstration of basic selectors by saying that the text of the h1 element should be underlined and that anything with the foreign
class be in italics.
h1 ElementThe final code for all of this is:
The type, class, and identity selectors will do a lot for you, but the last two require you to use those attributes and the first might be a bit broad. In CSS 2, 4 new types of selectors were added.
Some pseudo-classes and pseudo-elements were introduced in CSS 1, but they really didn't become popular until CSS 2
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.
Behold the result:
This has the bonus of being a very nice demonstration of nesting.
Type, class, and id selectors are far and away the most common selectors, and the universal selector gets quite a bit of use as well. You can create quite a good style sheet using just these. But the following selectors, although they are less common, may suit your purposes well. But be warned: they aren't supported by all browsers.
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 type of selector 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 properly view a page styled using these selectors.
The syntax for attribute selectors is a little more complex than what we've seen so far. To begin with, an attribute selector be contained within square brackets, like this:
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 (X)HTML.
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:
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.
What if I don't want English phrases to be in italics, because English is not (to me) a foreign language? In other words, 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):
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.
This means that every element that has a lang attribute with the exact value of en
will be displayed normally.
There are variations of this, all depending on what symbol accompanies the equal sign. The first three were introduced in CSS 2, the rest in CSS 3.
Example: [lang="en"]
The lang attribute has a value of exactly en
.
Example: [lang|="en"]
The value en
begins a hyphen-separated list of values or is on its own. This allows for values of en-CA
, en-UK
, or en-US
(Canadian, British, or American English, respectively) as well as en
alone.
Example: [lang~="en"]
The value en
is one of a space-separated 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.
Example: [lang^="en"]
The lang attribute begins with the text en
. This selector would match something like lang="english", but not lang="fr en de".
Example: [lang$="ca"]
The href attribute ends with the text ca
. For example, it would match lang="en-ca" but not lang="en-ca en-uk" .
Example: [lang*="en-ca"]
The href attribute has the text en-ca
somewhere in it. This would match lang="en=uk en-ca en-bb"
Pseudo-classes select elements according to characteristics that are not specified in their attributes, element name, or their ancestor elements (I'll get to that last bit later on in the chapter). The three exceptions are marked with asterisks. Pseudoclass names are preceded by a colon (:
). The pseudo-classes are:
CSS 3 was made a recommendation only in 2011, so not all browsers will support it.
There are two pseudo-classes that are exclusively for hyperlinks: :link and :visited. Along with active are the oldest pseudo-classes, debuting in CSS 1. These two pseudo-classes allow you to control the appearance of hyperlinks, both unclicked (through :link) and clicked (through :visited).
I give these rather short shrift because, if you've been to any websites where links are different colours depending on whether or not you've been to the pages they point to, you know the effects already. I will, however, make a note on the order these pseudoclasses should be in for them to have the proper effect:
*I cover this in Dynamic Pseudo-Classes
below.
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.
activebetween 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 means is that the form element has been selected to accept input.a element) and the colour or something like that changes? This is the pseudo-class that allows you to do that.The pseudo-classes introduced in CSS 3 are for the form interface elements: input, button, select and textarea. I describe these in greater detail in Forms
:enabled) or not (:disabled).These pseudoclasses select elements according to which child of the parent element they are. There are ten such selectors and two that fit the group in other ways. They are:
The :first-child pseudoclass, the oldest (introduced in CSS 2) and thus most common child pseudoclass, 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 apply to neither the body nor html element. The body element is not the first child of the html element (that's head, which does not appear on the webpage and thus gets no styling) and the html element (the root element) is not 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.
The result is:
The rest were introduced in CSS 3, and are not supported by a majority of browsers yet. Use of them may result in browser misinterpretations resulting in strange styling behavior (:only-child, I am looking at you).
html element. With other XML languages, however, this may come in useful if it's not clear what the root element might be.:first-child, :only-child and :last-child pseudoclasses, but they select elements of a specific type—for example, if one used p:first-of-type, it would select the first p element, regardless of whether any other elements preceded it.The rest I explain below.
Four child-pseudoclasses allow you to select either a child other than the first or last of the parent element, or select elements in a pattern. These are:
What goes between the parentheses is either a number (to choose a specific child element) or a mathematical equation. The number is simple— 1
would select the first child element, the first child of its type, the last child, or the last of its type, depending on which of these pseudoclasses you used—in other words, they would be the equivalent of first-child, first-of-type, last-child, and last-of-type respectively. If you used the number 2
, it would get the second child element, the second of its type, the second-to-last element or the next-to-last of its type—assuming that those elements were there, of course.
An equation is a bit more complex: it takes the form of an±b. In that equation, n
must remain n
, otherwise the equation won't work (I checked). Therefore, the two real variables here are a and b.
In the equation, a multiplies n. If a = 2, then every second child element (or child of its type) will be selected. If a = 3, then every third will be selected. If a = 1, you may as well omit a.
The variable b is added to or subtracted from an. If a = 1 (or is absent, which amounts to the same thing), b will have no effect if it is subtracted or adds only 1 to n (of course, if b = 0, it won't have any effect at all). If it adds two to an, then the first, first of its type, last, or last of its type (depending on which pseudo-class you're using) will be skipped; if b = 3, then the two first or two last will be skipped, and so on. The other way b can be used with an is to use the equation to set up a pattern: a to set the pattern's length (say every eight elements), b to decide where in that pattern a rule applies.
Below is a stylesheet using such selectors and a list that it styles.
ul>li>:nth-child(8n+1)</li>li>:nth-child(8n+2)</li>li>:nth-child(8n+3)</li>li>:nth-child(8n+4)</li>li>:nth-child(8n+5)</li>li>:nth-child(8n+6)</li>li>:nth-child(8n+7)</li>li>:nth-child(8n+8)</li>li>:nth-child(8n+1)</li>li>:nth-child(8n+2)</li>li>:nth-child(8n+3)</li>li>:nth-child(8n+4)</li>li>:nth-child(8n+5)</li>li>:nth-child(8n+6)</li>li>:nth-child(8n+7)</li>li>:nth-child(8n+8)</li>ul>The rather colourful result:
And yes, :nth-child(8n+2) does indeed apply to the body element as well; being the second child element of the html element, it gets a white background and black text. I deliberately arranged the pattern that way to keep the page from looking hideous.
Olive background. Ick.
This is the only pseudo-class that's actually based on an attribute—specifically, the lang attribute. This works much like the selector [lang] and its variants, but also selects the child elements of a the matching element as well.
This pseudo-class is a bit more complicated because it takes the following form:
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 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):
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.
Before CSS 3, if we needed to exclude certain elements based on their attributes, names, etc., we would have to write a general rule including all elements based on its class, identity, attribute or name, then a more specific one based on whatever the element was/wasn't supposed to have. For example, if I wanted to select turn all p elements without the attribute class attribute red, I would have to turn all p elements red, then code the exceptions. It was a very simple process—not!
Okay, I understand that usage of not
is almost 20 years old, but it seemed appropriate here.
This pseudoclass works on negation; it selects elements that don't have whatever is specified between the parentheses. Below is the selector that selects all elements that don't have the class attribute:
:not() Pseudoclass SelectorSince this was introduced in CSS 3, all browsers, even text-only browsers, support this pseudoclass—not.
While pseudo-classes control elements according to characteristics other than attributes, type, and ancestry, pseudo-elements tell a browser to select elements that don't exist—basically, they're added in by the stylesheet. The pseudo-elements are:
Two things to remember: First, these not universal to all modern browsers. Second, CSS 2 requires that the pseudo-element names be preceded with a single colon (:
), CSS 3 says they should be preceded by a double colon (::
). Browsers are more likely to support the single colon.
It is impossible to use (X)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 (X)HTML, this rule saves you some coding.
Below is a webpage that uses both pseudo-elements in its style sheet.
Below is the result:
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:
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 elements with "foreign" ClassDo 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:
class1and
class2
.class1.class2p and belong to class class1
p.class1ul and have the ID Navigation
ul#NavigationNavigation. And, if used in an internal stylesheet, specifying the element type would indeed be redundant. But recall that the ID
Navigationmust 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
Navigationas 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).q, have the class whisper, and a
lang attributeq.whisper[lang]lang attribute and may be of any language except English*.[lang]:not([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.
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.
For example, a selector could specify span elements that are descendants of h2 elements. Below is the selector:
span Elements With h2 AncestorsThe 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. The following selector is technically valid CSS, but is unlikely to select anything in a valid (X)HTML document.
h2 Elements With span AncestorsIf the above selector does match something, it means you've nested an h2 element within a span element, which you're not supposed to do, or you're abusing the del and/or ins elements.
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 is universal to all browsers.
What if you wanted to specify only span elements that had not just h2 ancestors, but h2 parents? A special symbol comes into play: >
.
span Elements With h2 ParentsAs 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 is not universal to all browsers.
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
p With Immediately Preceding h6 SiblingIn 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 would not come into effect.
CSS 3 introduced the ability to select an element by a preceding sibling that was not adjacent. The symbol for this is ~
.
p With Preceding h6 SiblingIn this case, if there was a div element between an h6 element and the next p element, the rule would come into effect.
These are 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.
Pictured below is the result:
The example back in Block Elements, which showed p elements nested within del and ins elements can be simplified by these simple rules:
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:
The result is identical to the example in Block Elements:
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.
For example, in the stylesheet for this book, the first letter of the first paragraph of the chapter is large, and the text of the first paragraph flowed around it. But I didn't want the content of any following elements to be affected by it. So how do I select the next element?
This means Start with a
div element with the class value of chap_intro
, then find a child element that is a p element and the first child, then find the following sibling of that p element, whatsoever that sibling element might be.
div elementclass value of chap_intro,
p elementp element,If you've been using the JavaScript tools that I told you about back in the Prologue, you're likely to have seen some fairly complicated selectors. With what you've read in this chapter, you can now follow them and see just how those selectors work to pick out a specific element.
Tables are handled strangely in HTML: Browsers assume that every table element has a tbody element nested within, and all tr elements are children of tbody unless they are explicitely nested within thead or tfoot. This has far more effect on scripting, which is why I mention it again in The Document Object Model and DOM Manipulation. I explain why things are this way in Coding Shortcuts And Other Things.
XHTML—when read as an XML-based language—does not have this quirk. As with any element in an XML document, if the tags aren't there, neither is the element.
As 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:
To save space and typing, you could also rewrite the above in this fashion:
You can join any number and any kind of selectors in this manner (my custom pagination stylesheet has a rule with no less than 257 selectors). Below is the result of adding an internal stylesheet with the above rule to the header elements example from Common Block Elements.
Just a few more things you should know.
One: while selecting elements solely by their name, class, ID, or attributes causes the top-to-bottom hierarchy of a stylesheet to be 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.
Two: The not() pseudo-class can only handle simple selectors (that is, only a single attribute, class name, identity, etc). Each new exception will need another not()pseudo-class appended to it. For example, if you wanted to select p elements with neither class or title attributes, you would have to write out p:not([class]):not([title]) as the selector. Unfortunately, this does mean you cannot exclude elements by nesting.
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.