When we introduced CSS rules, we described the generic form of a rule as in Figure 1. At the head of the rule is the selector, followed by a series of property and values pairs enclosed in curly braces.
Today's focus is on the selector. The selector indicates which element(s) the rule will apply to. So far, we have only seen a tag as the selector, so a rule would style all paragraphs (P elements), or all EM elements, or whatever elements correspond to that tag. In this reading, we will expand the set of selectors.
selector
Back in the reading on URLs, we learned about giving an element an ID (short for identifier, like a driver's license is a kind of ID card). Because an ID is unique on a web page, it can be the target of a hyperlink. For example, the title of this section (see the H2 element just before this paragraph) has an ID of css_and_id, and so the relative URL for this section is css-selectors.html#css_and_id. (Try it!).
ID card
css_and_id
css-selectors.html#css_and_id
In addition, an ID can be used as the selector in a CSS rule. Thus, the following rule was used to make that H2 section header teal:
#css_and_id { color: teal; }
Notice the syntax here: the ID is preceded by a # symbol (pronounced hash, or sharp sign, or pound sign, depending on your awareness of twitter, your musical training and your age).
#
hash,
sharp sign,
pound sign
The ID selector picks out the element with that ID, and only that element, to apply the style to. But what about the rule that sets all the H2 elements to light blue, namely this following? (Later, we'll learn about the #2EA9D3 code, but for now, trust us that it means light blue)
#2EA9D3
h2 { color: #2EA9D3; }
The conflict is resolved by using the more specific rule, which is the one with the ID. You're probably not surprised at that.
One drawback of using an ID is that an ID is unique, so you can only style one element using an ID. Suppose we have various elements on our page that are important, and we want to style them differently from non-important elements. We could number them important1, important2, and so on, but that would be unbearably tedious. Instead, we want to describe a kind or category of element, which CSS calls a class of element.
important1
important2
An example will help. Suppose we have a grocery list. We're actually out of some critical items, so those have been given the class important:
important
Here's the source code:
<ul> <li class="important">milk <li class="important">bread <li>apples <li>bananas <li class="important">toilet paper <li>soap </ul>
You can see that class works just like ID, in that you specify it as the value of an HTML attribute. Note that, just like ID, you as the author of the web page get to decide what the ID or class is. If you want to label them critical, or crit or whatever, that's your choice.
critical
crit
Now let's turn to the CSS side of things. The important items in the list above got styled using bold red using a CSS rule like this:
.important { color: red; font-weight: bold; }
First, note the syntax of the selector. The name of the class is preceded by a dot or a period (a full stop if you're British). Otherwise, it works just like an ID: all the elements with that class get that style rule applied.
full stop
In this discussion of ID and class, we can see the concepts of abstraction and modularity that we will return to many times in this course. First of all, the ID and class allows us to separate the structure and semantics of the page (which belong to HTML) from the presentation or style of the page (which belong to CSS). Separating different aspects is part of modularity. The name that we choose for the ID or class provides the semantic label, and the CSS rule then applies some style to those labelled element(s).
A related aspect of this modularity is how to choose the names. Suppose that instead of choosing important as the class name, we had chosen bold_red. It's about the same amount of typing, and it's much clearer as to what the class name does, right? However, trouble arises when we change the site. Suppose have a big website, with hundreds of pages and thousands of elements labeled important. Cleverly, you have one external CSS file that every page uses, so the CSS rule is just in one place, like this:
bold_red
.boldred { color: red; font-weight: bold; }
One day, the boss comes in and says I'm tired of the bold red; it's too scary. Change them all to medium maroon. You change the rule as follows:
I'm tired of the bold red; it's too scary. Change them all to medium maroon.
.boldred { color: maroon; font-weight: medium; }
However, you now have a website where class="boldred" changes the contents to medium maroon. At best, that's confusing and misleading.
class="boldred"
The better approach is to name things by what they mean rather than by what they do. That's the power of abstraction. It's not always possible to come up with a good name, but it's worth trying to. You can read more about good class names.
Students often wonder about what the difference is between a class and an id, and when to use each one. The key is uniqueness: an id must be unique, while a class describes a kind/type/category of element.
For example, there might be many occurrences of these classes of elements:
On the other hand, there is probably only one of the following elements per page, so these might have an id.
With ID and class as tools, we can create as many hooks for styling as we want. In principle, every single element could have its own ID, and we could give it a custom style. However, that would be tedious and confusing. There's a better way, which we turn to now.
hooks
A descendant selector creates a style rule where the elements are chosen based on where they are in the hierarchy of the page. Remember that an HTML document can be modeled as a tree. At the root is the <html> element, with all other elements as descendants, grouped in different families. Chrome's Inspect Element gives a very good depiction of the tree corresponding to the document.
<html>
Let's start with a motivating example. By default, hyperlinks are blue and underlined. That might be what you want for most of your page, but in the nav bar you want them to be, say, green and not underlined. Here's one way:
<nav> <ul> <li><a class="navlink" href="home.html">Home</a> <li><a class="navlink" href="about.html">About Us</a> <li><a class="navlink" href="contact.html">Contact Info</a> </ul> </nav>
You can combine that with the following CSS rule:
.navlink { text-decoration: none; color: green; background-color: gray; }
That's not too bad, but supposing that you also want to adjust other elements inside the NAV (say removing the bullets from the UL), you'd have to add more IDs and classes. You can see that this is tedious and annoying. You really want to say stuff inside the NAV is styled differently. For that, we can use descendant selectors, meaning that all descendants of an element are selected. (The UL is a child of the NAV, the LI elements are grandchildren, and the A elements are great-grandchildren.) Here's an example:
stuff inside the NAV is styled differently.
nav ul { list-style-type: none; } nav a { text-decoration: none; color: green; background-color: gray; }
With a descendant selector, you give two selectors. The first is the ancestor and the second is the descendant. If you have A B, it means all elements that match B that are also descendants of elements that match A. (This can be generalized to three or more selectors, but that's uncommon.)
A B
B
A
In the example above, we used two tags as the selectors, NAV UL and NAV A, but the selectors don't have to be tags. Either selector could be any one of the three basic selectors we know: (1) tags, (2) ID, and (3) class. For example:
NAV UL
NAV A
#banner H1 { font-size: xx-large; /* banner header is huge */ } #copyright em { font-style: normal; /* italic looks weird in tiny font */ } .appendix h2 { color: blue; /* make headers in appendices look different */ } .appendix .important { color: black; /* since it's in an appendix, don't use red */ }
In practice, you wouldn't use an ID as the second selector, since an ID is already unique and doesn't gain any specificity by adding an ancestor.
To use descendant selectors effectively, it's important to keep the tree in your mind. Here is a graphic of a tree from an example you've seen before: Figure 2: Depiction of a Tree
Since the ancestry of an element is important with descendant selectors, debugging can require being able to easily see the ancestry of a particular element. Figure 3 shows the path of elements in which our a element is nested, as displayed by Chrome's Inspect Element window. This is an absolute path, starting from the root, html. When we specify the selector, we can use only parts of such a path, such as nav ul li a, or simply nav a.
a
html
nav ul li a
nav a
There is one more kind of selector that will be important in this class, namely pseudo-selectors. We will look at how to format hyperlinks. As you know, hyperlinks are blue by default, but only when they haven't been visited. Once you've visited them, they turn purple (by default). You can control the style of both kind of link using CSS. You can also control what they look like when you hover over them, and in the moment of clicking on them. There are names for these four states:
a:link
a:visited
a:hover
a:active
Here's an example of some CSS to style all four states:
#hyperlink-example a:link { color: orange; } #hyperlink-example a:visited { color: red; } #hyperlink-example a:hover { border: 1px solid blue; font-size: 2em; } #hyperlink-example a:active { border: 2px solid red; font-size: 2em; font-weight: bold; }
Here's the example in action:
Note that there are ordering constraints among these pseudo-selector rules; we recommend specifying them in the order used above. You don't have to specify all of them (:active, for example, is pretty rare, and with touch screen devices, :hover is useless).
:active
:hover
You can learn more and play with the specifications using this page: W3 Schools CSS Links.
Note that if you don't care about the state of the link, you can specify the appearance just using the A tag:
#hyperlink-stateless a { color: green; }
Here's the stateless example in action:
Let's summarize the kinds of selectors that we've learned:
p
em
li
.important
class=classname
h2.important
#main
id=idName
To better understand the different kinds of CSS selectors, refer to the code examples in W3Schools CSS Selectors' page.
There are many more esoteric selectors, and you're welcome to learn them. The following material is optional, and you can stop here. Read on if you're curious.
If you have a rule that you want to apply to several things, rather than copy/paste the rule (copy/paste is always bad for modularity), you can share the rule. Suppose you have three elements on the page with IDs of harry, ron, and hermione. If they all have different colors, but the same font, you could do:
harry
ron
hermione
#harry { color: red; } #ron { color: green; } #hermione { color: blue; } #harry, #ron, #hermione { font-family: impact; }
You can see that there's just one rule to specify the font family for all three. All you have to do is list all the selectors, separated by commas. The selectors can be tags, classes, ids, even descendant selectors, in any order.
Pseudo-selectors come in two flavors: pseudo-classes and pseudo-elements.
:visited
:checked
:disabled
:first-child
:nth-child(odd)
:nth-of-type(n)
:not
:first-line
:first-letter
In CSS3, to differentitate between pseudo-classes and pseudo-elements, the syntax to refer to them has changed. An element is referred with a double colon. You will see both examples on the Web, because they are still supported by browsers. Two new pseudo-elements that are also interesting are ::before and ::after which can be used to add content before or after an element. These are used when one wants to add icons in front or after certain elements, see example.
::before
::after