Skip Navigation
The Illuminating Web

Getting It All, With CSS

Early Draft

In this three part series we will explore the potential of Cascading Style Sheets (CSS) to make life simpler. While it is true that CSS support is still not a guarantee among everyone in your web audience, the availability is high enough that most users that would benefit from it already have it, and those that do not have it may be better served by unstyled, but well structured content.

Part 2 : Layout and Structure with Divs and Spans

CSS is a large and very complex specification. This lesson goes into more syntactical detail and illustrates every day application with the div and spans elements. For a more HTML/Tag based primmer, and an introduction to CSS, please see Part 1.

What You Will Need

  • A Text Editor; WYSIWYG HTML editors are fine, but all you really need is a text editor. Understanding CSS requires working with the tags.
  • A Browser; Mozilla Firefox, Opera 8, or Safari are recommended. Internet Explorer is always important to test in (since most people use it), but it is not very compliant with the specifications.
  • These Files

What You Can Learn

  • The basics of writing CSS Style Sheets
  • How to position elements
  • How to use spans and divs to control appearance
  • Basic CSS formatting and positioning

What You Won't Learn

  • HTML in depth
  • DHTML, pop-up menus
  • Advanced CSS


Building a Page

In this tutorial we will build an HTML page. The page will have Navigational elements and content. It will start out plain and we will then explore various ways to style it with CSS.

Step 1 - Prepping a Document

If you already know CSS Skip to Step 3 .

What is CSS? CSS stands for Cascading Style Sheet. Put simply, a style sheet is a specification for how something should appear. Traditionally, style sheets were template examples of how documents should look. They are created to improve consistency from document to document. When dealing with stylesheets for HTML, the style sheet is not an example, but a set of formatting rules that are applied to the HTML tags. For a more in depth discussion of HTML see the previous tutorial. Style sheets for HTML are said to be cascading because the formatting rules have a system of priority that determines which rules apply to each element. There are default rules for the display of each element determined by the browser. These rules can be change based on html tag names, tag attributes, and relationships among tags. More specific rules override more general ones, and rules declared locally override global rules. This concept of cascading may seem CSS seem complex, and it can be that way at times, but in general the cascading rules make CSS easier because it reduces the number of rules that must be written.

Let's begin with a plain and relatively empty HTML file:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ""> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Untitled Document</title> </head> <body> </body> </html>

All web pages need certain information to fulfill certain expectations on the part of the user. Pages will contain text and images, some of these will be links to other pages. Pages need to give the user a sense of location, where they are and where they can go. To begin, insert some basic content into the body tag:

<body> <p> Logo </p> <a href="">About Myself</a> <a href="1.html">Friends</a> <a href="2.html">Family</a> <a href="3.html">Portfolio</a> <h1> About Myself </h1>
<p> A paragraph goes here </p> <p> Another paragraph </p> <h2> Other Information </h2> <p> Another paragraph </p> </body>

This is pretty minimalistic content, but will suffice for the first example. Viewing this page in a browser yields very lackluster results. By the end of the tutorial we will turn lackluster into block buster.

There is not very much that can be done with the existing tags to spruce them up, but they will be useful for learning the basics of CSS with a few small attribute changes:

<body> <p id="1" class="logo"> Logo </p> <a id="2" class="here first" href="">About Myself</a> <a id="3" href="1.html">Friends</a> <a id="4" href="2.html">Family</a> <a id="5"href="3.html">Portfolio</a> <h1 id="6"> About Myself </h1> <p id="7" class="first main"> A paragraph goes here </p> <p id="8" class="main"> Another paragraph </p> <h2 id="9"> Other Information </h2> <p id="10"> Another paragraph </p> </body>

The added attributes are IDs and Classes. Both are used to identify tags and assign style sheet rules. The main difference is that the ID attribute of a tag must be unique in the whole document, no two IDs should be identical. Many tags may share the same class, even if they are tags of a different type. Also, a tag may only have one ID, but it can have multiple classes if they are space delimited. Thus spaces are not allowed in class names, and they are also not allowed in ID names.

Next give the document a title. All documents must be properly identified by a title.

<head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>An simple page with CSS</title> </head>

Next add a style tag to the document. This will contain the CSS that formats and positions the form. It can go anywhere in the head, but after the title is a preferred location.

<head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>An simple page styled with CSS</title> <style></style> </head>

For absolute clarity, the "type" attribute of the style tag can be set to indicate that is it a CSS rather than some other, less standard, style specification. This may not be necessary, but is required by the specification.

<head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>An simple page styled with CSS</title> <style type="text/css"></style> </head>

The style tag is new to HTML, relatively speaking. Because there are old browsers that will not understand it, the contents should be wrapped with a comment tag. This will effectively hide the contents from older browsers, and newer browsers know to ignore the comment tags:

<head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>An simple page styled with CSS</title> <style type="text/css"> <!-- --> </style> </head>

At this point your document should look like this. Now the document is ready to receive it's first style rules.

Step 2 - Writing CSS Rules

CSS rules are instructions that tell the web browser how to style certain tags. The most generic rules can apply to every tag, and the most specific rules can apply to only one tag. Style rules are constructed from two parts, selectors and declarations. Selectors tell the browser what tags the rule applies to and declarations tell the browser how those tags should look. Here is the anatomy of a style rule:

h1 {font-size: 0.9em;}

In the line above the red portion is the selector and the blue is the declaration. There may be multiple selectors in a single rule, each separated by a comma:

h1, h2, p {font-size: 0.9em;}

The above rule would apply to h1, h2, and p tags. There are a variety of syntactical options for specifying tags in the selector, such as tags with certain IDs, classes, or relationships to other tags. These will be described later.

Declarations are always wrapped with curly brackets (so that they can be distinguished from selectors). Declarations can be further broken down into two components, properties and value. The property and value are separated by a colon. If there are multiple declarations in a rule they are separated by semicolons, and it is not uncommon to see the last declarations followed with semicolons (though this is completely optional).

h1, h2, p {font-size: 0.9em; color:#C00; line-height: 2em;}

The example above illustrates multiple declarations. Properties are in green and values are in pink.

Add the following rules into the style tag .

<style type="text/css"> <!-- h1 {font-size:1.5em; clear: left;}
h2 {font-size:1.25em;}
a {display:block; float:left; margin: 1em; border: #00F 1px solid;}
--> </style>

By this point your document should look like this.

Notice how the font size of the header tags has been reduced and the links are now more spaced out and enclosed by a box. The exact effects that these rules have had on the document will be explained in the next section. Before more complex styles can be applied selectors and declarations need to be explained more in depth.


There are many ways to formulate selectors. Some may not work in mid-generation browsers (IE 5 for example) or may even be unreliable in modern browsers (Firefox ignores some empty tags when they should still be styled). The following examples illustrate commonly used selectors and their application:

* {};

This selector (above) would apply to all tags. The * selector means any tag.

p {};

When a tag name is part of the selector it applies the rule to tags with the matching name. The rule above applies to all paragraph tags.

p, h1 {}

As has already been illustrated, multiple selectors can be grouped in the same rule by comma separating them.

p#1 {color:#C00; }

The pound sign indicates a specific ID attribute. This can be coupled with a tag name, but it is optional:

#1 {color:#00F; font-size:2em;}

In the first example (p#1) the style would only be applied to the tag with matching id = 1 if it also happened to be a p tag. In the second example (#1) the style would apply to an element with id = 1. It should be noted that #1 selector is exactly the same as the selector *#1. The p#1 syntax is rarely used because it is overly specific, but has some useful in a handful of very specific situations. p#1 rules take priority over #1 rules. Considering both rules above if the tag with id= 1 is a paragraph tag it would be red (#C00 is shorthand for #CC0000, or NC State Red) and double the size of regular text on the page. If any other tag has the id = 1 it would be blue and double sized. {}

The class attribute can also be used to target one or more tags. The advantage to using the ID selector is that it creates a rule very specific to one tag and therefore of high priority. The class tag on the other hand has a lower priority, but still overrides rules that apply to all tags with the same name. In the above example p tags with class = red would match.

.red {}

Just like the tag name is optional for selectors targeting ID'd tags, classed tag names are also optional. The same rules of priority apply. Anything specified in will

.red.dead {}

In the sample HTML file, there are some tags with multiple classes. When a tag's class attribute has multiple "words" separate by spaces, each word is one class name and the tag is a member of each of the listed classes. For example:

<p class="red dead revolver">

is a p tag that would match the above rule. When multiple classes are listed in a selector they are all required. a rule for .blue.dead would not match the same p tag.

p b {}

When tag names are separated by spaces ( with no commas between them) they indicate a hierarchy. In the above example the selector matches b tags inside of p tags, or literally "p's b descendants". These b tags may appear anywhere inside any p tag. They may be direct descendants (<p><b></b></p>) or indirect descendants (<p><a><i><b></b></i></a></p>). If the rule were b then it would be b tags anywhere p tags that have the class = "red" . This would be very different that the selector p which would match b tags with the class = "red" that are anywhere inside any p tag.

p > b {}

Another way to indicate hierarchy is to specify direct descendants, or children. Unlike p b, p > b means b tags that are directly inside of p and not surrounded by any other tag. p > b applies to <p><b></b></p> but not <p><a><i><b></b></i></a></p>. direct descendant rules are more specific than the regular (any) descendant rule, so it has higher priority. > * > b {}

It is possible to chain direct descendant selectors and mix them with other selectors. In the above example b tags that are the "grand child" of a p tag with the class = red will be affected. This rule would apply to <p><i><b></b></i></p>, but not <p><b></b></p> or <p><a><i><b></b></i></a></p>. The star means that any tag may be the direct parent of b as long as p is the grand parent.

p * > b, p > * b{}

These two types of selectors can be combined. In the example above both selectors mean the same thing. They both mean any b tag that is an indirect child of p and not a direct child. The first selector states that b may be the direct descendant of any tag that is in any way descended from p. The second says that b may be any descendant of a tag that is directly descended from p. As an exercise in logic, think about why those two selectors are the same while, p i > b and p > i b are not.

h1 + p {}; h1 + * {}; h1 + p > b{};

Another way to use tag organization is sibling order. Tags that are direct children of the same tag come one after the other. In the first selector above, the rule is applied to any p tag that comes directly after an h1 tag. Since there is no other hierarchy specified by the selector, any tag could be the parent.

The second selector applies to any tag that happens to appear directly after an h1. If both rules are in the same style sheet the rule specifying p overrides the rule allowing any tag (when the tag in question is a p tag).

The third rule chains sibling order with descendant hierarchy. b tags that are direct descendants of p tags that directly follow h1 tags are affected.

While all of these possibilities may seem overly complex, it can be surprising how power and useful this flexibility can be when styling content. Using hierarchy and sibling order can eliminate the need for added class and id attributes, which can be a pain to apply and maintain manually.

A special type of selector is used for link tags to replace the need for body tag link color attributes (which are now deprecated) JavaScript rollovers.

a:link {} a:visited {}

The first two selectors apply to links that have been visited or not. They are called pseudo-classes, and these two only apply to link (a) tags. {}

Just like all others, pseudo-classes selectors can be combined with other selectors. The above rule applies to links that have been visited if their class attribute = red.

a:active {}; a:hover {}; a:focus {};

There are three other pseudo-classes that may apply to more than the a element. The active class is for elements that are currently "selected", for example with the mouse button held down. Hover applies to an element where the mouse it over it, and focus applies to keyboard focus. These effects can be used to replace javascript rollover effects in some cases. Examples will be included below.

There are also a few other selectors that can be employed. They may or may not work with current versions of some web browsers since they are very new. More information about selectors can be found at the W3C web site.


The other side to style rules are the declarations. There are far too many properties to list here, but some of the more important ones for this workshop are:

display: inline | block;

Illustration showing inline and block elements. The inline element flows around a block element with it's top right corner and bottom left corner.The primary distinction between elements is whether the are inline or block elements. There are some other values for the display property, but they are not as commonly used (and many are not well supported yet). Block elements can have fixed or variable width and height, margins and padding, and can float. In general, much more control can be exerted on block elements, but their contents are effectively boxed in and so they must flow around other elements as one entity. The shape of their box is be determined by the style sheet, by their contents, or by some negotiation between the two.

On the other hand, inline elements limit what properties can be controlled by the style sheet. Some properties are dictated by the layout and behavior of other elements on the page, and so they cannot be controlled by the style sheet. Inline elements can "wrap around" line by line, flowing line by line around other elements and are not boxed in.

There are very complex rules for how these two values for display interact and affect elements, but in general inline elements can be considered to be wrapping and block elements are wrapped around.

position: static | absolute | relative | fixed;

While most content is styled in the static (default) position, meaning in relation to it's position in the tag hierarchy, there are ways to pull tags out of the standard flow for the purpose of positioning. Content can remain in the normal hierarchy, but be moved relative to it's default position using relative positioning. In both of these position modes the element can affect and be affected by the flow and positioning of the surrounding elements.

It is possible to take elements out of the display hierarchy and position them completely manually. When this is done, extra care must be taken to ensure that the move elements do not cover up other elements on the page since they will no longer flow around or affect other elements. Absolute positioning generally sets the position relative to the web page page borders while fixed positioning sets the position relative to the window borders ( not implemented in some browsers). For the purpose of printing, the fixed positioning applies to each printed page rather than a single browser window. Absolute positioning has the opposite effect on print media, where the element would appear on one page, being positioned in the overall printed document.

float and clear

Illustration showing floating elements. Three left floating elements are wrapped by an inline element. The first two appear on the same line but the third appears on it's own line due to limited horizontal space..The two other more complex properties that this tutorial uses are floats and clears. Elements that are floated are moved to the left or right and other content moves out of the way. The first elements to float (appearing first in the HTML) move farthest in their target direction and the floating elements that follow them stack horizontally until there is no more room. If room runs out floating elements move to the next line and float in their target direction until there is available space on a line. Elements that do not float effectively wrap around floating elements with what space is left, but bock elements wrap as a whole block, not as individual lines like inline elements do.

Illustration showing clearing elements. Three left floating elements each float to the far left on their own line because they clear each other.The clear property is used to ensure that the targeted element start it's own line rather than stacking to the left or right of another element. Clear also prevents wrapping in that direction. In the two illustrations for floats and clear, the floating elements in the illustration to the right do no clear. the box labeled left 3 wraps to it's own line because of space limitations. In the illustration on the left, each left floating box is on it's own line, because each one clears the other.

Floating a clearing can be confusing rules. The important thing to keep in mind is that elements will float to either side of no-floating elements they appear before, but not after. If a float appears after a non-float, it will clear the non-float. Floats don't clear other floats in this same way unless they are set to clear to boxes floating in that direction. When floating boxes in both directions the way floats and clears work can become confusing. To make matters worse there are bugs in the way browsers implement various combinations of floats.

One important thing to always remember about floats is that they must have a set width. They will behave unpredictably if a width (fixed or relative) is not set because CSS does not define the behavior of such boxes. Floatutorial is an excellent resource for learning more about how floats and clears (as well as inline and block elements) work.

background : background-color | background-image | background-repeat | background-attachment | background-position

The background of any given element (inline or block) can be changed by this property. There are separate properties for background color, background image, position, etc. The background property is a shorthand notation that can alter any of the background properties.

border: border-width | border-style | border-color

Each element may also have a border. These borders may decorate content, but are also an excellent tool for debugging code.

margin and padding

Elements also get margin and padding properties to space them out from other elements. Margins are buffer space outside the box surrounding the element. Margins overlap with other margins, but not the actual boxes of other elements. For example, if two elements have adjacent margins and one is 10px and the other is 20px they will be spaced 20 pixels apart (the larger of he two margins will be the total margin).

Padding is space inside an element's box. Padding stacks with margins to space out elements, so if the elements in the example above also have a padding of 5 pixels the contents of the two elements will appear to be spaced 30 pixels apart (5 plus the greater of 10 and 20 plus another 5).

color, font, height, and width

Four other very common, and fairly intuitive properties are the ones that determine font color, font styles, and the height and width of each element.

These selectors and properties form the basis for most of the remaining tutorial. Anything not explained in the following sections can be referenced above.

Step 3 - Structuring the Content

With the class and id selectors explained in the previous section there are many more ways that the existing content could be styled. The main limitation is that there are not any boxes that exists in the current markup that structure it so that the elements can be grouped and styled. For example, to draw a box around the h1, p, and h2 tags that follow the a tags, there would need to be an element that wrapped these tags, and not the a tags. Adding div tags to the HTML provides additional boxes that can be used to style content. Divs are by default block display elements, and so they are ideal for drawing boxes around grouped content. The div tag has no real semantic meaning other than to divide and group content. Span tags are the other type of structural tag in HTML with no specific semantic meaning. Span tags are inline, so they are idea for styling text and other elements that need to wrap. Because spans are inline there are some styles that will not apply to them.

Replace the existing body with this new content that has divs and spans to better control the content:

<body> <div id="head"> <p id="1" class="logo"> Logo </p> <a id="2" class="here first" href="">About Myself</a> <a id="3" href="1.html">Friends</a> <a id="4" href="2.html">Family</a> <a id="5"href="3.html">Portfolio</a> </div> <div id="content> <h1 id="6"> About <span class="me">Myself</span> </h1> <p id="7" class="first main"> A paragraph goes here </p> <p id="8" class="main"> Another paragraph </p> <h2 id="9"> Other Information </h2> <p id="10"> Another paragraph </p> </div> </body>

To take advantage of the new tags and see how some of the properties work, replace the current style with this new code:

<style type="text/css"> <!-- h1 {font-size:1.5em; clear: left;}
h2 {font-size:1.25em;}
a {display:block; float:left; margin: 1em; border: #00F 1px solid;} #head{background: #EEE;}
#content{background: #DDD;}
--> </style>

After adding this CSS you may notice that the backgrounds do not match up as one might expect. Something is amiss, but in order to find out what is going on it will help to see where all the boxes are being drawn:

<style type="text/css"> <!-- h1 {font-size:1.5em; clear: left;}
h2 {font-size:1.25em;}
a {display:block; float:left; margin: 1em; border: #00F 1px solid;}

#head{background: #EEE; border: #000 1px solid;}
#content{background: #DDD; border: #C00 1px solid;}
.me{font-weight:normal; border: #00C 1px solid;}
h1{border: #0C0 1px solid;}
.logo{border: #CC0 2px solid;}
--> </style>

Based on the appearance of these borders, it would seem that the a tags are inside of the div tag with id=content, but what is actually going on is a peculiarity of floats.

When floats appear inside of non-floats, the height of the parent (non-floating) element does not expand to completely surround the child float. In this case floating the header div will solve the problem. Remember that floats must have a defined width.

a {display:block; float:left; width:20%; margin: 1em; border: #00F 1px solid;} #head{background: #EEE; border: #000 1px solid; float:left; width:100%}

Obscuring Images, Easier Accessibility

One major benefit to using CSS for layout it that it obscures images used to generate site layout all together. With table layouts, images are included in the HTML of the document and must have alternative text attributes provided. These are easy to forget, and many accessibility checkers will assume images larger than 5 to20 pixels in any direction are non-spacers and flag warnings or errors when these images have empty alternative text (alt="") even though this may be the correct handling.

With CSS the opposite risk is present. It is all too easy to include images in the site's layout that may provide some important context. What constitutes important information can at times be highly objective, but in general this means information that is not otherwise represented on the page.

Take for example CSS Zen Garden. While the site is totally accessible to users that cannot see it, the site's navigation makes little sense. visually impaired users experience the same content, verbatim no matter which style sheet they select. The content is there, but the effect and whole purpose of the site is lost.

On a normal site, this is not the dellima. Images that go along with content should be included in the HTML and not the style sheet. Images that do not go with the content should not be represented.

Take for example the NC State Homepage. There are a variety of photos on this page, and while they have significance (the designers more than likely spent hours debating which images to include based on aesthetic qualities, representativeness of content, and relevant subjects) they do not really add anything to the content of the page. The alternative text in this image is:

image of the NC State Bell Tower with the achieve logo beside it.

"Achieve! The Campaign for NC State"

but in the HTML of this tutorial the more appropriate alternative text is:

"image of the NC State Bell Tower with the achieve logo beside it."

In the original page the fact that the bell tower is in the picture is insignificant. It is merely eye candy. But in the context of this tutorial the fact that the bell tower is in the picture is significant, so it's presence must be included in the alternative text.

On the original page the significant part of the image is the text beside the Bell Tower. It is important because the image is also a link to the Achieve web site. When making the transition to CSS design, one of the first things to consider is the advantage of moving to text based links instead of the traditional images. Thanks to font anti-aliasing and ability to apply backgrounds to links (which can be swapped with the hover and focus pseudo-classes) very sophisticated looking navigation can be achieved with text. Another clever alternative is to place text in the link, but then move that text off screen and place the same words in an image used as the link tag's background. While this technique is more complex it is very effective and accessible.

Example 1 - Text + Roll-over Background

The new College of Engineering Templates (still under development) use a real text + roll-over background to make easy to manage accessible links. In the past changing site navigation was a pain because graphics had to be altered in fireworks, exported, and then made into a roll-over image in a library item in dreamweaver. These library items then had to be updated throughout the entire site and this takes a while because Dreamweaver has to re-write javascript code on each page for the roll-over images to work correctly.

The new design uses easy to manage text, so the image editor step and the scripting can both be bypassed:

<div id="n1main" class="container">
<div class="left"><div class="right"> <!-- begin primary navigation area --> <a id="homelabel" href=""> <span class="unbold">NC State</span> Engineering </a> <a href="">News</a> <a href="">Academics</a> <a href="">Research</a> <a href="">Extension</a> <a class="here" href=""> Administration</a> <!-- end primary navigation area --> </div></div></div>

These simple image tags are styled with this code (#n1main and other #n1 styles) to add in the backgrounds and control the layout (floating left to line them up horizontally).

Example 2 - Hidden Text + Roll-over Background

The other method for doing this is to wrap the text inside the a tags with a span:

<a href="..."> <span class="hide">Link Text Not Seen</span> </a>

The span tag can then be positioned of screen:

.hidden{ position: absolute; top: -999px; left: -999px; }

Otherwise the images are styled just as in the first example. The main difference (and disadvantage) is that each link has to be styled individually so that it has it's own images for the active and in active states.

9 Panel Layout

The 9 panel layout is a method of nesting div tags so that a variety of images can be applied to one block of content. This effectively skins the block in almost any way conceivable.

This layout method is one type of box model. A box model is a way of wrapping content with tags so that it can be structured and/or styled. CSS Zen Garden has a uniform box model that all of the designers must follow, that is why the different CSS layouts can be applied to the same HTML. Box models add elements to a page that are available to be styled. These elements may be content or structure elements that the designer count on being there: div, span, p, and header tags with specific classes and ids for example.

Box models designed for one specific layout can be very simple and minimalistic. The 9 Panel Layout has more boxes than would typically be used. Designers have the option of removing the unused boxes or keeping them incase the layout of the site does change and more boxes are needed. The extra boxes constitute negligible increase in file size and even with so many redundant div tags the file size is generally much smaller the table based layout.

One advantage of the 9 panel layout is that content can easily move from one design to another since the box models are always the same. This improves style sheet re-use and makes custom layouts that are "one off" the original design easier.

In the new template, the silver bar at the top let hand corner of the content area is styled with code from this file (#n4 styles). It uses the same box model as all other navigation areas and as the content areas. If there is ever a need to change the layout of n4 to match one of the other areas, or vise versa, the transition is as simple as changing the selectors to apply the styles to the correct tags.


Floats and clears could easily be considered one of the mos tricky features of CSS. They are complicated to understand and not 100% consistent across the different browsers yet. As implementations improve, so too will the ease of use with these two properties.

Another thing to keep in mind as the arrival of XHTML 2 approaches is that this new specification will bring a whole new level of sophistication to structure in HTML documents. The current tags for structure are semantically poor, and with good reason, they were needed as a flexible place holder until a more sound and widely agreed upon set of semantically rich tags were ready. XHTML 2 is going to present a steep learning curve and will likely take a couple of year to be widely supported even after the official specs are done. The fortunate thing is that CSS and XHTML specifications are separate entities and CSS 3 does not appear to be shaking as many foundations.





Getting It All, With CSS

Part 1
Printer Friendly:
1.1 1.2 1.3 1.4 1.5

Part 2
(February 2005)

Part 3
(Summer 2006)

Other articles

The Year of the
Cascading Style Sheet