Home » Blog » Why Programmers Suck at CSS Design

Why Programmers Suck at CSS Design

October 27th, 2008

If I had a dime for every time I heard a web programmer apologize for the way his/her pages looked before revealing them, I certainly wouldn’t need to work anymore.

As with color picking, I think that programmers tend to avoid doing certain things not because they are inherently bad at it, but because they don’t know how to proceed. They find themselves in an uncharted and foggy territory, without a map, no sense of direction, and with a limited ability to know if they’re getting any closer to where they want to be. Also, when they talk to people that don’t share such problems and find it all too natural and obvious, it’s hard for the two to communicate in terms that make sense to a programmer.

There is a general tendency to believe that programmers can’t style things because they have no style themselves. Yet, all of them will be able to tell you very quickly which one of two designs they like the best, even if they generally can’t verbalize why. This seems to be an indication, at least to me, that some aesthetic sense is inherently present in all of us; what’s different is the ability to turn vague notions and gut feelings into actions and reusable procedures. And that’s where the problem is.

Don’t get me wrong: I don’t think anybody can design something truly beautiful, innovative, simple and that can resonate with a big percentage of the population. Far from it.

I have a much simpler and humble goal here: give programmers some tricks and some advice in how to proceed to make their web pages look cleaner, more readable and, hopefully, more professional, elegant and original than before.

Disclaimer: what I describe here is one possible way to achieve my goal. I’m sure they are many more. I don’t consider my suggestions to be the best way to do anything, just that worked well for me. If you disagree with the way I solved things, please try to read past that and look at the general goal of empowering people that otherwise feel hopelessly lost. Achieving perfection or optimality is not why I’m writing this. Once people that felt hopeless can feel empowered, we can have a totally different discussion and I’d be very happy to discuss CSS tricks like a pro. But that’s another time.

My hope is to show people that feel CSS challenged that you don’t need to be an artist, know how to draw or even just pick colors, and certainly you don’t need to know how to use Photoshop to be able to come up with a nice, clean, readable and original layout.

So arm yourself with your favorite editor and your favorite browser and follow me.

Start by cleaning the slate

Some browsers ship with default stylesheets that are simply horrible. One notorious problem, for example, is the <table> tag that forgets to inherit font settings from its parents. Meaning that if you set the font size on the <body> tag, the content of your tables will still not change size.

My suggestion is to start your CSS file with this line:

@import url("http://yui.yahooapis.com/2.6.0/build/reset-fonts-grids/reset-fonts-grids.css");

This imports the Yahoo YUI reset CSS file in front of your own [of course, the version number for that might change, so check the YUI web site]. The above doesn’t work with old browsers (NS4 and IE4, for example), but we can safely ignore those now.

Note that I used @import in the CSS instead of multiple <link> declaration in the HTML. This makes your stylesheet easier to reuse (you don’t have to remember other CSS what it depends on, since it carries its dependencies with it).

The side benefit of this is that you get a bunch of definition of ‘grids’ which are a way to layout your page (for more info on how to use this, check the YUI grid web site).

Em vs. Px

We can talk about this forever, but you probably don’t care. My suggestion for you is to do the following: start your CSS stylesheet with

html {
   font-size: 62.5%;

This apparently bizarre number brings your standard font size so that 1em = 10px (This is because the default size for ‘medium’ text in all modern browsers is 16px). And from that point on, you can easily use ‘em’ all over your stylesheet, even if you wanted to use pixels, simply by dividing by 10.

This doesn’t mean that pixels have no use: I tend to use pixels for things like borders and for padding/margin of images that have fixed sizes. But never for fonts or for padding/margins around text.

It all boils down to this: using ems will make your life a lot easier when dealing with cross-browser and cross-OS font rendering issues, so stick with that and be consistent throughout your CSS design and you’ll skip all sort of pain later.

Pick your grid

Now that your HTML is clean and the base font size prepared, you have to decide how you want to layout the building blocks of your page (thinks like header, footer, sidebar, etc)

I use paper and pencil for this, or you can use a whiteboard. The idea is that you should try to fit the kind of content you’re looking to present and where it should be contained in the page. Don’t need to think fancy, just use rectangles and place a label inside the rectangle, that’s good enough. Don’t think about style and don’t think (much) about interaction, just what very basic building blocks you need. If you can only come up with header, footer and sidebar on the left, don’t worry, that’s pretty much all you need to start. If you come up with 100 rectangles, you’ve gone too far.

During this phase, you might realize that you need more than one page and that they look different. That’s ok. Don’t try to fit every possible thing into one design, it’s totally fine to have more than one template.

Once you know how you want to layout the page, you can use the YUI grid builder to try to come up with an HTML grid layout that mimics (roughly, don’t try to be precise at this stage) the layout you designed on paper before.

NOTE: a lot of HTML/CSS designers will cringe at the use of <table> for page layout control. I personally don’t. If one day all browsers support CSS3 and all the table-specific styling, I might change my mind, but right now my own personal strategy is “don’t use a table for horizontal placing unless you really can’t find a way to avoid it”. But whatever you do, make sure to use a different class for the tables you use for layout and for the tables you use as real content tables, for example <table class=”table”>.

Fill the content

Once you have your page skeleton, fill it up with content. One great helper is the Lorem ipsum generator that gives you some good content to fill your page with. Don’t use “aaa bbb ccc” or similar because it tends to spoil how the page will look and feel. Or cut/paste any Wikipedia article.

At this stage, make sure that you keep your HTML as clean as possible and that you include all possible things that you might want to use in your page, such as lists, tables, image figures, notes, blocks of code, quotations, inline code fragments and acronyms, bold and italic text, all various headings and lots of paragraphs of content. Anything that you think you might need, but not more. Remember: this is just a starting point and an exercise.

Try to use existing HTML tags instead of creating new ones using <div>s and <span>s with your own classes and try to minimize the creation of such containment tags (yes, even if you like to be “more semantic”, get over it). If you are thinking at Microformats or RDFa, don’t; at least at this stage: you can always go back and add semantic attributes to the HTML elements later. This is completely orthogonal to the choice of <p> vs. <div class=”paragraph”>.

The reason for this is that it makes the resulting CSS stylesheet much more portable, as in you can easily apply it to any web page and see how it behaves. This is something that you might not care about right now but you will be thankful about this in the future when you’ll have to start a new, similar design, and you can reuse your stylesheet as a starting point instead of having to cut/paste and tweak all the class-based selectors. I’m telling you because I made this mistake myself in the past and got burned by it big time.

Also, add IDs to HTML elements only for things that you know will appear once and only once in the page (say things like “sidebar” or “footer”, but not for “note” or “figure”). As a general rule, you should place a different ID in every one of those rectangle boxes that you drew in your paper layout. This allows you to easily ‘overload’ the style definitions for elements in those boxes.

Once you’re satisfied with your filled-up template (or you can use mine if you’re lazy), you need to tighten the bolts a little before you can safely start to style it. First, you need to make sure you have the right DOCTYPE declaration at the top of the page. There are many and they do different things on different browsers, but what’s important is that there is one that does the right thing on all of them and it’s

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

so place that at the very top of your template and you’re good (look here if you want to know more about this, but you can safely skip it).

Then another thing you might want to do if your content contains non-ASCII characters (or might in the future) is to specify the page encoding. You do this by adding

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

to the <head> of your HTML page (doesn’t matter where).

NOTE: if you don’t understand char encoding but you’re heard of UTF-8 and Unicode, DO NOT place UTF-8 in there just hoping that the browser will automagically interpret your page in the right way for international content. You have to make sure that your editor saves your HTML text using the UTF-8 encoding. This is why it’s a good idea to have at least a few non-ASCII characters in your templates. In case you’re not sure, leave it out and the browser will try to do its best to guess the encoding, but don’t complain if your internationalized characters get rendered all screwed up. Instead, go learn more about encoding.

Time for Style

Now you have your HTML page, it has the right skeleton, the right area divisions, the right clean HTML content, and it renders the same in every browser and every operating system, but it looks like crap.

This is the point where most programmers start to get anxious, start thinking “I’m not a designer”, try a few things, they all suck even more and give up, or cut/paste CSS from some other web site they find attractive until it look is bearable. I know this because I was one of those guys.

My problem was that I didn’t know where to start and I didn’t know what to look at, what to look for and what to care for, what to prioritize. I had no workflow, no entry point, no map and only a very rough idea in my head on where to go. This felt like a recipe for disaster or at least the entry point to bad results and a lot of wasted time.

I knew immediately to recognize a good design from a bad one when I saw them, but I had no idea how to get from where I was (my crappy, flat and boring HTML page) to where I hoped to get (something unique, good looking, pleasant to the eye and ultimately, something that you would not feel embarrassed about).

Moreover, I was scared by one of the biggest myths regarding HTML design: the general notion that if don’t have at least half a dozen of obnoxiously cut-to-size images to use as backgrounds in various <div>s around your page, it will continue to look dull and boring no matter what you do with the rest of your stylesheet.

This is simply not true: there is a lot you can do with CSS alone and no additional (or very few and easily reusable from somebody else’s web site) background images.

Start by tuning your base font

We need to start with something that will reward you and will give you the feeling that, in fact, you can make a difference on your own. For me, this something is tuning your base font. There are three things I suggest you to experiment with:

  1. font-family – this selects which font you want to use
  2. font-size – this is obviously the size of the font
  3. letter-spacing – this lesser known but incredibly useful CSS feature (supported by all modern browsers) allows you to specify how “densely packed” the font characters are horizontally. Note that you can have both positive and negative values of this property and you can use fractions as well.
  4. line-height - this allows you to specify how densely packed the font characters are vertically.

While every programmer knows about font-family and font-size, very few know about letter-spacing and line-height, even fewer know that they are generally well supported in the existing browsers.

Also, a great tool to test different font and font families is the web typesetter.

Choosing font family

The first thing you have to choose is weather you want to use a serif or a sans-serif font. If you are like I was, you probably have no idea how or why you should choose between the two.

There is no rule, but there are some general principles: serif fonts are believed to be easier to read for blocks of text because they give more information to your brain to analyze (that’s because the characters look more different form one another) and this guides your eye. Serif fonts also tend to look more classic and old-school (go and open up a random fiction book in your bookshelf and you’ll find a serif font).

Sans-serif fonts, on the other hand, while they are not as readable, they are normally used for titles and headlines (as they appear bolder by virtue of their increased perceived thickness), they normally render better on screen than serifs (this is due to the screen having lower resolution which generates artifacts around the serifs that might distract during reading), and they also tend to feel more modern.

Even after a while, I still have trouble telling you exactly what font is being used on a page if you point me to it and ask me. I can certainly distinguish between serif and sans-serif and between, say, very different fonts like Courier, Comic or Times New Roman. But for similar fonts, I still have a hard time.

At the same time, I can tell you right away, if you show me the same page with Arial vs. Helvetica or with Georgia vs. Times New Roman, which one I like best. This means that even if fonts looks extremely alike in your font picker or in a table of fonts, once presented in a page full of text, the result is very different and much more distinguishable, even if it’s very hard for people without extensive typographical knowledge to verbalize why.

But I encourage you to open your font picker (FontBook on MacOSX or any font picking software on Windows, including just the file explorer) but try to use those in the browser (that’s why the typesetter is so useful). Keep in mind that every font that your operating system contains is usable by the browser on your local machine. So go explore with those.

Here is my list of favorite font-families so far (in alphabetical order):

  • Serif: Adobe Caslon Pro, Adobe Garamond Pro, Arno Pro, Baskerville, Big Caslon, Book Antiqua (also known as Palatino Linotype), Calisto MT, Century, Century Schoolbook, Chaparral Pro, Cochin, Constantia, Footlight MT Light, Garamond, Georgia, Goudy Old Style, Hoefler Text, Minion Pro, Palatino, Perpetua, Trajan Pro.
  • Sans-Serif: Calibri, Candara, Corbel, Geneva, Helvetica, Kozuka Gothic Pro, Lucida Grande, Myriad Pro, Optima, Tahoma, Trebuchet MS, Verdana

Unfortunately, only a handful of fonts are ‘web friendly’, meaning that will be available on the greatest majority of desktop operating systems. Here you can see the list of how the web-friendly fonts look on various systems.

It is entirely possible to use font-family cascading to try to use fonts that are available on one operating system but not available on another (say, Myriad Pro which is a truly beautiful sans-serif font and that Apple uses for its own marketing text and for its web site, but it’s not available by default on windows), but there are some issues with that to take into consideration.

Gotchas with Font Family Cascading

CSS has the ability to ‘fall back’ to another font family in case the one you want is not available in your system. This can be used to look for the same font that has different name on different systems (say Book Antiqua and Palatino) but can also be used as a preferential list, starting with the one on the left.

It is not uncommon to see font-family definitions such as:

font-family: "Tahoma", "Verdana", "Helvetica", "Arial", sans-serif;

which is used to mean: I like Tahoma better, then Verdana, then Helvetica, then Arial, in this order… if you don’t have any of those, all I really need is any sanf-serif that you have.

Unfortunately, such cascading works with font-family, but doesn’t work with any of the other font settings. This wouldn’t be a big deal if all fonts behaved the same… but they don’t. Try changing from Tahoma to Verdana and keep everything else the same (same size, same letter spacing, etc.). You’ll see that while the individual characters look pretty much the same, the overall effect is radically different. One appears to be denser and bigger than the other. This is why changing font-family alone is not enough to achieve the settings you want (you have to act over the font density and the size as well) and why using cascading for font that behave very differently is a recipe for cross-OS disaster (although there are ways around this problem that we’ll see shortly).

Multiple Font Families

At this point, you might be inclined to choose different font families for different things in your page, especially headings and titles. While this is indeed very useful to obtain a more professional look in the page, I suggest that you move on to something else that gives you more instant gratification before attempting this.

Mostly because finding fonts that ‘go well together’ it’s a rather complicated and frustrating experience if you have rarely done it before, and might spoil your fun. So I suggest that you just pick one font-family for now and, especially, that you leave the headings (<h1>,<h2> etc) alone.

As for things like letter-spacing and line-height, try to experiment with them for your main text stuff but don’t be afraid of leaving them set to default values for now, we’ll go back to those later once we start tweaking things more deeply.

Give your page some air

Probably the most important thing about pleasant page design is ease of readability.

Readability is a property of the content itself, of course, but also of how the page is presented. Mostly, and counterintuitively, once a nice and well designed font has been selected and appropriate letter and line spacing is present, it has to do with the space around the text rather than within the text itself. It’s like pauses in music: silence is as important as sound when they go together harmoniously.

There was a time in the past where people thought that web pages that scrolled were a problem because people didn’t tend to scroll (for various reasons). It might have been the case 10 years ago, but right now pretty much every web user knows how to scroll, so the idea of packing things tight and removing space around things as to avoid users from having to scroll is just a bad idea, so you should forget it and give your text enough air to breath.

The main properties that deal with space around text and change the CSS box model are mainly three : margin, padding and border; in order of importance. Margin indicates the amount of space outside the box of text, padding the amount of space between the text and the box itself and border the style of the box border.

For now, try to leave borders alone and just focus on margins and paddings, in this order.

The main difference between margins and paddings is that margins are transparent while paddings have the background color of the box and that margins can collapse, while paddings do not.

The fact that CSS collapses margins by default is not very widely known: basically, if you have two consecutive <p> each with margin 10px, the space between them will be 10px, not 20px. This is because the bottom margin of the first <p> was collapsed with the top margin of the second <p> (in practice, it’s the maximum between the two margins). This does not happen for paddings, which is why margins are more useful than paddings as a way to create vertical space between boxes, as the collapsing does a great job in avoiding too much space to be created (or force you to come up with clever CSS selectors to compensate the problems this generates). For a more detailed example of this, the CSS2 spec has a nice section about this.

Horizontal Placing

I can’t really tell you if this is a problem of the CSS specs themselves or the way they are implemented in browsers today, but using CSS for laying things out vertically is simple, pleasant and straightforward, but dealing with anything that has to do with horizontal placement is an absolute nightmare.

Things as simple as “center this paragraph” that used to be very simple in HTML in the preCSS era, are a constant source of pain. This is because centering the box and centering the text inside the box are considered two different things.

Centering the text inside the box is easy, just use “text-align: center”, but centering the box while leaving the text alignment unchanged is a lot harder as there is no way to say “box-align: center” in CSS (because, if you really think about it, it doesn’t make much sense). The trick is basically to set the box width to the size we want and then ask for “automatic” left and right margins, like this:

blockquote {
   width: 50%;
   margin: 1em auto;

which means “make the <blockquote> half the width size of the box it is contained in and center it horizontally, while leaving 1 line of space at the top and at the bottom.

One thing that CSS introduced that HTML alone did not support is the ability to ‘float’ a box and have the text surround it. This is very useful for notes and callouts (see a bunch of examples here). Unfortunately, since floats are one of the few ways one can layout thing horizontally with CSS (without using tables), floats have been used to that effect. The problem is that every browser treats them slightly differently. My suggestion for you is to use floats for what they were intended to be and use tables for horizontal placing even if this pollutes your HTML a little; it might be less purist but it sure is easier to write, maintain and make it look the same across browsers and OSes.

Dealing with the Fear of Colors

If you think you suck at CSS design, you probably think you suck at color picking as well. The good news is that you probably don’t, you just don’t know how to do it.

First, I suggest you to read my previous post about why programmers suck at picking colors, but if you don’t really care and want some suggestions to move on the simplest one I can give you is: complete your design in black/white first.

This forces you to think in terms of contrast and therefore forces you to make decisions on a single dimension, other than multiple ones.

Dealing with contrast is also easy because you can make your own colors by simply typing them without the need to pick from a palette or a color picker. One nice thing that all browsers support is the ability to specify a gray-scale color using just three hex digits (instead of six):

p {
   color: #333;
   border: 1px solid #ccc;

The above indicates that <p> paragraphs should have text color that is not all the way black but it’s 3 shades lighter and use a border that is not white but has 2 shades darker (out of 16 major hex shades). I personally use #ccc for borders a lot and #333 or #222 for text. I try to avoid #000 (full black) for text because it feels too dark, the contrast too sharp and the visual artifacts around the characters too distracting.

Sometimes, especially with background colors, the difference between #eee and #fff is still too much. At that point, you’re forced to use 6 digits hex colors, such as #f0f0f0 or even #f8f8f8 which are whiter shades of gray (and I tend to use for background colors in blockquotes or callouts).

Any hex color that has three repetition of the same number is on the grayscale. This allows you to stop worrying about colors being three-dimensional and just focus on one.

This is important also because visibility and text importance is given with size, space/density and last with brightness. Hue (the tint of color) and saturation (how deep the color is) play a very marginal role in readability (their role is mostly in originality and differentiation between designs), so we can ignore that until the very end.

As a general rule, avoid too much contrast and try to look for subtle yet meaningful changes: you have a hard time distinguishing shades of color for things that should have different importance, you’re being too subtle, if you have a hard time reading something even if it has a minor role in the page, you’ve gone too far. Don’t be afraid of small differences; don’t try something big first and then make it minor but do the opposite: try something subtle and increase it until you can easily distinguish but not more than that.

As we’ve seen with fonts, even if it’s hard for people to identify what is different, they can tell you that there is a difference and that is all you need.

Taming Headings

For me, headings (such as <h1><h2><h3> etc.) are the hardest part of the page design. This is why I kept them at the end.

The problem with headings is that they are some of the most visible part of the page, and most of the time too much so. Another issue is that they tend to come with horrible defaults, but we already took care of resetting those at the beginning.

The biggest problem with headings is that they have to be different enough between each other and give a sense of relative importance (the heading level), but without taking up too much space or look too obnoxious.

Most people use only font-size and font-weight (which makes the font look heavier/bolder) to differentiate between heading levels, I find that too limiting and, frankly, a little poor. An improvement is to differentiate using other properties as well. Let’s see what they are and that they can do for you:

  • font-family – Using different font families for text and for headings makes it for a very professional look, if the fonts go well together. Heading tend to look better in Sans-Serif anyway, no matter what your text base font is, so that simplifies your life a little. You might also decide to change the font between different heading levels. I like that especially when two headings might appear next to each other (say title and subtitle).
  • letter-spacing – I personally find letter-spacing to be a much more elegant differentiator than font-weight. Slightly negative letter spacing tend to feel like an increased font-weight, with only a slight reduction of readability but with a sort of modern twist to it (sometimes, closed characters end up looking like ligatures). Positive letter-spacing makes the font appear lighter but without reducing its size.
  • color – Obviously color is a great differentiator, even if only using grayscales. It’s a good idea to have alternating colors between heading levels because if they are ever found together they are easier to distinguish.
  • text-transform – This is a relatively unknown CSS property that allows you to transform your text using a stylesheet. There are three types of transformations you can apply: uppercase, lowercase and capitalize. I tend to use uppercase text-transforms with a few pixels of positive letter spacing and some lighter shade of color together, it works very well in practice.
  • font-variant – This property is even more rare than text-transform and the only useful value is “small caps”. Small Caps achieve as similar effect than text-transform: uppercase, but use an entirely different font, instead of using the caps of the current font. Some fonts have very beautiful small caps variants while some others do not, so be careful when using this, but it’s good to know it’s there.

By using the above properties first, instead of starting with size and weight, you’ll find that choosing the size and the weight becomes a lot less problematic, mostly because they are already so differentiated that you don’t have to resort to huge headings. Not only you save space, but you increase readability because nothing in the page screams at you.

Dealing with adjacent headings

Another one of the big issues with headings is how they tend to look really ugly when they appear together. It took me forever to figure out a simple and elegant way to solve this issue, but I recently found it: it’s a combination of the “+” CSS selection operator and negative margins.

Headings, almost by definition, have bigger space around them than paragraphs. Unfortunately, they all do, so when you place them one after another (say <h1></h1><h2></h2>), even if you correctly used margins instead of paddings and the two margins collapse, you might still have too much space between the two. A solution is the following:

h1 + h2 {
   margin-top: -1em;

where “h1 + h2″ selects all h2 tags that come immediately after an h1 but at the same nesting level. Do not confuse this with “h1 > h2″ which selects h2 that are nested inside an h1. The negative margin allows the box to ‘recede’ backwards into the previous margin and therefore adjust it (of course the size depends on your own layout, I just used -1em as an example).

Note how you can use the same trick for things like <table> or <p class=”figure”> and its following caption.

More CSS tricks

Here I list some of the tricks that I use in my layouts. You might not find them useful to you but I use them to highlight some CSS features that you might not be aware of.

Curly Quotes

Any typographer would cringe at the use of ‘ and ” as quotes. Those symbols in fact do not represent quotes, at least not how real typographers would think of them (see this Wikipedia article for more info). My solution is to avoid using ” and use the existing HTML tag <q> for that and then use the following CSS tricks:

q {
   font-family: "Georgia", serif;
q:before {
   content: "\201C";
   padding-right: 0.1em;
q:after {
   content: "\201D";
   padding-left: 0.1em;

This trick uses two CSS features that are not widely known (or were not widely supported until very recently): the :before/:after pseudo element selectors and the ‘content’ property. :before matches a pseudo element that is right before the element we’re looking for (in this case <q>). This is called a pseudo element because it does not exist in the page, it’s created by the CSS renderer while rendering the page, but can be styled like any other element or box in the page. Unfortunately, this pseudo element is always empty, so we need to put some content in it. This is done using the “content” property. Here, we use the curly left quote (Unicode char 201C in hex) for the pseudo element before the quote and the right curly quote (Unicode char 201D) for the one after. Also I use Georgia as the font-family (no matter what font-family I use in the text) because it has the most classic glyphs for those characters of any of the web-friendly fonts. But because of the different fonts, we sometimes need to adjust the paddings around such pseudo elements, so that they properly kern with the quotes they surround.


Breadcrumbs are the list of pages that helps you navigate and have a sense of the location of the existing page in the page collection hierarchy. They are a list of pages, but they are normally presented horizontally. One would want to use <ul> and <li> to represent the list items of such breadcrumbs, but lists are normally rendered vertically, not horizontally. But there is a simple way to achieve that.

ul.path > li {
  display: inline;
  list-style-type: none;

here we’re saying that any <li> inside a special list that with class “path” will be considered an ‘inline’ element (like <b> or <i> or <span>, for example) and not a block element (like <p> or <div>). This will force the rendered to attach them horizontally instead of vertically.

We can also use the same trick as the curly quotes to add fancy char separators between the breadcrumbs:

ul.path > li:after {
   content: "\00BB";
   font-family: "Times New Roman", serif;
   font-size: 14px;
   padding-left: 6px;

this uses the right angle quotes glyph (Unicode char 00BB) from Times New Roman to separate the parts of the breadcrumbs.


An initial, in typography, is the first letter of the first paragraph of an important part of the text (a Chapter in a book, or a page in hypertext). It’s a very classy way to start a page and declares pretty evidently that some considerable effort went into making the page look nice and adhere to typographic principles.

CSS has another pseudo element selector that is useful for us in this case “:first-letter”. Here is how I used it:

p.first:first-letter {
    font-family: "Imprint MT Shadow", "Times", "Times New Roman", serif;
    font-size: 3.6em;
    color: #222;

where I used “Imprint MT Shadow” as the preferential font family (which is available only on MacOSX by default) and a pretty big size and a darker shade of text color to make it stand out even more (I normally use #333 for text color against a #FFF background). Note how it is also possible to use “float: left” to do initials that drop down into the text, but one of the problems with that is that every letter will require different margins to have its top properly aligned with the first line of the paragraph and that might not always look correctly.

Finally Colors

Now that your layout is complete but it’s black & white, it might feel too much sterile and flat, so you might want to spice it up with some colors.

When programmers think of colors, they think of RGB, because that’s how they were introduced to color. Unfortunately, RGB was not designed with color picking in mind and turns out to be by far the most difficult way to pick colors. So, rule #1: forget RGB.

A better idea is to use HSL (hue, saturation and lightness): hue changes the color (red vs. yellow), saturation the intensity of the color (vivid red vs. gray-ish red) and lightness the brightness of the color (dark red vs. bright red). Using HSL instead of RGB makes it a lot easier to change one color to fit better into one’s page layout…. but unfortunately it doesn’t help to pick pairs or pallete of colors that go well together.

I use three things to help with palette choice (from more manual to more automated):

  1. the NASA color picker (that uses a perceptual contrast-based color space instead of the usual HSL)
  2. palette listing sites (such as Colour Lovers or Adobe Kuler)
  3. palette generators from pictures (such as this one or this one)

One thing that it’s easy for me to start with is to pick an image that feels like it contains an appropriate color scheme in it but it’s hard for me to find it by simply pickign at individual pixel colors. The palette generator is your friend there and gives you a wonderful way to start with something that will go well together if only because those colors in the picture gave you pleasent feelings.

I find myself using the palette generators to give me suggestions on colors that I might want to use together and then either look for palettes that contain those colors in the listing sites or play with them directly in the NASA color picker or using the HSL color scheme directly in CSS (which is a lot easier to tweak with a text editor than RBG).

Unfortunately, not many browsers support HSL directly, but if you’re developing with Firefox 3 (which supports it), you can safely use HSL instead of RGB to experiment with your colors without having to go back and forth on a color picker until you’re satisfied with them and only at the very end transform the colors into RGB for compatibility reasons.

Compatibility Issues

Another one of the reasons why programmers get easily discouraged when writing CSS stylesheets is the fact that they think that dealing with cross browser and cross-OS compatibility issues is a pain and generally not something they look forward in doing. Also it doesn’t feel like an effort that one can reuse later.

I admit to have suffered this a lot myself, so much that my earlier designs didn’t even work on IE5 because I refused to test them against it.

We are in much better shape now, with IE7 phasing out IE6 and with IE8 getting very close to Firefox, Safari and Opera in CSS2/3 support. Unfortunately, slight compatibility issues remain, mostly with IE6 which has a pretty suboptimal CSS implementation (compared to the other browsers). What to do?

Enter IE7 (the library, not the browser)

Luckily, just like there are javascript libraries like jquery or prototype abstract away all these subtle differences for you, there is a similar thing for CSS support. It’s called IE7 and it’s a javascript library that ‘patches’ IE6 and IE7 CSS implementation from javascript right before your page loads and removes a lot of the headaches.

To use it, simply add these two lines in your <head> section:

<!--[if lt IE 7]><script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE7.js" type="text/javascript"></script><![endif]-->
<!--[if lt IE 8]><script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script><![endif]-->

these two lines will look like comments to all browsers but IE, but IE will be recognize them as conditionals and react to them based on the version of the browser. If the browser is less than IE7, it will load the IE7 library. If it’s less than IE8, the IE8 library. The result is that all IE browsers will behave for your page just like IE8 would!

Fine tuning your page portability

This last step is for those who really want to make sure that their pages look the same across all browsers and, most importantly, operating systems.

It is a fact that the same exact page will look differently (pixel-wise) even if rendered by the same browser on two different operating systems. Especially if we are being very picky with fonts. The font renderer in windows is much poorer than the font renderer on macosx (so much that Safari on Windows ships with the macosx font renderer and avoids using windows’).

It is not uncommon that even when you target the latest and greatest breed of browsers, with the most up-to-date support for all the CSS stuff, you need to tweak sizes, or paddings, or margins or other things, due to bugs, or simply differences in rendering.

The use of conditional comments works for IE, but doesn’t work for any other browser, and certainly doesn’t work for changes across OS due to font rendering or the fact that the font we planned to use it’s not available there.

Again, javascript comes to the rescue: this very tiny javascript library called “css browser selector” will add special classes to your <body> element depending on which browser version, what HTML rendering engine and what OS is currently interpreting your page.

This has a very elegant side effect: now you can use portability specific CSS selectors at the end of your stylesheet that are ignored in all the platforms but the one they are supposed to run on to correct things. So for example, after you downloaded the css_browser_selector.js script (I couldn’t find a deep link for this library) add this to your <head> section:

<script src="scripts/css_browser_selector.js" type="text/javascript"></script>

and then you can do stuff like this in your stylesheet

.win body {
    font-size: 1.3em;
    line-height: 1.7em;

that fixes the fact that on windows we know we’ll default to another font-family and we need a different size. Or

.ie ul.path > li:after {
    padding-left: 0.3em;
    padding-right: 0.2em;

which fixes a problem with the IE renderer and the inline <li> that requires us to change the paddings. Or this

.mac.safari pre {
    font-size: 1.2em;

which uses a very unknown feature of class selectors that allows you to select an element only if both classes are present in it (for example, <p class=”mac safari”>). In this case, it changes the font size in <pre> only for Safari on the mac.

Final Words

You can find the result of the journey that inspired this blog post here (a layout that I called “Earth”) and its relative stylesheet (and you can see this tutorial styled with that stylesheet here). This will be put to use soon in a new web site we’re about to launch, but I hope that the lessons I’ve learned over time can be useful to others as well, not only if they decide to cut/paste from it, but especially if you decide to be braver and make their own.

Update (a few things worth pointing out)

I had hoped this post would be useful to others (or I wouldn’t have written it), but honestly did not expect it to become so popular (and attract so much criticism). I did expect some confrontation on some of the tricks used and that is why I wrote that I did not expect my suggestions to be universally applicable, but only act as a way to empower people and show a possible way to achieve some of their goals in CSS design space. Still, there are interesting points in such criticism that I feel the need to address (I’ll just smile at the ones that don’t really deserve attention):

  • Deep linking can be dangerous – Yes, this is true. In this tutorial, I used deep links for both <script> and <style>. While deep linking can be initially useful, it surrenders your control. I didn’t bother to tell you because I thought it was self-evident and since it’s dead easy to just copy those libraries/stylesheets and serve it off your own domain to regain control, I didn’t think to make a point out of it. This post does not advocate the use of deep linking vs. self hosting. It’s up to you to decide which one fits your needs best.
  • html { font-size: 62.5%; } – Several people don’t seem to like this one. I’ll admit it felt pretty hacky to me too when I first came across it, but after a while I can tell you that it does make your life easier. Those who suggest to use font-size: 10px instead don’t really get the point: percentages and em are relative dimensions, meaning that you never mess with the browser defaults, whichever they happen to be on that platform, you just keep on working off of them with multiplication factors. It’s a subtle difference but makes sizes much more uniform across operating systems (if you don’t believe me, try it yourself!)
  • [insert library here] is lame – Sometimes, when you point people at the stars, they look at the finger.
  • Using Javascript is lame – A few people suggested that I should learn to work around browser bugs instead of using Javascript libraries to avoid doing that and that using Javascript for that is lame. Again, up to you: if you don’t like javascript and wish to learn all sort of ways to make your CSS more pure, go right ahead; since I don’t enjoy that exercise, I’ll stick to my javascript helpers. I’m sure I won’t be the only one among the practical ones.
  • Sensational titles may be catchy but pollute the message – This tutorial is first and foremost self-criticism: I’m a web programmer and I know I suck at CSS design (at least compared to most, if not all, CSS designers that I’ve met in my career). I don’t pretend to know what every other programmer thinks or knows, and I’m clearly not a CSS guru and never thought of myself as one: I just wished to share my experience hoping to be useful for others. If that’s not the case, I’m sorry I wasted your time.
  • Funny how you talk about CSS design and your blog design sucks – guilty as charged: this blog design is 5 years old and I haven’t had the time to bring it up to speed to the latest and greatest tricks that I’m outlining here. If this bothers you, you can read the nicer styled version with the stylesheet that I wrote recently and that inspired this blog post.
  • Can’t give feedback directly (commens or email) – This is a feature, not a bug. If you really want to communicate something to me, I’m sure you’ll find a way (as you can see, I consistently track who says what about this blog on the web). I think of it as a lazyness driven signal/noise amplifier and has the advantage of keeping the potential toxicity away from here.