Hi, I'm Nicholas Johnson!

software engineer / trainer / AI enthusiast

The HTML / CSS Foundation Book

Complete your awesomeness upgrade!

By Nicholas Johnson

Document Version: 2.0.0

Last Updated: 2023-09-09

Workbook Cover Image

Welcome to Web Dev 101!

Hi there!


This document that you have in your hand or on your screen is your key to becoming a new web developer. It’ll be tough, but you’ll pick it up no problem if you keep at it. This course is practical, we will learn by doing, so there are a lot of exercises for you to work through.

This isn’t a tutorial, if you’ve done any tutorials you’ll know it’s pretty hard to learn the fundamentals from them. Instead it’s a set of exercises that starts at the foundations and bulds up, each step on the last.

You’re going to learn from the ground up, skipping nothing, until you have a solid foundation on which to work. Welcome to the secret ways of the Internet!

As a very wise old web developer once said,

“How awesome is working on the web? This Awesome!”

This Awesome!

Technologies you’ll need

The two main technologies we’ll be covering in this book are HTML and CSS.

What is HTML?

HTML is used for defining the CONTENT of a web page. The words you see on the screen, that’s the CONTENT. It’s a markup language, we write a document in words, then we mark up specific parts of that document to make them make sense.

Maybe this bit is a paragraph, maybe this bit is a heading. HTML lets us say what the parts of the page are for.

We use the word SEMANTIC HTML (write that down). The word SEMANTIC means “to do with meaning”, our HTML conveys meaning.

What is CSS?

CSS on the other hand is for defining the APPEARANCE of the page, it’s for STYLING. We can choose a font, colours, line heights, letter spacing. We can do a layout and tell this bet to go on the left and this bit on the right.

We can provide different styling for mobile phones.

And JavaScript?

Good question. We’re not covering JavaScript in this course, but JavaScript is for behaviour. It’s a tidy little scripting language that you will want to look at somewhere down the line.

HTML / CSS / JS sum up

  • HTML - page content, structure and meaning (semantics)
  • CSS - page stying and appearance, including layout and mobile layout
  • JavaScript - page behaviour. Not covered in this course, but you can circle back to this later.

Types of HTML

HTML has had many incarnations over the years. All of these are similar, but successive refinements have been added over time to cope with our evolving understanding of the best way to make a website.

The way they have changed reflects our changing understanding of what web design should be like.

Three types of HTML are in use today. These are:


HTML4 is the oldest type of HTML still in use. You’ll still see it around on junky old websites that haven’t been updated in a while. HTML4 had a loose syntax and was very friendly. You could pretty much do what you wanted and it would have a go. This was nice, but also a problem. Because it wasn’t strict with you, it was easy to make a mistake and not notice.

And so we got XHTML

XHTML stands for eXtensible Hypertext Markup Language. It’s actually a specific dialect of XML which is a generalised markup language. XHTML was the exact opposite of HTML4 and was a reaction to it. It was incredibly strict and would punish you if you made a mistake. If it were a person, it would have a bristly moustache and a clipboard. It’s still in use, although less so now.


And this brings us to HTML5. This is the dialect of HTML we’ll be learning today. It’s the latest specification. It’s a happy balance between strict and loose. It lets you screw up, but not too badly. It will fix your mistakes, but not the big ones. In short, it’s rather nice.

See how this has worked out? In the old days, HTML was super relaxed, not even a language. We didn’t really see ourselves as professionals, and front end development was not seen as real programming.

Later we decided to get serious, so we imported XML and got super militant. It was an overreaction, but it felt right at the time.

Nowadays we’re a bit more relaxed. We’re secure in ourselves. We know that web dev is real software development and we don’t have anything to prove, so we’ve invented this nice, useful markup language that isn’t too strict but still takes things seriously.

Styling with CSS

CSS is the language we use for styling documents. There have been many iterations of this, but the current one is CSS3. CSS stands for Cascading Style Sheets (pretty cool). It lets you select parts of a web page and then add styling overrides to it.

Some people really hate CSS, but I think this is maybe because they never took the time to learn it. CSS is pretty simple, and will make you happy if you study its ways.

Now on the the course!

Marking up a document

HTML is the language that web pages are created in. Rival technologies such as Flash and Shockwave have tried to challenge HTML in the past but none has matched it for simplicity, flexibility and ubiquitousness. Those technologies are all dead now, but HTML still stands.

HTML is a markup language. An ordinary text document is “marked up” using special pairs of tags which tell a piece of software called a web browser how the text should be displayed.

Browsers include Chrome, Firefox, Edge, Brave, Opera, etc. They are just computer programs that read an HTML document and turn it into nicely formatted pixels on the screen.


A paragraph can be created in html by placing a <p> tag at the start of the paragraph, and a matching end `

“ tag at the end of the paragraph. We sometimes talk about “wrapping” text in p tags to create a paragraph.

When text has been wrapped in paragraph tags, we describe that text as a paragraph element. We are then able to apply specific styling to that paragraph element using CSS which we will come to later.

Tags come in pairs

Tags generally come in pairs, a start tag and an end tag. A start tag looks like this: <p>. This tag means start a new paragraph. An end tag looks like this </p>. This tag means end your paragraph.

<p>This is now a paragraph</p>

Tags are placed before and after the text we want to wrap, so if you wanted to make a top level heading you might write <h1>Here is my heading</h1>

Lets make a web page

A web page at root is a simple text document. You can create one in any editor that allows you to write plain text. You might use Notepad, but most of us prefer a programmers text editor like VSCode, which you can download for free from here.

To create your blank page, just create a new file and save it as index.html. The .html suffix is super important, as it tells your computer that this is a web page that should be opened in a browser.

Don’t use Microsoft Word or Apple Pages. There’s are word processors, not text editors and they add their own markup.

Exercise - create a page

  1. Create a file and save is as index.html. Type “Welcome to the Wonderful World of HTML” into it.
  2. Double click the file to open it in a web browser and see what you have. You should see a web page with that text. Simple eh? You’re aleady doing it!
  3. Create a new line of text” Here is another line”.
  4. Go back to your browser and press refresh. Interesting eh? The newline has been ignored.

Exercise - add some tags

  1. Wrap the “Welcome” text in <h1> </h1> tags.
  2. Add some paragraphs of text. Leave a double newline in between them.
  3. Now wrap these paragraphs in <p> </p> tags. See what you have?


Your html file should look something like this:

<h1>Welcome to the Wonderful World of HTML!</h1>
<p>First Paragraph.</p>
<p>Second Paragraph.</p>

In a browser it should look something like this:

Chrome showing a simple web page

More practice with markup

We have many more tags at our disposal:

  • <h1> - Top level heading
  • <h2> - second level heading
  • <h3>, <h4>, <h5>, <h6> - well, you can guess. Heading level 3, 4, 5, etc.
  • <p> - for paragraphs
  • <em> - Emphasis (usually italic)
  • <strong> - Important, (usually bold)
  • <nav> - navigation elements
  • <form> - forms
  • <header>, <footer> - headers, footers
  • <article> - an article
  • <section> - a section in an article
  • <img> - an image
  • <ol>, <ul>, <li> - ordered list, unordered list, list item
  • <a> - an “anchor” tag, which is another way of saying hyperlink. It’s a link.

And quite a few more. This list might look intimidating at first, but remember when I talked about Semantic HTML? These are all things that can be used to express the meaning of a page. This bit is a header, this is an article, this is a list. It actually all makes sense, and because it makes sense it’s easy to learn.

Execise - Lets Mark Up a Real Document!

Start with the following text document. You can just copy paste:

Types of HTML

HTML has had many incarnations over the years. All of these are similar, but successive refinements have been added over time to cope with our evolving understanding of the best way to make a website. Three types of HTML are in use today.


HTML4 is the oldest type of HTML in use today. Its very popular and still a good choice. HTML4 has a fairly loose syntax. Closing tags are often optional, so paragraphs for instance are automatically ended when a new paragraph is started.

A loose syntax is good for amateur developers but not so great if you want to achieve a specific result across browsers since it makes it harder for browsers to accurately guess at what you mean. To counter this problem, XHTML was introduced



XHTML stands for eXtensible Hypertext Markup Language. It’s actually a specific dialect of XML which is a generalised markup language. The main difference between XHTML and HTML4 is that all tags, once opened, must be closed. There are also some restrictions about what tags can be nested inside each other. These restrictions are sensible and you probably won’t run up against them.

The browser will make no assumptions and will allow you your mistakes. Aside from this, all the tags are the same This is the language used by most professional web developers.



HTML5 is the current HTML specification. It is still a fairly loose term and refers to a number of related technologies. It takes the best features of HTML4 and adds a number of extra tags, such as the header tag, the section tag and the video tag. Many features of HTML5 can be used today.


Mark it up as follows. We’re using a few more tags this time. Do view the results in your browser as you go so you can see what’s changing.

  1. Use h1 start and end tags <h1> </h1> to demarcate the “Types of HTML” heading
  2. Use h2 start and end tags <h2> </h2> to demarcate the subheadings.
  3. Mark up the paragraphs so they display correctly using the <p> </p> tags
  4. Make the text “best way” appear in bold using the opening and closing Strong tags <strong> </strong>
  5. Make the word “incarnations” appear italic by wrapping it in opening and closing <em> </em> tags. Em stands for Emphasis.


Some things like an <h1> or <p> make sense on their own. A section is either a paragraph or it isn’t. Some types of tag though need extra information. A hyperlink for example needs to know where to link to. An image needs to know what file to display.

We can change the behaviour of our elements using HTML attributes. These go inside the first angled braces.

For example, here is a hyperlink (<a> stands for anchor, which was the old name for a hyperlink):

<a href="http://www.google.com">Link to Google</a>

Whoa there mister, that’s a funny looking opening <a> tag. Yes, it has extra text inside it to say where the link should point to. We call this an Attribute.

href is short for hypertext reference in case you were wondering.

The <a> tag must have an href attribute to say where it should point to, otherwise it can’t work and will just sit there crying. We’ve put the place we want the link to link to right there inside the <a> tag. It’s an href attribute that tells the <a> tag how to work.

Lots of tags have attributes you can use to change their behavior or appearance. Images have a src attribute. Most tags can have style and title attributes if you want. We’ll find out more about this later.

Exercise - Attributes

Extend the previous exercise. There were links to wikipedia in the document. Convert these into actual hyperlinks. Verify they point to the right place.

Further Exercise - a new tab

Add another attribute to your a tags to make them open in a new tab. The attribute is:


Try this now. Click the link. Does it open in a new tab? You should be a little bit careful what external sites you like to, but Wikipedia is probably safe.

Now let’s look at some images!


What would a web page be without images? To add an image to a web page we use the img tag like so:

<img src="kitten.jpg" alt="kitten" />

Two attributes to notice here:

  • The src attribute is a url where the image can be located.
  • The alt attribute will be displayed if the image cannot be downloaded, and will be read out in a screen reader. It is alternative text.

img is a self closing tag

Note the trailing slash. This is there because the image element doesn’t wrap any text so it has to self close. It is a self closing tag.

Other examples of self closing tags are the <br /> line break tag and the <hr /> horizontal rule tag. They don’t wrap any text so the open and close tags are rolled into one.

Self closing tags were not needed in HTML4. They are totally required in XHTML (bristly moustache, clipboard). They are optional in HTML5, but nice to use anyway, it’s just more correct.

Remember, if your tag does not have a corresponding close tag, pop the / at the end to make it self closing.

Exercise - Everyone loves kittens

  1. Go to Google and do an image search for kittens. Pick a kitten, right click and download the image into a folder.
  2. In the same folder, create an html page. Add an img tag. Give the html tag a src attribute, such that it shows the kitten.

Exercise - title and alt

The alt attribute is alternative text for the image. This is useful for Google, and also for screen readers. It’s important for accessibility.

The title attribute can be added to any attribute. Add a title attribute, then mouse over the image. You should see the title pop up under your mouse.

  1. Add an alt attribute. (Sometimes called alt text)
  2. Add a title attribute.

A final note on URLs

The src attribute stands for source. It’s a URL - a Universal Resource Locator, otherwise known as a web address. It tells the web browser where to look for the image.

In this instance it’s pretty simple. It just points to an image called kitten.jpg in the same directory as the html file. It’s a relative URL because it’s relative to the location of the html file.

URLs can also be absolute. An example of an absolute URL would be:


This URL is absolute because it contains a complete web reference to the image, including the domain where the image can be found.

If you leave off the first part of the URL, but keep the leading slash, the web browser assumes that you’re talking your own domain, so if you had a URL like:


and you were serving a website like from a domain like


The web browser would look for the image at:


You’re not currently serving a web page from a domain, you’re just serving them from your file system, so absolute URLs are going to be difficult at this stage. We’ll circle back to this later.


Lists are used a lot in HTML, most commonly to make menus and navigation. They come in two types. Ordered lists have bullet points, and Unordered lists have numbers.

We make lists using the following elements:

  • <ol> - wraps an ordered list
  • <ul> - wraps an unordered list
  • <li> - wraps an individual list item

An ordered list looks like this:


In a browser this will look like this:

Avenger Coolness

Note that this was an ordered list. I’m sorting the Avengers in order of coolness. Fight me.

Exercise - Mark up the cats

For this exercise, we will mark up a list of cat types as a bulleted list.

Why cats? I like cats. Use dogs if you’re some sort of cat hater, I don’t mind.

Use a list like the following:

  1. Wrap the whole list in opening and closing unordered list tags <ul> </ul>. Doing this tells the web browser that all the elements belong to the same list.
  2. Wrap each individual item on the list in list item tags <li> </li>. Doing this separates each list item, one from the other. When you’ve done this, view in your browser.
  3. For extra credit, create a numbered list using the same data. Do this by changing the unordered list tag into an ordered list tag <ol>

Your final document should look like this:

  • Persian
  • Siamese
  • Ragdoll
  • Pixie-Bob
  • Devon Rex

Nested Lists

Lists can go inside other lists. We use this a lot for hierarchical navigation, or just for presenting information clearly.

A nested list looks like this:

      <li>Flan Star</li>

Nested lists are commonly used for site navigation elements. We can also use them to indicate levels in a structured document.

Exercise - Nested Lists

  1. First enter and mark up the following list as an unordered list.
  1. Now add the following sublist of types of dogs. Do this by creating a new ordered list and inserting it into the dogs list item, just before the closing </li> tag.
Afghan Hound
Norfolk Terrier
  1. Now create similar lists for cats and hamsters.

Your final document should look something like this:

  • Dogs
    • Afghan Hound
    • Beagle
    • Norfolk Terrier
  • Cats
    • Persian
    • Siamese
    • Ragdoll
  • Hamsters
    • Asyrian
    • Black Russian

Style attributes

We define the look of our web page using CSS. The best way to apply styling to a page is using a separate CSS stylesheet, which defines all the rules for our site. We’ll get to this shortly.

We can however apply styles to individual elements on a page. Say we have a paragraph, like this:

<p>Let's make it bigger and redder!</p>

We can make it bigger with a simple style attribute like so:

<p style="font-size:30px">Let's make it bigger and redder!</p>

If we wish to apply some more rules we can do so by separating them with a semi-colon, like so:

<p style="font-size:30px; color: red;">Let's make it bigger and redder!</p>

Here are some things you can do:

  • color: red; - make the element red
  • background: yellow; - set the background to yellow
  • font-size: 2rem; - double size font. More on rems later. font-face: sans-serif; - set the font. You can also give a specific font name like arial or courier.
  • font-weight: bold; - bold text
  • font-style: italic; - italic variant border: 1px dotted blue; - a thin dotted border, solid and dashed are also valid border styles
  • width: 100px; - set the width of the element to 100px max-width: 100px; - the element can go up to 100px if it needs to to fit the content
  • min-width: 100px; - see max-width

Exercise - Adding some Styling

Use HTML something like this. You can copy and paste this if you like:

<!DOCTYPE html>

    <h1>Style attributes are handy</h1>
      In a pinch.
      <strong> But be careful not to overuse them! </strong>

Refer to the CSS cheat-sheet here:

CSS Cheat-sheet

  1. Make the h1 big and red.
  2. Make the paragraph blue.
  3. Add a background colour to the html element.
  4. Add a 5 pixed dotted grey border around the body element.
  5. Make the strong element purple and twice as big.
  6. Set a width on the body of 500px.

Divisions and Spans

Sometimes we want to add styling to an arbitrary region of a document. A portion of a document might be a header or a sidebar. A region of text might just be special somehow. Perhaps it’s an address that we want to highlight in a particular way, or a date that needs special formatting.

For these purposes we have divs and spans.

A document division is intended to demarcate a largish region of text like a header, sidebar or footer. It groups a number of related items. It’s defined using the <div> and opening and closing tags.

A span is designed to demarcate a small region of text, maybe just a word, not more than a line or two. Span’s are defined using the <span> and opening and closing tags.

Exercise - Make some divs

Here is the document to use. Copy and paste this to give yourself a start:

This is a title. Wrap this in an h1 tag

This is a strapline. Wrap this in a paragraph tag

This is body text. Wrap this in a paragraph tag.

This is more body text. Wrap this in a paragraph tag.

This is a line of text containing some words that might want to be styled appropriately. Red, green, blue, big, small

This is footer text, perhaps a copyright notice
  1. Wrap the title in an h1 tag and the strapline in a p tag.
  2. Wrap the strapline in a p tag.
  3. Wrap each of the three lines of body text in p tags
  4. Wrap line of footer text in a p tag
  5. Wrap the h1 and strapline together in a div tag. This groups them. They are now grouped. Add a style attribute to the div tag like so:
<div style="”border:2px" solid grey”></div>

As always, remember to close your div tag using a matching tag so the web browser knows where the div finishes.

Further Exercise - more divs

  1. Wrap the three body text paragraphs in a div tag. This is your main div. Put a border around the main div.
  2. Wrap the footer paragraph in a div tag. Put a border around the footer div.
  3. Wrap span tags around the words: red, green, blue, big and small. Give each element its correct style, so the word blue should be blue.
  4. Add a background color to the header div. use your CSS cheat sheet to find out the correct rule to apply.

Using hexadecimal color references

Generally speaking, the built in color names like red, green, puce and teal are not up to scratch in a real web situation. For a start, there’s no universally defined standard of what colour puce actually is. Is it a reddish brown, or more of a browny red? For most circumstances we need to define our colours more accurately using Hexadecimal colour notation, commonly called Hex codes.

Hexadecimal is base 16. Our everyday decimal notation uses base 10, so we count from 0 to 9, then start again at 10. There’s nothing special about base 10, We just happen to have 10 fingers so it makes finger counting easier.

The ancient Egyptians counted finger joints, so used base 12. To this very day, we still use their 12 hour clock.

Hexadecimal Decimal Equivalent

In Hex, we count from 0 to 15, then start again at 10. To represent the numbers from 10 to 15 we use the first six letters of the alphabet like so:


The reason we do it like this is because of the way information is stored in a computer. Basically, 16 is 2 to the power 4. This means that the numbers 0 to 15 can be represented completely by 4 binary digits with no wasted memory.

Computers use binary digits, and wasted memory is bad. That memory aint free ya know.

Colour values are always expressed using 3 hex numbers jammed together, one number for each primary colour: Red Green and Blue.

For example, if we wrote #f00 that would be red full, green off and blue off, making a nice fire engine red colour.

There are two ways to write a hex code, long form and short form. Long form is more accurate, short form is quicker to type. Short form uses a single hex digit for each colour component. Long form uses two, making it more accurate.

Some example Colours

Red ComponentGreen componentBlue ComponentColour
888Mid grey
0f0Full green
ff0Full Yellow

To make an item full green, we might type:

  <p style="color:#0f0">Some green text</style>

To make it pale blue we might add a little more red and yellow making it lighter like this:

  <p style=”color:#99f”>This text is pale blue</p>

The same colour expressed in long notation would look like this:

  <p style=”color:#9999ff”>This text is also pale blue</p>

Exercise - Pick some colours

  1. Enter the following document and wrap each line in p tags
  2. For each line, add styling to make it the correct colour.

Use this document:

  This line is dark grey
  This line is full red
  This line is rosy pink
  This line is dark blue
  This line is mid green
  This line is purple
  This line is the colour of a brown paper bag.
  This line is the colour of a stormy sea
  This line is the colour of a streetlamp in the early evening.

Entity References

HTML has a limited set of allowed characters. This is due to the way that HTML has evolved to be displayed on various different computers, fonts and character encodings. If we want to use special characters in HTML we need to use entity references. For example, to display a copyright sign we need to use the entity ©. Note the semicolon.

ValueEntity ReferenceOutput
Copyright sign&copy;©
Pound sign&pound;£
Left Double Quotes&ldquo;
Right Double Quotes&rdquo;
No Breaking Space&nbsp; 

There are many more, far too many to list here. If you need a specific reference, Google “html entity reference” to find a very long list.

Exercise - Entity References

Use this document:

"Time and Tide wait for no man." Copyright Chaucer 1390
  1. Enter the document and save it as html.
  2. Increase the text size of the quote.
  3. Replace the word “and” with an ampersand character.
  4. Wrap the quote in pretty double quotes.
  5. Replace the word copyright with a copyright character.
  6. Put the quote in a nice serif font like Georgia.
  7. Change the colour of the quote to a pale grey
  8. Align the quote in the center of the page.


HTML is a tree. We nest elements inside and underneath each other.

We can pull off parts of this tree for styling using CSS selectors.

Style tags

We can put CSS onto our page using a style tag. Later we’ll see how we can extract our styles into a separate document.

  /* Styles go here */

We then write selectors to trim parts of the tree, and add rules, like this:

  h1 {
    color: red;
    font-size: 30px;
  p {
    color: blue;

We can put the style tag in the head of our page like so:

<!DOCTYPE html>
      /* Styles go here */
    <h1>CSS Selectors are better</h1>
      Because they apply
      <strong> to the whole page! </strong>

Exercise - Style the page

Use a style tag and selectors to solve the following:

  1. Make the h1 font-weight: normal
  2. Style the body using a sans-serif font.
  3. Add a couple of dozen lines of text to the paragraph. Now set line-height:2em for double spacing.
  4. Add a couple ore paragraphs. Set top and bottom margins to add spacing between the paragraphs.
  5. Use letter-spacing:0.1em on the paragraphs to open the text out a little.

So far we have been writing CSS directly on out elements using the style attribute. As you can imagine, this quickly gets tiring, and if you have a large site becomes very difficult to maintain.

If only there was a way to extract all the style rules into a different document shared across our whole site. Then we could update that one document and have all the styles update everywhere all at once.

That’s exactly what stylesheets do.

Exercise 1 - create some HTML to style

First create a folder and index.html file. Add the following:

    <title>Super awesome</title>
    <p>Paragraph 1</p>
    <p>Paragraph 2</p>
    <p>Paragraph 3</p>

Open this file in your browser and preview.

Note the link tag. This is linking an external stylesheet.

Exercise 2 - Create the CSS

In the same folder, create a file called styles.css. In it write something like this:

p {
  color: grey;
  font-size: 3em;
  text-align: center;
  margin: 2em;

In the head section of your HTML, right after the closing title tag add a link tag like so:

<link href="styles.css" media="screen" rel="stylesheet" />

This will link the CSS file to the HTML file. Refresh your browser and you should see a styled page.

Exercise 4

Open up your style.css and attempt the following. After every change refresh your browser.

  1. The paragraphs are currently grey. Make them blue.
  2. Increase the margin on the paragraphs to 5em.
  3. Align the paragraphs right.

Jolly good.

Classes of things

So this is all very nice. We can apply a rule to all paragraphs on a page, but what if we want to apply a rule to only one specific paragraph, what then? Thankfully this has been thought of.

Use the following simple html file. Save it as index.html

    <title>The use of classes</title>
    <p class="first_paragraph">Here is the first paragraph</p>
    <p class="second_paragraph">Here is the second paragraph</p>
    <p class="final_paragraph">Here is the final paragraph</p>

Notice the new class attribute that I’ve added to the paragraphs. We say that “we have given the paragraphs class names”. We can now identify the paragraphs uniquely using these class names and the dot operator.

  1. Create a CSS file and save it as exercise_4.css. Use the tag to link the stylesheet to the html document.
  2. Enter the following into your CSS document:
.first_paragraph {
  color: red;

Now test in your browser. What has changed? As always, if nothing has changed, call me over and we’ll sort it out together. The dot operator has selected an element based on its class attribute, rather than it’s tag name.

Exercise - Colours

  1. Make paragraph 2 go blue
  2. Make the final paragraph smaller and grey.
  3. Write a single rule that puts a cute little one pixel dotted grey border round all the paragraphs.

Styles are commonly used in conjunction with divs and spans to demarcate special areas of the document, headers, footers and suchlike. Now we’re really coding. Isn’t this great?

Note that “first_paragraph”, “second_paragraph” and “final_paragraph” are just words that I made up. You could just as well use “header”, “main_text” and “footer”, or “flange”, “doodad” and “thingummy”. It’s best if your class names make sense in context though so “thingummy” would not be a great class name, unless you have written a paragraph about thingummies.

Teaming Up Selectors

The final thing we need to know before we move on to creating some web pages of our own is how selectors chain together to make more complex selectors. This is the last bit of pure theory we’ll learn before moving on to make some real websites.

If we put 2 selectors together with a space between them, we narrow our focus. The selectors act like filters. The first selector narrows the focus a bit. The second selector can then only choose parts of the document that the first selector has already chosen.

Take the following HTML.

    <title>Super Selector Tag Team</title>
      <h1>A big title makes an impact</h1>
      <p>a subtle <strong>strapline</strong> is great</p>
    <div class="main">
      <p>some body text</p>
      <p>and some <strong>more</strong></p>
      <p>and the <em>last line</em></p>
      <p class="copyright">&copy; 2011</p>
      <p class="contact"><strong>Contact</strong> us</p>

We can create a stylesheet and link it as before. Let’s choose only the strong tag in the .header

header strong {
  font-weight: normal;
  color: #666;

The strong element in the header has changed, but the strong element in the body has not. The first selector in the style rule has narrowed the focus to the header div. The second selector has further narrowed it to strong elements inside the header.

Exercise - Nested Selectors

  1. Write a style rule that makes both paragraphs in the footer small and grey
  2. Write a style rule that makes the word contact black and italic.
  3. Write a rule that makes the h1 twice the size
  4. Write a rule that makes the word “more” big and red.
  5. Underline the word “strapline”

eBay Analogy

Some people find it helps to think of CSS rules as filters. If I want to buy a new 17 inch unibody macbook pro on ebay, I don’t look through the complete list of all auctions. That would take many many years. Instead I do a search for macbook. Ebay then returns a sublist of everything matching that keyword. It’s no longer the whole set, it’s a subset of the whole set.

But wait, now I have a whole list of screen protectors, cases, cleaning wipes, etc, etc, so I narrow again, this time by price. I say to eBay: take that sublist you previously generated and give me a sub-sub-list containing only the items of £500 or more. Now I only see the thing’s I’m interested in.

CSS chaining is like this. You narrow, then you narrow again. You filter a sublist of elements, then you filter a sub-sub-list and a sub-sub-sub list if you like.

Great job. There is plenty more to CSS, but this is all you will need to be pretty great at most things. If you’d like to go further, you could take the advanced CSS course.

Onwards and upwards!


A little simple typography can take a boring simple page and make it beautiful.

  • font-size - font size
  • letter-spacing - kerning
  • line-height - leading
  • font-family - change the font

Font Sizes

We can specifiy a font size in several ways:

  • px - pixel sizing.
  • em - the width of a letter M - legacy, do not use.
  • rem - Root relative Em. The best way to do font sizing today.

we specify a font size like this:

body {
  font-size: 16px;

This will set the base font size on the document to 16px, which is a nice round number.

We can set the font size on an h1 like this:

h1 { font-size: 32px; }

but we should avoid doing this if possible. Instead we should set a base font size on the body, then use rels to specify to size of individual elements:

body {
  font-size: 16px;
h1 {
  font-size: 2rel;

The h1 will have font size 2 * 16px, or 32px. Changing the root font size will scale up all other elements specified in rels.

We can use this to create a harmonious set of font sizes that scale smoothly from small to large:

h1 {
  font-size: 2rem;

h2 {
  font-size: 1.5rem;

h3 {
  font-size: 1.25rem;

p {
  font-size: 1rem;


Kerning refers to the space between letters. It’s subtle, but makes a huge difference to the attractiveness and legibility of text. Generally speaking, small text looks great with more space between the letters. Large text looks better with tighter kerning.

Small text

When text is smaller, it is more readable and attractive if we increase the letter-spacing a little.

%p{style: ‘letter-spacing:0.15em; font-size:0.5em; border:1px solid black; padding:1em;’} Small text looks better with a little more letter spacing. Here it is set to 0.15em.

Big text

When text is larger, it looks better if we move the letters together a bit. Check out any newspaper headline.

%p{style: ‘letter-spacing:-0.05em; font-size:3em; border:1px solid black; padding:1em;’} Big text looks better with tighter kerning (-0.05em)

Ordinary text

Ordinary sized text looks better with slightly higher than default letter spacing:

%p{style: ‘letter-spacing: 0.05em; font-size:1em; border:1px solid black; padding:1em;’} Ordinary text with just a little more breathing room (0.05em)


Leading refers to the space between lines. It’s a good idea to increase the default leading slightly. We do this with line-height.

Generally speaking, the larger your text, the less leading you need. Small text can be very legible with lots of leading.

Alternative fonts

We can use any font using font stacks. The browser will use the first available font in the list, like so:

font-family: helvetica arial sans; font-family: “Times New Roman” serif;

Google fonts

We can also link to web fonts if we want something specific.

GEt them from here: https://www.google.com/fonts


Black type on a white ground is glaring and hard to read. If you inspect this page you’ll find that the type is not fully black, but instead is a dark charcoal.


Wide text is hard to read because it’s difficult for the eye to track back across the screen. Aim for 80-120 characters to a line. More than 120 and you have a readability problem.


  1. Copy and paste some of the content from this wikipedia page: http://en.wikipedia.org/wiki/Typography
  2. Add in p tags, h1s and h2s.
  3. Increase the kerning and leading a little so it looks nice.
  4. Reduce the kerning on the h1s and h2s.
  5. Change the text colour to dark grey, perhaps #111.
  6. Make the h1s and h2s a little lighter in colour, perhaps #222.
  7. Replace the default font with a Google font. You might like Open Sans or Slabo.
  8. Change the width of the body tag to show around 80-120 characters.



Full Width Elements

A useful default. Full width elements are easy to achieve in CSS. Any block level element will take up the maximum amount of space available to it by default. You don’t have to do anything to trigger this behaviour. Full width elements are used all the time in HTML layouts for headers, footers, or just the document body. We should take advantage of this useful default behaviour whenever possible.

Exercise - Simple page

  1. Create an html file and linked stylesheet.
  2. Add three 3 divs to the file, one after the other.
  3. Put some text in each div to hold it open and make the page more realistic. You can cut and paste this text from any source you choose.
  4. Use CSS to give each div a border so you can see where it is.
  5. Resize the browser, notice how the divs take up all the available horizontal space.

The structure of your page should look something like the diagram below.

%img{ src: “/images/webdev/full-width.jpg” }

The elements in the layout above take up the full width of the browser. This is useful if we want to create a responsive liquid layout that takes advantage of available screen estate. With clever use of gradients and background imagery such a layout can look rather good.

Constraining width

Often we don’t want out page to stretch and grow. In these cases the width of an element can be constrained using the width property. Elements nested inside this element will be constrained by the width of their container. This is tremendously useful as we can set the width of one wrapper element and let the elements inside find their own width.

Exercise - Constrained width

  1. Create an html file and linked stylesheet.
  2. Create a wrapper div, give it a class or wrapper and set it’s width to 800px in the stylesheet.
  3. Nest 3 divs inside the wrapper div, give each a class.
  4. Put text inside each of the three inner divs to make it more realistic. You can cut and paste this text from any source.
  5. Give the wrapper div and each of the three inner divs a border. Notice how the inner divs expand to fill the wrapper div.

%img{ src: “/images/webdev/constrained-width.jpg” }

This is a useful simple layout. We commonly see this with a subtle dropshadow added to the wrapper div, and a background image on the body, making the content appear to float over a textured background, clean, simple and pure.

Absolutely Positioned Layouts.

Absolute positioning gives us full control over the size and position of any element, but it comes at a cost. An absolutely positioned element cannot affect the position of any other element on the page, so it can’t push other elements out of the way if it expands.

If the position of an element doesn’t need to affect the position of any other elements on the page, you have an absolute positioning candidate. Declare the element position absolute and optionally give it top and left values. If you don’t need to worry about IE6, you can also give it bottom and right values.

Exercise - Simple column layout

  1. Create an html file and linked stylesheet.
  2. Add four divs to the page
  3. Put text inside each of the divs
  4. Give each div a border do you can see where it is.
  5. Position each div absolutely.
  6. Give each div a top and left value to create something like the layout below.

%img{ src: “/images/webdev/absolute.jpg” }

Exercise - Arbitrary layout

  1. Create an html file and linked stylesheet
  2. Add four divs to the page.
  3. Put text inside each of the divs to hold them open and make them more realistic.
  4. Give each div a border do you can see where it is.
  5. Position each div absolutely.
  6. Give each div a top and left value to create something like the layout below.

%img{ src: “/images/webdev/absolute2.jpg” }

You can create any layout you like using absolute positioning, provided you don’t need the elements to jostle each other out of the way.

Exercise - Header Layout

  1. Create an html file and linked stylesheet.
  2. Add a div to the page. Give it a class of header.
  3. Give the header div a width of 800px and a height of 150px in your stylesheet. Give it a border.
  4. Declare your header div position:relative. This will reset the origin for all absolutely positioned elements within it.
  5. Put three divs inside your header. Give them classes of logo, top-nav and menu.
  6. Position them appropriately using CSS and absolute positioning to create the following, useful, real world layout.

%img{ src: “/images/webdev/absolute3.jpg” }

Absolute positioning is useful in any element where we know the height in advance. It the case of our header, we have fixed the height so we don’t need to worry about elements interfering with each other. We’re free to chuck the header’s contents around as we see fit.

Positioning with margins or padding

We often forget that one easy way to move elements around the page is by using margins and padding. For example, if we want to move an element away from the top of the page, we can use margin-top to achieve this very simply. If we want to move two elements apart, we can add margins to force them away from each other.

Exercise - Margins

  1. Create an html file and linked stylesheet.
  2. Add a div to the page. Give it a class of header.
  3. Add another div inside the header. Give it a class of logo.
  4. Fix the height and width of the header div and the logo div.
  5. Put a border round both divs so you can see where they are.
  6. Position the logo div inside the header div using margins, e.g. margin-top:20px;

%img{ src: “/images/webdev/margins.jpg” }

Often margins and padding are sufficient to achieve the effect we need. When playing with padding, do keep in mind the issues with IEs box model. Don’t set padding on an element with a fixed width or height or you’ll run into cross browser issues.

Negative Margins

A positive margin moves an element away from other elements. A negative margin does the opposite. Negative margins are occasionally very useful for certain special effects. You can make two elements overlap a little, or a lot.

Exercise - Negative Margins

  1. Create an html file and linked stylesheet.
  2. Create an h1 and put a page title in it.
  3. Create a paragraph and put a subtitle in it.
  4. Set the margins of the h1 and paragraph to 0 so they sit underneath each other
  5. Set the top margin of the paragraph to a negative value and watch how the subtitle moves up tight to the h1.

%img{ src: “/images/webdev/negative-margins.jpg” }

A word of warning

Negative margins are both useful and dangerous. Beware of using them to “fix up” a layout that logically should work. They can hide a layout bug, but bugs have a tendency to pop up unexpectedly. Use them with care and awareness, not to fix a layout issue that you don’t understand.

Centering on the page using margin:auto

Margin:auto simply means take all the available space and distribute it evenly. An element can be centred on a page by using margins. If you declare it to be fixed width, then setting margin:0 auto; (top and bottom 0, left and right auto) will make the left and right margins automatically share the remaining space on the page.

Exercise - Margin Auto

  1. Create an html file and linked stylesheet.
  2. Create a div and add quite a lot of text to it. Cut and paste from a web page of your choice.
  3. Fix the with of the div to 800px;
  4. Add a border to the div.
  5. Set margin: 0 auto; on the div. It should now be centered horizontally on the page. You can stretch and grow your browser and it will remain centered.