CSS Selectors!

Delegating and Refining.

Introduction

So far we have used a very basic CSS selector. We have referred to HTML items directly. That is only the beginning however. Selectors can actually get quite complex in terms of how we define which content will get which rules applied to it. In this section we won't cover all selectors (that would be way too long and confusing). Instead we'll cover some of the more useful selectors and create a base from which you should easily be able to explore and learn the others.

This section is quite large but most of it is pretty easy to take in and not too difficult to apply. To begin with, understanding the first few selectors (types, id's and classes) will be adequate for most cases but you should be aware of the others so you can come back and expand your knowledge when you encounter scenarios which could take advantage of them.

So What is a Selector?

We saw in an earlier section that the basic layout of CSS rules is as follows:

selector {
property: value;
property: value;
}

The selector tells us which items in the HTML the properties should be changed for. The properties may be applied to a single item in the HTML, or to several.

Type Selectors

The type selector is the most basic selector. It is the name of a HTML tag. When we use this selector, every item in the HTML which is defined by that tag will have the given properties applied to it.

style.css

  1. h1 {
  2. font-family: Times New Roman;
  3. }
  4. p {
  5. font-family: Verdana;
  6. }

our_page.html

  1. <body>
  2. <h1>Where are average things built?</h1>
  3. <p>In the satisfactory.</p>
  4. </body>
Type Selectors

Where are average things built?

In the satisfactory.

Id's and Classes

Often, we would like finer grained control over where our CSS rules will be applied. An effective way to achieve this is by way of id's and classes. We apply both of these to the HTML as attributes on tags. The examples below will make it clearer.

Id's

An id is used to identify a single item in the HTML. To do so we add an attribute to the relevant HTML tag as follows;

<tagName id="idName">

Then in the CSS our selector becomes a hash symbol ( # ) followed by the idName like so:

#idName {
property: value;
property: value;
}

The id may be named with letters, digits, underscores and dashes. It is best to name it as something descriptive so you can easily identify what it represents. You may have as many different id's on a page as you like. You may apply an id to any tag on the page.

style.css

  1. #topmenu {
  2. background-color: #cccccc;
  3. }

our_page.html

  1. <body>
  2. <div id="topmenu" >Page1 | Page2 | Page 3</div>
  3. <p>Page content goes here.</p>
  4. </body>
Id Selectors
Page1 | Page2 | Page 3

Page content goes here.

A common mistake is to misplace the # symbol. Remember, you don't use the # in the id attribute within the tag, but you do use it for the selector in the CSS.

Id's are good for identifying items which should appear only once on a page such as a menu, or a page heading or footer etc. They are also used a lot with Javascript but that is another subject.

Technically, there should be a single instance of each id on each page. That is, it is ok to use an id on multiple pages, as long as it is used only once on each page. Most browsers will happily let you break this rule but you will find that it will get you into trouble later on if you start adding Javascript to the page. If you need to apply properties to multiple items then you should use a class which is discussed next.

Classes

A class is similar to an id except it applies to multiple items as opposed to just a single item. To make an item on our page part of a class we add the class attribute to its tag like so:

<tagName class="className">

Then in the CSS our selector becomes a full stop symbol ( . ) followed by the className like so:

.className {
property: value;
property: value;
}

Similar to the id, a class may be named with letters, digits, underscores and dashes. Again, you should name it as something descriptive. You may also have as many different classes on a page as you like.

style.css

  1. .important {
  2. font-weight: bold;
  3. border: 2px #cc2244 solid;
  4. }

our_page.html

  1. <body>
  2. <p class="important">Important: When everything is important, nothing is important.</p>
  3. </body>
Class Selectors

Important: When everything is important, nothing is important.

It is perfectly fine to have a class which only refers to a single item in the HTML. In fact it is better to do this than have it as an id if you anticipate that later on there may be a need to apply it to multiple items. A single class may also be applied to different types of tags on the same page as well.

It is also possible for a HTML item to have multiple classes applied to it:

<tagName class="className1 className2 classname3">

Or both an id and class/classes

<tagName id="idName" class="className">

A common mistake is to misplace the . symbol. Remember, you don't use the . in the class attribute within the tag, but you do use it for the selector in the CSS.

Classes are good for many different things. For instance, maybe you want to identify particular pieces of content as being important by making them a different colour. The content could be in a heading, or a paragraph, or list etc. Using a class would be a good idea here.

Descendant Elements

With descendant elements we can say that any items within another type of item should get a set of properties applied to them. We do this by writing the parent selector, followed by the child selector like so:

parentSelector childSelector {
property: value;
property: value;
}

Both the parent and child selectors may be either a tag name, id or class.

style.css

  1. .important {
  2. font-weight: bold;
  3. border: 2px #cc2244 solid;
  4. }
  5. .important b {
  6. color: #ff1122;
  7. }

our_page.html

  1. <body>
  2. <p class="important">Important: When everything is <b>important&tl;/b>, nothing is important.</p>
  3. <p>And this is perfectly <b>normal</b>.</p>
  4. </body>
Descendant Selectors

Important: When everything is important, nothing is important.

And this is perfectly normal.

Multiple Selectors

Sometimes you find yourself repeating the same set of properties and values for several different selectors. To make life easier, you can put those properties into their own block and specify that it should apply to multiple selectors at once. To do this, list all the selectors, separated by a comma like so:

selector1, selector2, selector3 {
property: value;
property: value;
}

You may list as many selectors as you like.

Using this approach can be good if you know they are always supposed to be the same. If you need to change a value later on then you may make the change in one place and have it automatically applied to all of them.

Hover

You have most likely seen the hover selector used to make links change when you hover your mouse over them. We identify a set of properties to be applied when the user hovers their mouse over an item by adding the keyword :hover to the end of the selector.

selector1:hover {
property: value;
property: value;
}

The selector may be a type, id orclass and you may apply the hover effect to any item on the page (you are not limited to just links).

style.css

  1. p:hover {
  2. padding-left: 30px;
  3. color: #3366cc;
  4. }

our_page.html

  1. <body>
  2. <p>Hover over me. I dare you!</p>
  3. </body>
Hover Effects

Hover over me. I dare you!

With a bit of creativity you can create some really interesting effects using hover.

Pseudo Elements

Pseudo Elements are not specific items on the page but virtual items you may target.

First Line

It is possible to change the first line of content for an item using the ::first-line keyword (Note: 2 colons as opposed to 1 for hover).

selector1::first-line {
property: value;
property: value;
}

Not all properties work within this selector for various reasons.

First Letter

As well as the first line, we may also target the first letter. This is done using the ::first-letter keyword.

selector1::first-letter {
property: value;
property: value;
}

Similar to ::first-line, not all properties work within this selector.

Before and After

The ::before and ::after keywords tell the browser to insert a pseudo element on your page before or after the item identified by the selector.

selector1::before {
content: value;
property: value;
property: value;
}

When using these, we include the property content which sets what the content of this pseudo element should be. The value could be a string:

content: "some text";

Or it could be an image:

content: url(/path/to/image.jpg);

Or it could be a counter:

content: counter(li);

Note: The content is rendered exactly as is. HTML will not be rendered.

style.css

  1. #topmenu a::before {
  2. content: ' | ';
  3. padding-left: 10px;
  4. padding-right: 10px;
  5. }

our_page.html

  1. <body>
  2. <p id="topmenu"> <a>Page1</a> <a>Page2</a> <a>Page3</a> </p>
  3. </body>
Before

Page 1 Page 2 Page 3

In the right scenarios, and with a bit of creativity, these can be put to good effect.

Overlapping Rules

With all these different selectors at your disposal, it is quite possible that a particular item in your HTML will have multiple selectors applied to it and that within those selectors there may be clashes in terms of properties. How the browser determines which property values actually get applied can be a bit tricky and involves specificity, inheritance and cascading.

Specificity is the most important to understand and has to do with how directly the selector relates to the item. In general, from least direct, to most direct, they are:

  • type
  • class
  • id

It can get more complex once descendants and other mixes come into play.

Find out more about CSS Precedence Rules.

Let's have a look at an example with the colour property.

style.css

  1. p {
  2. color: #3366cc;
  3. }
  4. .whatcolor {
  5. color: #66cc33;
  6. }
  7. #whatcolor {
  8. color: #cc6633;
  9. }

our_page.html

  1. <body>
  2. <p class="whatcolor" id="whatcolor">What colour am I?</p>
  3. </body>
Overlapping Rules

What colour am I?

Best Practice

With several different selectors and an almost endless combination of ways they can be combined and applied it may seem like a daunting task to work out how best to structure your code. Working out the best way to do things should come naturally with time and experience as long as you are experimenting and thinking about this as you go. Don't worry if your first attempts seem clunky and inefficient. Also, don't be afraid to rework your code when you get stuck.

I can't really tell you how best to organise your code as every page will be unique in terms of the content on it and how it may grow over time. Here are some general concepts you should consider however.

  • Removing duplication is always a good thing.
  • Descendant elements are a good way to avoid having to add classes to many items within your HTML

What we are aiming for is the ideal balance which gives you the best separation of content (HTML) from style (CSS). You could, for example, make many classes which are quite specific in your CSS to avoid duplicating properties many times. This may look good from the point of view of having clean and efficient CSS but then your HTML will require many classes applied to many items and so we have lost that separation. Getting the right balance is something you will work out for yourself over time with experience.

Different patterns of selectors are also more efficient than others from the point of view of work that needs to be done for the browser to render the content but at this stage I wouldn't worry too much about that. Until your content reaches a certain size and complexity the performance hit isn't anything to get excited over.

If you are interested though, you can find out more about CSS performance.

Summary

type selector
Set properties on items by their HTML tag.
#idName
Set properties on a single item on your page.
.className
Set properties on several items on your page.
selector1 selector2
Set properties on all items matching selector2 which are a descendant of items identified by selector1.
:hover
These properties get applied when you hover your mouse over the item.
::first-line ::first-letter ::before ::after
Set properties on various pseudo items on your page.
Cleanliness
With a well thought out structure you will get a good separation of content (HTML) from your style (CSS).
Precedence
Properties can clash and when they do precedence determines which values will be applied.

Activities

Now we are getting to a point where we can start to have some real fun with our content.

  • Apply some CSS to your page using the basic selectors (type, id and class).
  • Now play about with the :hover keyword. Add some hover effects to headings, paragraphs, maybe a row in a table.
  • Create two classes (.external and .internal) and add the pseudo class ::after to them so that you can make it easy for visitors to your page to identify between internal and external links.
  • Create an item in your HTML which has multiple CSS selectors applied to it (eg. type, desdendant element, id and class). Now put a property to change it's text colour on different combinations of the selectors and experiment to get a feel for how precedence get's applied.

  • Challenge: This one is a bit harder. Create a page with a series of paragraphs. When you hover over each paragraph a number will show up next to it telling you which number paragraph it is on the page. Also, hide some codewords in one of the paragraphs which only stand out when you hover on the paragraph.