ABSTRACT
We’ve learned to use what I call “specificity level 1” and “specificity level 2” rules to affect our markup, but we are just scratching the surface. Before we get into using multiple levels and classes, I want to go over using classes and IDs (which are always single). We’ll cover classes in this section.
REFERENCING CLASSES
Classes are referenced in CSS by preceding the name of the class with a period, like so:
.overall_body_class { border:1px solid yellow; color:red; }
You can increase the specificity of the class reference by preceding the period with the type of element to which the class is assigned. Assigning the same class name to a different kind of element will not apply this rule to the element. You need to define a separate rule for that element type.
body.overall_body_class { border:1px solid yellow; color:red; }
This assignment uses the same class name, but only applies to <div> elements:
div.overall_body_class { border:1px solid purple; color:red; }
Review
First, let’s review our markup. This is the structure we have to work with. We won’t be changing the stuff in the <body> element. We’ll be messing with the presentation, which will take the form of a <style> element directly embedded in the <head> section of the file:
<html> <head> <title>Example 24</title> <style type="text/css"> body { border:1px solid yellow; color:red } div { border:1px solid red } p { border:1px solid green; font-style:italic } </style> </head> <body id="mr_boddy" class="overall_body_class"> <div class="container_class" id="main_container"> This text is in the main, outer container. <div class="secondary_container_class" id="secondary_container"> This text is in one level. <p class="tertiary_container_class" id="tertiary_container"> This text is in two levels. </p> </div> <div class="secondary_container_class secondary_container_class_2" id="secondary_container_2"> This text is in one level, but via a second container. <p class="another_container_class" id="another_container"> This text is in two levels. </p> </div> <p class="inside_container_class" id="yet_another_container"> This text is in one level, but via a third container. </p> </div> <p class="outside_container_class" id="yet_another_silly_container"> This text is in a second, outer container. </p> </body> <html>
Rules vs. Properties
Before we continue, I want to mention the difference between where specificity is defined, and where it is implemented.
Specificity is defined in the rule selector:
<style type="text/css"> body { border:1px solid yellow; color:red } div { border:1px solid red } p { border:1px solid green; font-style:italic } </style>
However, it is implemented in the rule properties:
<style type="text/css"> body { border:1px solid yellow; color:red } div { border:1px solid red } p { border:1px solid green; font-style:italic } </style>
This may sound like an odd distinction to make, but humor me for a second. It means that you don’t say that “The divs have a specificity of 2.” Rather, you say that “The divs’ red border has a specificity of 2, and their red text has a specificity of 1 (because it is inherited from the rule applied to its parent container).” You need to look at each property applied to a markup element as having its own origin and its own specificity. The actual properties that affect any given element can come from a number of places, and can have varying levels of specificity.
Using Classes (Specificity Level 3)
All of the markup elements in example 24 have classes assigned to them. This is done by specifying a class attribute:
<div class="secondary_container_class" id="secondary_container">
You can assign the same class to multiple elements. In fact, that’s the best way to use classes. By assigning a class to an element, you can “tack on” a number of style properties.
Class assignments also have a higher specificity than general or inherited properties. Let’s revisit the original example I outlined previously:
<style type="text/css"> p { text-indent:1em } p.first { text-indent:0em } </style>
Remember this? The <p> element with an assigned class (“first”) gets its “text-indent” property assigned from the rule with the higher specificity (“p.first”). Actually, we don’t need to do “p.first”. Just “.first” will do. Adding the “p” actually gives the “first” class a bit of a boost.
It could just as easily be written like so:
<style type="text/css"> p { text-indent:1em } .first { text-indent:0em } </style>
In fact, let’s do that, just to prove it to ourselves:
<html> <head> <title>Example 25</title> <style type="text/css"> p { text-indent:1em } .first { text-indent:0em } </style> </head> <body> <p class="first">This is a first paragraph. It is not indented.</p> <p>This is a normal paragraph, so it is indented</p> </body> </html>
We can also assign multiple classes to an element:
<div class="secondary_container_class secondary_container_class_2" id="secondary_container_2">
Instead of using our rather complex test bed, I’ll modify our simple indented paragraph example to show how this works:
<html> <head> <title>Example 26</title> <style type="text/css"> p { text-indent:1em; font-style:normal } .first { text-indent:0em } .second { font-style:italic } </style> </head> <body> <p class="first second">This is a first paragraph. It is not indented, and it is italicized.</p> <p>This is a normal paragraph, so it is indented and displays normally.</p> </body> </html>
The “first” class removes the indent, and the “second” class italicizes the text. They both override lower-specificity properties.
Now, let’s get a bit more complex, and throw a third class into the mix:
<html> <head> <title>Example 27</title> <style type="text/css"> p { text-indent:1em } .first { text-indent:0em } .second { font-style:italic } .third { font-style:normal } </style> </head> <body> <div class="third"> <p class="first second">This is a first paragraph. It is not indented, and it is italicized.</p> <p>This is a normal paragraph, so it is indented.</p> </div> </body> </html>
I threw in the <div> element because I’m going to use it in some upcoming examples, and I wanted you to get used to seeing it there. I also don’t want you to get complacent. In the World of the Web, we need to learn to be flexible and adapt to changes. The changes will result in no visible changes to the display.
Now, let’s give our first paragraph a conflicting set of classes:
Before you look at the example, try to think about what will happen to the display. The “second” and “third” classes conflict. They have the same specificity, they both apply to the element, and they both affect the same property.
<html> <head> <title>Example 28</title> <style type="text/css"> p { text-indent:1em } .first { text-indent:0em } .second { font-style:italic } .third { font-style:normal } </style> </head> <body> <div class="third"> <p class="first second third">This is a first paragraph. It is not indented, and it is italicized.</p> <p>This is a normal paragraph, so it is indented.</p> </div> </body> </html>
Let’s make one teeny little switch. What do you think will happen now?
<html> <head> <title>Example 28</title> <style type="text/css"> p { text-indent:1em } .first { text-indent:0em } .third { font-style:normal } .second { font-style:italic } </style> </head> <body> <div class="third"> <p class="first second third">This is a first paragraph. It is not indented, and it is italicized.</p> <p>This is a normal paragraph, so it is indented.</p> </div> </body> </html>
Remember what I called “specificity modifiers”? The “third” rule was declared after the “second” rule, but now it’s declared before it. It is now useless in the context of our first paragraph, as “third” is canceled out by “second.” However, it still applies to the <div> element.
Now, the class definitions in the rules are “generic.” They start with a period (“.”), and that means that they can be applied to any type of element. Not all their properties may apply, but the class itself can be applied.
One way we can bring the “third” class back into preeminence is to increase its specificity by just a teeny little bit:
<style type="text/css"> p { text-indent:1em } .first { text-indent:0em } p.third { font-style:normal } .second { font-style:italic } </style>
Adding that “p” means that only <p> elements can have “third” applied to them, and when they do, the specificity will be just a bit higher than a “generic” class.
Now, we’re back to non-italicized text:
To prove that the “third” assignment in the enclosing <div> element is now useless, we’ll make the <body> element have italic text. This specificity would be low enough to be overridden by a class definition in the <div> element, but it doesn’t happen:
<html> <head> <title>Example 31</title> <style type="text/css"> body { font-style:italic } p { text-indent:1em } .first { text-indent:0em } p.third { font-style:normal } .second { font-style:italic } </style> </head> <body> <div class="third"> <p class="first second third">This is a first paragraph. It is not indented, and it is italicized.</p> <p>This is a normal paragraph, so it is indented.</p> </div> </body> </html>
You’ll notice that the second paragraph now displays as italic. That’s because there’s nothing between it and the <body> element to gainsay the italic text style. If the “third” class applied to the <div>, the second paragraph would be displayed with normal text. We’ll specialize the “third” class for <div> elements as well, and you’ll see what I mean:
<html> <head> <title>Example 32</title> <style type="text/css"> body { font-style:italic } p { text-indent:1em } .first { text-indent:0em } p.third,div.third { font-style:normal } .second { font-style:italic } </style> </head> <body> <div class="third"> <p class="first second third">This is a first paragraph. It is not indented, and it is italicized.</p> <p>This is a normal paragraph, so it is indented.</p> </div> </body> </html>
And that should give you a pretty good idea of how to use classes, and some basic tweaks for specificity.
By now, you should be realizing that the Web designers who think they can expect graphic designers to hand them ready-made CSS, as well as graphic layout, are smoking some really primo stuff, and need our help desperately.
CSS design and debugging is hard. Really hard. It can get hairy and complex, and you need to keep track of a dozen balls in the air at once. You need to be able to trace a CSS property all the way back to where it first appeared in your food chain, and then understand how it could be affected on the way to your element.
Next, we’ll look at IDs, which are relatively simple compared to classes.