By now, you probably know that you use CSS styles to alter the look of your HTML document. The way CSS bobs and weaves through your document to style the right elements is both fascinating as well as useful for you to understand if you want to create great looking applications and web sites.
In this tutorial, you will learn how common CSS selectors work to map a particular rule to elements in your document. We will start off by deconstructing and understanding very simple examples and then moving to more complicated examples that you will encounter...in the wild!
If any of the CSS terminology such as selectors and rules is unfamiliar to you, check out the Anatomy of a CSS Style 101 article for a quick introduction.
Let's first start by looking at a simple rule whose selector applies to all p tags:
What this means is that if any p tags are encountered in your HTML document, this rule will get applied. For example, the following text will fall under the influence of this rule:
As you can see, this truly is simple. Because your browser sees a match between the p selector in the style rule and the p tag in your document, it applies this style to that element. This type of a selector is known as a type selector because it applies to elements whose types match what it specifies.
Let's say your document had many p tags with some p tags nested inside other elements:
The rule you defined earlier will apply to every instance of the p tag in the document. The reason is because the selector isn't very specific on which types of p tags to apply the rule to. To describe this situation more formally, this particular selector is said to lack specificity. It will apply to every p tag without discriminating. We'll see later how to address this.
So far, you've seen selectors that apply only to a particular type of element. For example, regardless of their specificity, the selectors you've encountered so far apply their rules only to the p element. While type selectors that only apply to a particular type of element is useful, for many types of visual changes you want to make, you want to use selectors that can be applied broadly to different types of elements.
To help you accomplish this, you have class-based selectors and ID based selectors. Let's look at them now.
Let's say you want to assign a blue background color to a variety of elements in your document. As mentioned earlier, the type selector syntax will not work well because we are no longer selecting by type. The selection will be based entirely on which elements you designate as worthy of having a rule applied, and these elements could each have a different type.
This is where the class selector comes in. Let's look at an example:
We have a rule that sets the background color to a shade of blue, but take a look at the selector. The selector isn't named after an HTML element, but instead is something custom that I decided to name - coolBackground. Note the period in front of the class selector name. That is important when declaring your selector.
Another change is how this rule gets applied. If I wanted to apply this rule to an element, I will have to explicitly add it:
If I don't specify the class attribute on the div element with this selector's name (coolBackground), then this rule will never apply. When specifying the selector name as the class attribute's value, notice the period is not there. The period needs to be there when declaring your selector, but it does not need to be there when using it on the element you wish to apply the rule to. (Say that last sentence three times fast!)
In your document, you may have elements that are uniquely named by having their ID attribute set:
In the above example, the div element has an ID value of spaceship. If you want to apply a style just to this particular element, you can use an ID selector that looks as follows:
Notice that the selector's value is #spaceship. The hashtag (#) is important because it designates the selector as an ID based selector, and the value that follows it specifies the ID of the element you wish to apply this rule to.
You may be wondering why you would use an ID selector as opposed to a class based one. For the most part, I don't really have a good answer. Class based selectors are more flexible because you can apply the rule to many elements. Because a document can only have one element with a particular ID, any rule with an ID selector will apply only once. Depending on how your document is structured, just pick one and run with it.
Your selectors do not have to consist of single HTML types, class names, or ID values. You can string together combinations of selectors to constrain the range of elements your selectors can apply a rule to.
Let's look at an example where your HTML looks as follows:
What we want to do is only apply some styles to the p tags (highlighted in green) that are descendants of the mainHeading div tag. The p tag that is outside of the mainHeading div tag (highlighted in orange) should remain unaffected.
The rule we had towards the beginning of this article will not work:
Like you saw earlier, the selector for this rule doesn't discriminate - it just applies the rule to any and all p tags it encounters in the document. To constrain the elements your selector applies to, you can nest additional selectors to an existing selector.
Because the p tags we want to affect live inside a div tag, we can modify our selector as such:
Notice that our selector now specifies that this rule applies anywhere in your document only when a p tag is a descendant of a div tag. Any ordinary p tags will no longer get to bask in the awesomeness this rule provides.
One thing to keep in mind about nested selectors is that, just because your selector says div p, it does not mean that this rule applies only to an element p that is a direct child of the div. Your div can have many levels of of children under it before a p element is encountered, but as long as p falls under the path of the div (aka a descendant), you are all good.
Below is an example of this:
Notice in this example that the second p element is actually under a list item inside an unordered list. Despite its distance from the div element, because this p tag is still a descendant, the style rule still applies.
Let's go a bit further. Let's say that constraining your styles to p tags that are descendants of a div element is still too freewheeling. Instead, you want to apply your style to p tags that are descendants of the div whose ID is mainHeading.
In this case, taking the same HTML snippet you saw a few seconds ago, you don't have to do anything too different to what your selector looks like. Instead of your selector being div p, you simply use #mainHeading p instead:
You can mix and match selector types to help pinpoint the range of elements you want to affect! Think of matching all of the CSS rules to elements in your document as nothing more than a giant game of pattern matching!
This section is entirely optional, but because nesting selectors and pattern matching takes some getting used to, let's look at another example to help bake it all in.
In this example, your document looks as follows:
You have three nested divs, and at the very bottom of those divs is a p tag containing some text. As you can guess, we want to style only this p tag, and we must only do this through CSS. In other words, you can't modify your HTML and give your p tag a unique ID and take care of it easily with a single ID selector. There are several ways of accomplishing this, and we'll explore a few of those ways.
Using just type selectors, one approach may be to do the following:
The only p tags that will be accepted are ones that are desecendants of at least two divs. This eliminates the first p tag because it is the descendant of only a single div, but the p tag we are interested in gets hit. The reason is that our p tag with the class name awesome is the descendant of three div elements!
Another approach you can take can be:
This rule will apply to any p tags that are a descendant of an element whose ID is spaceship. This means our p tag will be affected by this style because it is a direct child of a div whose ID is spaceship.
The last example we will see is one where you combine both the ID and class-based selector into your rule:
In this case, any element whose class value is awesome that is also a descendant of an element whose ID value is spaceship will fall under the umbrella of this rule.
We won't look at any more examples, but what you have seen so far should give you a good taste of how to specifically pinpoint an element or a set of elements for applying a style to. As long as you have a good visualization of the DOM / hierarchy of the elements you wish to style, constructing an appropriate selector with the right specificity will become very easy after a few tries!
Well, that's all there is to understanding how to use type, class, and ID selectors. Armed with these three weapons, you can take on pretty much any army of HTML-based orcs and trolls as you fight your way through Lordaeron. Yes, I need a vacation.
Got a question or just want to chat? Comment below or drop by our forums (they are actually the same thing!) where a bunch of the friendliest people you'll ever run into will be happy to help you out!
Get cool tips, tricks, selfies, and more...personally hand-delivered to your inbox!
( View past issues for an idea of what you've been missing out on all this time! )