Roger Johansson, 456 Berea Street
Warning! Old content ahead. The latest update was 2008-11-01.
In the early days CSS was used mostly to specify font properties. CSS support in browsers has been mature enough for several years now that it can be used to control the entire layout of a document. However, to do this efficiently requires a somewhat different approach than when tables are used to control layout.
Structured, semantic XHTML is necessary for CSS to be able to control layout in an efficient way.
As mentioned earlier, browser support for CSS has improved a lot in the last few years. Unfortunately all browser vendors haven’t been equally interested in implementing CSS fully and properly, so the level of support varies from browser to browser. On top of that there are software bugs that make browsers act in ways they shouldn’t be.
Currently (2008), the web browsers that have the best CSS support are:
Internet Explorer doesn’t yet (as of version 7.0) have the same level of CSS support, but it will let you do most of the basic stuff, though often in a buggy way.
Since currently a majority of people use Internet Explorer for Windows you will often have to let that browser be the lowest common denominator. That does not mean that you cannot or should not use the abilities of browsers with better CSS support to enhance the design for them. Doing so is fine as long as it does not make your site unusable to people using less capable browsers.
It’s important to stress that people using old (obsolete) browsers and browsers that by design do not support CSS must not be locked out. In the nineties, browser sniffing was a popular way of redirecting people using the “wrong” browser (normally anything but Internet Explorer for Windows) to a page that told them to upgrade their browser to gain access to the site.
These days you can handle unsupported browsers in a better way. One big advantage of using logical, semantic HTML is that it makes documents accessible and usable even without CSS. The presentation – the way the document looks – won’t be the same as in a supported browser, but the content will be there. In most cases, for most visitors to a site, the content is actually more important than the way it is presented. That’s why it is better to send an unstyled page to unsupported browsers than to lock them out of the site.
There are different ways of doing that. One of the most common ways is to use @import
to link to the associated CSS file. Netscape 4 and older browsers don’t understand @import
and will not import the CSS file.
There are plenty of ways to hide certain CSS rules from web browsers. The thing most methods (“CSS hacks”) for hiding CSS have in common is that they are based on bugs in the way browsers interpret CSS code. This means that there will always be a risk that a browser update fixes the bug that is used to hide CSS from it, but not the CSS problem that was the reason for hiding certain CSS from that browser. So the less you rely on CSS hacks, the better.
Obviously you can use server side technology to do a browser check and then send different CSS files (or none at all) to different browsers. If you do that you will have to make sure the detection script is kept current to avoid sending the wrong CSS file when a browser is updated or a completely new browser is released. You should also know that browser sniffing is fragile and error-prone since there is no guarantee that the browser is what it claims to be.
There are several ways of applying CSS to elements in an HTML document.
There are several advantages to keeping all CSS rules in one ore more separate files. The HTML documents become smaller, CSS files are stored in the browser cache and will only need to be downloaded once, and you only need to edit a single file to change the presentation of an entire website. An external CSS file can look like this:
h1 { font-size:2em; }
Note: there should be no style
element in an external CSS file.
You can link a CSS file to an HTML document by using a link
element:
<link rel="stylesheet" type="text/css" href="styles.css">
or by using an @import
rule in a style
element:
<style type="text/css"> @import 'styles.css'; </style>
By using the style
attribute, you can apply CSS directly to an HTML element:
<h1 style="font-size:2em;">Heading</h1>
This should be avoided since it mixes structure and presentation.
Internal CSS is contained in a style
element, which in turn belongs in the document’s head
element:
<style type="text/css"> h1 { font-size:2em; } </style>
This should also be avoided, since it is best to keep HTML and CSS in separate files.
A CSS rule consists of a selector and one or more declarations. The selector determines which HTML element or elements the rule affects. Each declaration consists of a property and a value. The declaration block is surrounded by {
and }
, and each declaration ends with a ;
(semicolon).
A simple CSS rule looks like this:
p { color:#0f0; font-weight:bold; }
In this case, p
is the selector, which means that the rule will affect all p
elements in the document. The rule has two declarations which together will make the text in all p
elements green and bold.
For a more detailed description of CSS rules, see for example CSS Beginner’s Guide, CSS from the Ground Up or a CSS book.
When starting out with CSS, it’s common to make the mistake of using unnecessary HTML elements, superfluous classes, and extra div
elements. This doesn’t necessarily mean that the code will be invalid, but it counteracts one of the reasons of separating structure from presentation; to get simpler, cleaner markup.
An example of using unnecessary HTML elements:
<h3><em>Headline</em></h3>
If you want to make the headline italic, use CSS to restyle the h3
element:
h3 { font-style:italic; }
Superfluous usage of classes can look like this:
<div id="nav"> <ul class="navlist"> <li class="navitem"> <a class="navitemlink">Lorem ipsum dolor</a> </li> </ul> </div>
This will do fine:
<div id="nav"> <ul> <li> <a>Lorem ipsum dolor</a> </li> </ul> </div>
To control links in the div
element with the id nav
you can use descendant selectors in the CSS code. In this case it could look like this:
#nav a { /* rules */ }
In many cases CSS can be used to style logical HTML the way you want without having to add any extra markup. However, there are cases when adding some extra code is worth it.
Obviously, once you start using CSS seriously, you will eventually run into problems of some kind. Some problems may be caused by misunderstandings, others by unclear specifications or buggy browsers.
The CSS Crib Sheet is a collection of good advice, compiled by Dave Shea. Here are some of the most important tips plus a few more that aren’t in the CSS Crib Sheet.
Validate first: When debugging, start by validating both HTML and CSS. Many problems can be caused by invalid code.
Test in the most advanced browser first, then make it work in the others: If you’re using an old browser with a bad and/or erroneous implementation of CSS while you’re testing, your CSS will be adapted to that browser’s implementation. When you test in a more advanced browser, chances are things will not look the way you intended. It’s better to first make it work in the most standards compliant browser, and then worry about less able browsers.
In other words, do not use Internet Explorer as a reference.
Understand the CSS box model: To get an element’s actual width or height, you add its padding
and its border
to its width
or height
. In Internet Explorer 5.*/Win (and later versions of IE when they use quirks mode), padding
and border
are included in the supplied width
or height
.
Suppose you have the following CSS:
.box { width:300px; padding:20px; border:10px solid; }
The total width of the elements this rule is applied to is 360px.
10px + 20px + 300px + 20px + 10px = 360px
In Internet Explorer 5.*/Win, the total width is 300px, and the width of the content is 240px.
300px - 10px - 20px - 20px - 10px = 240px
To work around this problem, you can either use a CSS hack to feed different values to the browsers that get this right and those who get it wrong, or you can avoid specifying both width
and padding
or border
for an element.
For more thorough explanations of the CSS box model, see Box model and Internet Explorer and the CSS box model.
Specify units for numerical, non-zero values: CSS requires that units are specified for properties like width
, height
, and font-size
. An exception from this is when the value is 0 (zero). In that case, no unit is necessary, since zero is zero, no matter what the unit is.
Understand floats: The concept of floats can be hard to understand, but is very important since it is frequently used to in CSS based layouts. Some very good articles on floats are Containing Floats, Floatutorial, and Float Layouts.
“LoVe’s Hurts Fade Away”: Define pseudo classes for links in the order Link, Visited, Hover, Focus, Active. Eric Meyer explains why the order matters in Link Specificity, Ordering the Link States, and Who Ordered the Link States?.
“TRouBLed”: When using shorthand to specify an element’s margin
, padding
or border
, do it clockwise from the top: Top, Right, Bottom, Left.
Name classes and IDs by their function, not by their presentation: If you call a class .smallblue
, and later decide to make the text big and red, the class name will be confusing. It’s better to use names that describe function or structure, like .copyright
or .important
.
Case sensitivity: Values of the HTML attributes class
and id
are case sensitive when used with CSS (see CSS2 syntax and basic data types).
Element names are case sensitive when used with XHTML served as XML, but not when used with HTML or with XHTML served as text/html
.
Check your IDs: Only one element in a document can have a certain value for the id
attribute, while any number of elements can share the same class
name.
Use only allowed characters for class
and id
: Class
and id
names can only consist of the characters [A-Za-z0-9], hyphen (-), and underscore (_), and they cannot start with a hyphen or a digit (see CSS2 syntax and basic data types).
Comment correctly: CSS comments start with /*
and end with */
:
/* This is a comment */
There are many examples and step-by-step tutorials on how to use CSS for layout. A good advice is to start with a simple layout, learn how it works, and then move on to more advanced layouts.
Eric Meyer describes four ways of hiding CSS from certain browsers.
A large collection of techniques that can be used to hide CSS from browsers.
A document on different ways of enhancing the experience for people using a modern browser.
An explanation of, among other things, CSS import and media types.
With the help of his readers, Dave Shea has made a list of practical CSS tips.
John Gallant and Holly Bergevin explain how to write compact CSS.
A very good explanation of different CSS selectors and how they work.
An example of how to create a simple layout with a header, two columns, and a footer.
A collection of links to different CSS layouts.
Comments, questions or suggestions? Please let me know.
© Copyright Roger Johansson