CSS 101

Tutorial: CSS 101

Introduction

As we emphasized in our introductory HTML tutorial HTML 101, HTML is a markup language, not a layout language. In other words, HTML is all about defining the logical structure of a document, not how it looks. A completed HTML document should tell the browser where paragraphs stop and start, which elements are headlines, which are quotations, which are images, which are lists, and so on. It should say nothing about what fonts or colors are used, where the sidebar lives, which direction the menu flows in, or anything else that relates to document display.

Why is this important? For three main reasons:

Site designs change frequently. When you embed formatting commands into a document, you make it difficult to change later. By decoupling your content from its display rules, you greatly simplify future changes to the design – you’ll be able to alter the display rules without digging around in the content.

Webmasters are seldom concerned with a single document — sites comprises dozens, or hundreds, or thousands of pages. If you maintain a 3,000-page site with formatting embedded in the content of each one, and decide you want to change it later, you’re going to have a heck of a job on your hands. By decoupling content and design, you can tweak design rules in a single external document and have the changes apply to your entire site instantly.

Keeping HTML documents simple and handling display issues with stylesheets makes your pages more accessible – readers using assistive technology such as screen readers for the blind will have a much easier time navigating your document.

CSS, or Cascading Style Sheets solve these problems (and more) with a straightforward syntax that lets you create and apply design rules to unstyled HTML documents.

The Cascade

It’s easy to figure out what “Style Sheets” means, but what is the “Cascade?” The term refers to the way CSS rules are inherited down through a hierarchical chain. To understand this, you need to first know that CSS style rules can pertain in any of three places:

An entire site

A single document

A subset of a document (like a paragraph, or even a single character)

Let’s say we decided that all paragraphs in our site should be rendered in a 12pt. bold blue Verdana font. And let’s say that on a single page of our site, we decided that paragraphs should be rendered in 13pt. italic green Tahoma. And let’s say, just because we’re nuts, that one of the paragraphs on that page should be rendered in 14pt. underlined pink Times New Roman. In all three cases, we’re applying a rule to a single HTML element – the P tag. So should that one page have blue paragraphs, or green? Should that one paragraph in the middle of the page have green, pink, or blue characters? There’s a conflict here – who wins? This is where the “cascade” comes in, and the cascade rules say:

“When style rules conflict, the rule that applies to the more specific context wins.”

A single page of your site is more specific than your site as a whole, so the rules attached to that whole page win over the site-wide rules. And a single paragraph in that page is more specific than the page as a whole, so that one paragraph will be pink.

In actual practice, you’ll use a single site-wide stylesheet most of the time and won’t be dealing with many conflicts like this, so the issue rarely comes up. And yet, when it does, the cascade is an easy-to-understand, powerful tool you can put to great use. We’ll explore it more later.

Need a sample document to work with? It’s best to create your own, but if you’re pressed for time, feel free to download our sample document here.

As with the HTML 101 tutorial, we’ll assume you’ve chosen a good text editor and know how to switch back and forth between a document you’re editing and that same document open in a web browser (or to use the Preview in Browser option in your text editor, if it has one).

TextMate users: We recommend familiarizing yourself with some of TextMate’s powerful shortcuts to maximize your speed and efficiency while editing.

Rules and Selectors

To style elements in a document, you simply apply rules to selectors. What’s that now? Simple: A “selector” is a way of referring to some specific element or group of elements on a page. For example, if we want to apply a style to all paragraphs, then the <p> (paragraph) tag is our “selector” – it’s what we’re “selecting” to style. Selectors can either be standard HTML tags, or custom elements you define.

A “rule” is a set of properties that get applied to the selected element or elements. A rule can be as simple as a single line declaring the background color of the element, or a complex grouping of properties that work together to achieve an effect.

Let’s start with the simplest case – styling a single paragraph. All you need to do is attach a style to an element on the page, and create rules as name:value pairs, separated by semi-colons. Try this:

So now we’ve gone and done exactly what we said we weren’t going to do – embedded stylistic information into the document, thus making it more difficult to maintain/update in the future. Let’s fix that by creating a document-level style for the page you’re working on. First, remove the style you just attached to that paragraph, restoring it to a normal <p> tag.

Now, go to near the top of your document, somewhere inside the <head> container tag, and add this:

What you’ve just done is remove the “inline” style added earlier, and replaced it with a document-wide style declaration. <style> is an HTML tag that provides a container into which you can insert any number of style rules that should apply to the entire document. Remember that earlier we said there were three places you can apply styles: 1) To a single element, 2) To an entire document, 3) To an entire site. We’ve just moved from method #1 to method #2.

With the style added to the entire document, you get the same effect, but for all paragraphs on the page. In this case, the standard HTML <p> tag is your selector. In the <style> section of your document, you’ve created a rule that corresponds to all instances of that selector. Of course, you probably don’t want blue paragraphs all over the place, so go ahead and change it to black. While you’re at, add a second name:value pair, specifying the font size. When you’re done it should look like this:

What else can you specify besides color, font size, and font family? Lots. Background-color, border width, border color, and much more. But how do you know what name:value pairs are available to you? We’ll be showing you the most commonly used CSS properties in this tutorial, but we can’t cover every possibility. To go beyond the basics, use any CSS reference, such as a book or web site (see the Related Links section of this tutorial for links). One of the best, and easiest-to-read sources of CSS information is the W3Schools’ CSS Reference.

Alternatively, you can use a text editor that will help you with styles. For example, Adobe Dreamweaver has extensive CSS creation tools built in. However, for the sake of this tutorial, we’re going to focus on learning CSS, not on finding tools that write it for you. And the best way to learn is to write code by hand. Later, after you’ve climbed the garden wall, you can push away the ladder if you want to. But you probably won’t want to

Custom Selectors

What we lost in the previous step was the ability to target a single paragraph. Our new page-wide rule applied to all paragraphs on the page — but what if we need the occasional ability to make a particular paragraph stand out? CSS makes this easy, through the use of the “class” and “id” constructs. By attaching a “class” name to an HTML element, and writing a corresponding rule for that class, you can get as specific as you like. Modify the style rules at the top of your document to look like this:

Now, modify the opening <p> tag of one of your paragraphs to look like this:

The result should be this – a single paragraph on your page that gets additional stylistic information.

So what just happened? The “special” paragraph actually got instructions from two selectors. It’s a paragraph, so it inherited the rules for all paragraphs, and it had class="alert" attached to it, so it inherited those rules as well. Another interesting thing about this is that the rules for both p and .alert specified a color – black for paragraphs and darkred for anything in the class “.alert”. Only one of them could win, so the cascade kicked in. The class declaration was more specific than the general rule for paragraphs, so it won.

OK, here comes the cool part. Go to a second paragraph somewhere in your document and attach class="alert" to that one as well. Voila! Now you have two custom-styled paragraphs in your document, even though you’ve only established one ruleset. The rule you’ve created is the .alert { ... } section in the style section at the top of your document.

The selector you’re using is anything with class="alert" attached to it. Anything? Darn near. Try attaching that same class to a blockquote on your page, or to a list. Same effect, different element. Pretty cool.

Class vs. ID

Above, we mentioned that there were two constructs for custom selectors — “class” and “id.” You’ve seen that a class can be applied as many times as you like on a page. IDs work almost the same way, but apply to just one element on a page. When creating rules for IDs, simply prepend the selector name with “#” rather than “.” For example:

Since you will probably only ever have one footer on a page, it makes sense to use this as an ID rather than as a class. You would invoke this ruleset in your document like this:

Recap: When writing CSS rules, you don’t have to specify an existing HTML tag as a selector. If you start any word in a ruleset with a dot (“.”), it becomes a custom selector called a “class”, which can then be applied to anything on the page. In our example, we used the word “.alert” in our ruleset, prepended it with a dot, and it became the rule for the selector “alert”. Similarly, we can address a single element on a page by referencing with an ID rather than a class. Rules for IDs use the “#” syntax rather than the “.” syntax. In general, you’ll use IDs when elements are guaranteed to be unique on a page, and classes when they’re not.

The ability to style any existing HTML element, combined with the ability to create custom, named selectors, gives you complete design and display flexibility.

Refining Selectors

So far we’ve been working with rulesets that look like this:

In other words, we’ve created rules that apply either to a single HTML tag, or to anything that matches a custom selector name. But we actually have even more control than that — you can easily broaden or narrow the “scope” of elements your rulesets apply to.

Broadening the Scope of Rulesets

What if we wanted that default p style to apply to both paragraphs and blockquotes? We could duplicate the rule, but that would stink because then any time we modified one we’d have to remember to modify the other as well. CSS solves this problem by letting you list a whole set of selectors for a given rule, like this:

Now the rules in the set will apply equally to paragraphs, ordered and unordered lists, and blockquotes. Of course, if you want to set some basic rules that will apply to your entire document, there’s an easier way — just use the HTML <body> tag as your selector:

Since all visible elements in a document fall inside the opening and closing <body> tags, these rules will apply to everything on the page. And since the cascade favors the specific over the general, you can easily override any rule on a per-selector basis. For example:

Even though you’ve defined a color for the entire document, and your blockquotes fall inside that document, blockquotes will be rendered with a pink font. The cascade says that even though everything on the page is black by default, blockquotes are effectively treated like an exception.

Narrowing the Scope of Rulesets

Let’s look at the opposite situation. Earlier, you created the class .alert, which applied to anything on the page with class="alert". But maybe you want to be more specific than that. Maybe you only want those rules to apply to paragraphs in that class, but not to blockquotes in that class. This is done like this:

The rule above would not be invoked for standard paragraphs, nor would it be invoked for blockquotes with a class of “alert.” It would only be invoked for paragraphs with a class of “alert.” This “narrowing” approach can be used for IDs as well as classes:

The above rule would be invoked only for an instance of <p id="alert">.

You can also narrow the scope of rulesets by referring to the way HTML tags are nested within one another. This is best understood through a practical example you’re likely to encounter. Let’s say you’ve defined your body background color to be white, and your link color to be gray. But let’s also say you have a rule that says paragraphs with a class of “alert” have a gray background. Unfortunately, any links appearing in those paragraphs are going to be invisible, since they’ll be gray on gray. You need the ability to say “Any links found inside of a paragraph with class “alert” should be white.” Here’s how you’d do it:

Compare the following two paragraphs. The top one is “normal,” while the bottom one has class “alert”. Both paragraphs contain links, but the links are displayed with different colors.

The key to making this work is the bolded part above. The rule says, “If any <a> tag is found within a paragraph of class “alert,” use these style rules instead.” The nesting reads from outer to inner (the “a” tag is within the “p” tag). Nesting can go as many levels deep as necessary. Creating rules that specifically address nested elements may seem tricky, but this real-world scenario comes up often, so make sure you understand the syntax.

Available Properties

So far we’ve been using a small handful of properties in our examples (color, background-color, border, etc.). But obviously there are many more attributes available. So… what exactly can you stick in a name:value pair? Think back to the HTML 101 tutorial, where we said that different HTML elements could take different attributes. The situation is very much the same here — it makes sense to specify the color of a font, but not of an image. For the most part, though, you can attach almost any attribute to almost any element on a page. Again, see a complete CSS reference such as the one hosted by W3Schools for detailed listings. In this section we’ll cover some of the most commonly used attributes and some of their allowable values. This list is by no means complete.

A quick note on comments. If you want to leave a note to your future self or for another developer on your team in your CSS code, just surround any amount of text with /* and */. It’s good practice to comment code in any programming language when its purpose is not immediately obvious.

The CSS rabbit hole goes very deep, but this is a CSS 101 tutorial, not a comprehensive manual. We cover the most commonly used attributes and their possible values, with implementation notes below.

Color

Specifies the foreground or background color of any selected area. In practice, foreground usually refers to font and border colors, while background-color refers to, well, the background color.

Usage example:

In earlier examples, we’ve been referring to colors by their “friendly” names, such as “blue” or “gray”. There are only 216 of these “friendly color names” in HTML/CSS, but you’ll want access to the full range of colors in the spectrum for your web work. Therefore, most of the time you’ll be referring to colors by their “hexadecimal values,” such as “#7FFFD4.” You can obtain hex color values in a bunch of ways. Your text editor may have a color picker built in, which can insert color values into your CSS code automatically.

In TextMate, hit Cmd-Shift-C anywhere a color can be inserted to select a color. When you click OK, The hexadecimal equivalent of the selected color will be inserted at that point. Other text editors should have similar features.

You may need to extract a color value from Photoshop or Flash, in which case you can look for hexadecimal values in those tools’ color pickers, and copy/paste color values back and forth between images and CSS. Or you may use any of the hundreds of web-based color pickers out there. One of our favorites is colorhunter.com, which will let you create entire palettes of complementary color values, and email the hex values to yourself for reference. We’ll refer to colors by their hex values throughout the rest of this tutorial.

Fonts and Text

You can independently set the font face (font-family), the font size, font style (such as italic) and the font weight (such as bold):

Font sizes can be set in pixels, points, ems, or relative values.

You can control how widely your letters and lines are spaced, set text color, align text left or right, and even change the case of text, all from within CSS.

Setting text color and letter spacing:

Letter spacing can be set in points, pixels, or ems. “Em” is a typesetter’s term, referring to the width of one character. We recommend using ems when setting text sizes and widths, because it flexes automatically with the user’s current screen resolution and magnification.

Line spacing is not set in ems – it’s a simple decimal value representing a factor of the current line height. In the example below, “1.8” means “spacing between lines should be 1.8 times whatever the current height of a line of text is.”

Amazingly, you can even control the case of letters. This is very handy if, for example, your staff has always entered headlines with Initial Caps, but you later decide that headlines on your site should be all uppercase. Rather than go into your CMS and change every headline in the system, just set the display case in CSS. Here’s the exact same paragraph above but with the text-transform property set:

Links

A common requirement is have full control over the appearance of links on a page. You may want your links bolded rather than underlined, or to appear in a different color. You want to control how a link appears when the mouse is hovering over it, or you may want links on different sections of a page to appear in different colors.

In HTML, a link is represented by the “anchor” tag, represented as <a>, with an attribute of href. Therefore, a rule to style links simply uses “a” as a selector. Here we’ll make our links green, bold, and turn off underlining.

Instead of “none” you can also use any of “overline,” “line-through,” “underline,” or “blink” (for lord’s sake, please don’t use blink!). Actually, these are general text properties, not just link properties — we just happen to be decorating the text that appears within links here.

But that doesn’t take us far enough. At the least, you want to style links differently depending on whether the user has or has not visited them before. But there is no HTML in the document you can use to determine whether a user has visited a link before — you’re trying to detect a condition that only exists in the web browser, not something in the HTML itself. CSS accommodates this through something called “pseudo selectors,” which you see separated by colons in the code below (:visited, :hover).

Notice also that we don’t have to specify the font-weight and text-decoration for the two pseudo states. Since we specified those properties for the basic a selector, they apply to all links, regardless of state, unless you specifically override them.

To see how to set link styles/colors differently on different sections of a page, see the end of the Refining Selectors section of this tutorial.

Borders

You can put a border around almost anything, from a single character, to an image, to a section of a page. Borders can be of any thickness and any color, and can be solid, dotted, or dashed. If you use border: by itself, the border will go around all four sides of the element. Or you can use border-top:, border-left: and so on to control each side of the border independently. You can can consolidate all of the attributes of the border into a single command by separating the attributes with spaces.

Usage examples:

That will give a consistent border on all four sides of an element. For more control, use:

By default, a background image will tile repeatedly in all directions, to fill up the space it’s assigned to. Alternatively, you can tell your background image to only repeat along the x or y axis. In the next example, we use both a background color and a background image. We tell the background image to only repeat vertically. To prevent the text from sitting on top of the tiled image, we add 120px of left padding (covered in the next section).

Margins and Padding

If you ever learned the cellpadding or cellspacing attributes for HTML tables, you’ll find working with margins and padding similar in CSS. Margins refer to the area around, or outside of an element. Padding, in contrast, refers to the area between the edges of a box and what lives inside that box. An easy way to remember which is which is to think of sending a breakable object through the mail – you fill the empty space in the box with foam peanuts to protect the item. Those foam peanuts are your padding. The margin would then be the space between your box and the next box in the truck. Just remember: Padding is inside the box, margins are outside the box.

In CSS, you’ll generally use padding to give an element some breathing room within the space it’s in, as we did with the last example in the Backgrounds section. You’ll typically use margins to cause a box or element to be offset from adjacent elements. The syntax for working with padding and margins is very similar.

Padding and margins may just seem decorative right now, but they’ll become critical when we start getting into CSS page layout, so make sure you understand them.

But that’s pretty verbose. When setting padding values separately for different sides of a box, you can use this shorthand, which achieves exactly the same result as the previous example:

When using the shorthand syntax, specify all four values, separated by spaces, in a clockwise circle starting from the top (top, right, bottom, left). If you specify only two values rather than four, the first value will apply to the top and bottom, and the second value will apply to left and right:

To illustrate margins, we really need to talk about how one element (box) relates to another. For our purposes, we’ll be putting a sample paragraph inside of an element called a “div,” which we haven’t covered yet. For now, suffice to say that a div is an arbitrary box used to contain other things. We’ll put a border on the div so you can see it, then put a paragraph with its own border inside that div, so you can see what the margin attributes do to it.

The blue space above represents the paragraph, while the green space represents the margin between that paragraph and it’s containing box. As with padding, we can control margin depths per-side, rather than globally.

In the second example, we’ve used syntax very similar to the shorthand we used earlier for padding, but to create different size margins on each side of our paragraph box. Again, these concepts will become critical when you get into CSS page layout techniques.

Lists

An ordered or unordered list can be much more than a simple set of bullet points – in CSS, lists are often used to create navigation elements such as horizontal or vertical menus. Let’s start with options for simple lists.

For unordered lists, you can select whether the bullet style should be circular, square, or none:

This

Is a

List

Try changing “square” to “circle” or “disc” for other effects. You can also use an image in place of your bullets by specifying its URL:

This

Is a

List

Ordered lists can have any combination of Roman numerals, decimal, alphabetic characters and more. A nice trick is to nest lists within lists, then use the CSS nested selector syntax we learned earlier to style different levels of your list differently, like this:

Person

Place

Region

Country

United States

Canada

Mexico

State

Thing

In the example here, ordered lists “ol” are told to use “upper-roman” as the list-style-type, unless it’s an ordered list inside of an ordered list, in which case the list-style-type is “decimal”… unless it’s a triply nested ordered list, in which case the list-style-type is “lower-alpha.” This technique is the key to building CSS based flyout navigation menus.

Lists As Menus

By default, list items are “block-level elements,” which means each one gets a line break above and below itself. To make a list appear horizontally, we need to override the default block behavior and use CSS to tell list items that they’re “inline” elements instead. In this example, we’ve also added background-color and padding to our list items, to make them appear like real menu items. Here is the simple HTML and CSS to create a basic list menu.

Which is rendered by the browser as:

Item one

Item two

Item three

Item four

Item five

For a better user experience, we want to add some rollover behavior, so that the list items change color when the mouse rolls over them. To accomplish this, we’ll first make our list items into links (in the HTML). Then we’ll again use the CSS nested selector syntax to detect a linked item inside of a list item. Finally, we’ll use the anchor tag’s :hover pseudo-property to change appearance when a list item is in a certain state – namely, when the mouse is hovering over it.

Which is rendered by the browser like this. Roll mouse over list items to see the hover state in effect.

Basic CSS rollover menus like this are pretty easy to create yourself, but for more advanced menus, with nesting and “flyout” items, we strongly recommend using a pre-fab CSS menu solution – that particular wheel has been invented many times over. A lot of CSS positioning is required, and it’s very difficult to make them work properly across all web browsers. Try Listamatic for a great collection of free CSS menuing systems.

Tables

On the internet of the 1990s, web developers used HTML tables to lay out pages. This was very convenient, but led to exactly the mess we described at the beginning of this tutorial – tons of display-oriented code intermingled with the true markup of the page. This made redesigning web sites very difficult, as well as difficult to use by assistive technologies such as screen readers for the blind.

When CSS came along, developers had to learn an entirely new way of laying out pages, using CSS rather than tables. People started thinking of HTML tables as “the wrong way to do things.” Well, yes and no. It’s true that you really, really shouldn’t be doing page layout with tables unless you want to create an unmaintainable rat’s nest of code. But you should continue to use tables for displaying tabular data, such as charts, schedules, budgets, or anything else that is naturally tabular. This section is about styling legitimate tables, not page layout (we’ll cover that in our CSS 201 tutorial).

In the example below, we’ve created a simple table of staff contacts. We’re showing both the HTML and the corresponding CSS so you can see how they relate to one another. For the most part, all of the CSS rules are things you’ve already encountered in this tutorial. The most significant new item is the border-collapse:collapse property. This is used to make sure that any overlapping borders truly overlap one another, rather than appearing side-by-side. Also note the use of the “dotted” bottom border property on normal cells, which makes those rows a bit more elegant.

Perhaps the biggest difference is that with HTML tables, you’re forced to either show or hide all of your borders – you either get a grid or you don’t. With a CSS-based table, we’re able to enable an outside border for the whole table and for the header row, but only a bottom border for the table cells. This gives the appearance of having rows but no columns, which is nice. Notice again the use of nested selectors, so we can attach styles to cells and rows of just this table, not all tables that might appear on the page.

Using External Stylesheets

At the beginning of this tutorial we showed you how to “inline” styles, attaching them directly to an element on a page. While this works in a pinch and actually makes sense to do in certain circumstances, for the most part you’ll want to avoid that technique, since you end up adding stylistic information directly into the document, sidestepping one of the major advantages of using CSS.

Throughout most of the tutorial, we’ve been adding style rules to a “styles” block at the top of your document’s HTML. That’s much better, but really only makes sense for single-page sites. If you have a three-page site (or a 3,000-page site), do you really want to reproduce (and keep updated) the style data on every single page? Of course not.

The real win is in using a single stylesheet to control visual display for an entire site. That way you have just one place to make style changes, and those changes will be reflected across your entire site immediately, no matter how large it is. Here’s how:

Create a new document in your site’s document root, called styles.css (or anything you like). Copy the style rules out of the top of the document you’ve been working on and into the new file. Copy only the actual style rules, NOT the lines:

Save styles.css, then remove the entire style block from the top of the HTML document. Now, paste this somewhere in the section of your HTML document:

Obviously, edit /path/to/styles.css to match the actual path to the stylesheet on your site. If you don’t understand relative paths, just make sure the stylesheet is in the same folder as the HTML document and refer to it as simply “styles.css.” Reload the web page, and all of your styles should still be intact, even though there’s not a shred of CSS in the entire HTML document.

OK, here comes the cool part. Save your existing HTML document with another filename, and make some changes to it. Create standard links between the two pages. Load the new document up in a browser, and bingo – it will have all of the same styles. Click back and forth between the two to verify that the styles are identical between the two.

To use a site-wide stylesheet, all you need to do is link every document on your site to that central stylesheet and you’re in business. Change something in the stylesheet, and all pages are updated automatically.

You should now be able to do basic stylistic decoration of your web pages, without adding any stylistic information to the document itself. Congratulations! Now it’s time to move on to CSS page layout. We’ll cover that in our next tutorial, CSS 201 (coming soon). Until we’ve got that online, please read Creating a CSS layout from scratch.

About this Tutorial

About…

Republishing Policy

This content may not be republished in print or digital form without express written permission from KDMC. Please see our Content Redistribution Policy at kdmc.berkeley.edu/license.