Pulling the Comp into Markup:
I like to begin my code with envisioning the content and the structure of the page. This helps really nail down the organization of the page before you get too deep in how to make it look the way it's supposed to. The skeleton of my page looks like this:
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Sample Design</title>
<style type="text/css" media="screen">
</style>
</head>
<body id="home">
<div id="branding">
<h1>Cassie's Place</h1>
<ul>
<li>Navigation</li>
</ul>
</div>
<div id="content">
<div id="main">
Main Content
</div>
<div id="side">
Side Content
</div>
<div id="footer">
Footer
</div>
</div>
</body>
</html>
You'll notice there are a few wrapper divs--one being "branding" and the other being "content." You really should strive to minimize these in your designs, but they serve a few important purposes in this layout: 1.) They limit the width of the content to 960px and center everything horizontally with automatic margins 2.) the content div can be "faux-columned" to make sure I get a consistent look. They also do provide a semantic grouping of like divisions, which from an organizational stance isn't such a bad thing.
This next process is really kind of a puzzle. You have a Photoshop comp that looks the way you want it, but you have to get the CSS to kind of "speak your language" in terms of repeating and placed backgrounds as well as borders and positioning. You will definitely improve with experience, but hopefully by me outlining my thought process you can gain some insight into the workflow.
I start with the header, which fortunately for me I designed with a consistent color pattern left-to-right. This should tell you that you could recreate the background with a repeated image, which is what I've done below:
You might notice that the filename of that image is "bg_header.png" which is a naming convention I like to follow. By using type_name I can visually group similar types of files together without needing to create a directory structure. Little things like this can really save time when you have to hunt down images in a site that has several hundred. Also you'll notice that I chose PNG as the format of choice, and that is simply because you can depend on color precision with pngs and as long as the color palette isn't too high or the image too large they come out with nice small filesizes.
I could place this header inside of #branding, but since I want it to stay at 960px wide and I want the header to span the entire width of the page I'll instead place it inside of the body tag:
Code:
#header {
color: #666;
background: #d4d495 url(img/bg_header.png) left top repeat-x;
}
It's worth noting that I could have easily recreated that 1px bottom contrast line in CSS, but that would require an addition div so I was content simply including that in the repeated bg tile.
My next step is extracting out my logo image, which I've decided to make with the full background in-tact:
I could have just as easily extracted the logo layer out as a transparent PNG, but because I don't want to bother with PNG hacks this is an easy way to make the logo look good cross-browser. Another option would be to make a transparent gif with parts of the gradient background outlining the logo to ensure the it blends properly into the background, but because that pixel-perfect alignment to fit into the gradient I'll stick with the composite png.
For the markup I use a header tag. It is common to mark the site title up with a h1 tag, which is what I've chosen to do. You'll notice I use image text exclusively in the logo, but that doesn't mean I can't provide the same text inside of the h1 and hide it. This lets people with CSS disabled view a proper site header while letting everyone else see the pretty version:
Code:
#branding h1 {
position: absolute;
width: 381px;
height: 199px;
left: 0;
top: 0;
background: url(img/img_logo.png) left top no-repeat;
text-indent: -9999px;
}
So why use absolute positioning if i'm just going to stick it top-left? (which is where it would default to in normal flow) Well, flexibility. It makes the placement independent of my logo, and if I ever decide I want to move it around or change its grid it's just a few tweaks to the CSS. If I had instead done this with floats I'd have to consider width, margins, and how it interacts with my navigation. I just find it's a good practice to put these hooks in early so that when I need to make changes down the road they're simple. Also take note of the "text-indent: -9999px" This is a common method of hiding text without hiding the element itself which is important to users with screen readers.
Next up I need to tackle the navigation, which is usually quite the beast for most people new to CSS. The trend is to use unordered lists for navigation markup, and I'm a fan of that as well. Not only does it give your navigation semantic structure (and plenty of nested tags to style), but for users who have CSS disabled it presents the navigation in a logical format. For beginners I think you should learn to jump in there and make your own CSS navigation. One of the worst things beginners do is simply copy CSS code, which means if you want to make any additions or manipulations you're completely in the dark. CSS navigation isn't as hard as it looks, so here is the step by step process on how to achieve the navigation I made in the comp:
First off there's the issue of the the tabs themselves. Typically if you want image navigation people place tabs or buttons as background images, but these don't handle text resizing well. Douglas Bowman pioneered a technique called "Sliding Doors" which allow tabs to grow horizontally and vertically with the text using only a few images. If you are using text for the labels of your navigation I would highly suggest looking into this method, which is well-outlined here:
http://www.alistapart.com/articles/slidingdoors2/
Like I mentioned above we decided to go with image-only text to reinforce the branding, so because I chose a larger font size to enhance accessibility I don't have to worry too much about resizing. I'll take advantage of this fact and create both the normal tabs and the hover tabs all in one image:
You'll notice that the tabs are 50px high, and that entire image is 100px high. This lets me do some clever things with the image tabs themselves without needing a bunch of separate files. To understand how this will work, think of an oldschool roll of film. The film itself consists of several frames, but only the one directly infront of the lens opening is displayed. What's displayed on the screen is a direct result of where the projector offsets the film. Think of the list items (LIs) of our navigation as the camera lens. It has a fixed height and width, and will only display the background that can fit in it. By using CSS background positioning, we can offset the background so that different parts of the background show through on different LIs. This lets us store our rollover states, our idle states, and all tabs in one file. The following figure illustrates how specific LIs can use offsetting to show different parts of the same image:
My first step is to absolutely position my navigation ul, which I place at the bottom right corner of my header (allowing 1px for the contrast line):
Code:
#branding ul {
position: absolute;
right: 0;
bottom: 1px;
width: 454px;
height: 50px;
}
Next I'm going to fully mark up my navigation, providing hooks for each list element (you'll see why in a minute):
Code:
<ul>
<li id="nav-home"><a href="home.html">Home</a></li>
<li id="nav-about"><a href="about.html">About</a></li>
<li id="nav-archives"><a href="arch.html">Archives</a></li>
<li id="nav-contact"><a href="contact.html">Contact</a></li>
</ul>
For a horizontal navigation, you need to get the LI elements to position themselves horizontally. The easiest way to achieve this is by floating the elements. We'll also take off the list-style, removing the bullets from the list:
Code:
#branding li {
list-style: none;
float: left;
margin-left: 2px;
}
You'll notice I put a margin of 2px there, and that's mainly to provide a small gutter between the li's that aren't clickable. This is a subtle visual cue that makes the tabs feel like separate entitites, and not just an image bar. Also notice that because I gave the ul a specific height I do not need to float it. Normally if you float the list elements of an unordered list, the unordered list ceases to have any height unless you float it as well. Since I know the height of my navigation exactly I removed this behavior by simply giving it a height.
Now we want to mark up the anchors inside of the list items, which is where we will place our background images. Now, it would have been perfectly feasible to instead put the background elements on the li tag, but this raises a problem in IE6 which doesn't support :hover on all element types. We want the tabs to change when you hover over them with a mouse, and by placing the background on the anchor instead we can use a:hover to change the background image--which IE6 handles just fine.
Code:
#branding li a {
height: 50px;
display: block;
width: 111px;
text-indent: -9999px;
}
There's two things worth noting here. First is "display: block", which turns the anchor tag into a block-level element. This has to do with a design guideline called "Fitt's Law," which essentially states the amount of time it takes a user to select something is a function of both the size of the target area and the distance the user has to travel. By making the anchor tags block level you essentially make the entire tab area clickable, which is a win for ease-of-use. You can read more about how Fitt's Law can apply to the web at Dunstan Orchard's (sadly now defunct) blog:
http://1976design.com/blog/archive/2...ion-fitts-law/. The second thing of merit is the repetition of the text-indent from our site header, which will effectively hide the text of the unordered list while still allowing them to be clickable.
Note that there's a seemingly arbitrary width for the anchors, but if you do a little math (4 tabs @ 111px = 444px, 4 2px margins = 8, 444+8 = 452) you'll see that it all adds up to the width of our ul: 452px.
Something handy that I like to do at this point is to place the navigation image as a background of the ul, and give the li's a transparent background to make sure everything lines up.
I'll temporarily add the following code to the ul and li tags:
Code:
#branding ul {
position: absolute;
right: 0;
bottom: 0;
width: 452px;
height: 50px;
background: url(img/bg_nav.png) 2px top no-repeat;
}
#branding li {
list-style: none;
float: left;
margin-left: 2px;
background-color: #000;
opacity: 0.4;
}
This puts a transparent overlay in the li elements, which lets you quickly check to make sure everything is positioned correctly before you move on:
http://just-in.org/etc/tut/10-nav.jpg
As one last tweak I put the entire navigation image as background of the UL. This is to deal with flickering that IE6 is bad about during images changes. There's a slight pause for the server to redisplay an image, even if it's only been repositioned, so by putting the image on our UL it will still look loaded and we won't get any flickering.
Now I need to place the background images on my li anchors, which will let them display the tabs individually:
Code:
#branding li#nav-home a{ background: url(img/bg_nav.png) left top no-repeat; }
#branding li#nav-about a { background: url(img/bg_nav.png) -113px top no-repeat; }
#branding li#nav-archives a { background: url(img/bg_nav.png) -226px top no-repeat; }
#branding li#nav-contact a { background: url(img/bg_nav.png) -339px top no-repeat; }
With these selectors you see how we can use the same image for all of them, and simply change the negative offset to scoot the image backwards so that only the right tab shows through that li. You'll also notice that because all of these elements are aligned to "top" that we'll only see the inactive tabs. If you remember, the nav image we crated was 100px tall, and the bottom 50px are the rollover versions of the inactive tabs.
Now we add the tabs for the rollovers, along with a few extra selectors:
Code:
#branding li#nav-home a:hover,
#home #branding li#nav-home a { background: url(img/bg_nav.png) left bottom no-repeat; }
#branding li#nav-about a:hover,
#about #branding li#nav-about a { background: url(img/bg_nav.png) -113px bottom no-repeat; }
#branding li#nav-archives a:hover,
#archives #branding li#nav-archives a { background: url(img/bg_nav.png) -226px bottom no-repeat; }
#branding li#nav-contact a:hover,
#contact #branding li#nav-contact a { background: url(img/bg_nav.png) -339px bottom no-repeat; }
So what's up with the rules like "#home #branding li#nav-home a"? Well, this allows us to place a single id on the body tag, which will make one of these rules active. This allows you to make one of your tabs "active" without actually having to touch the navigation markup at all (conventionally people put a class on one of the elements called "active" or something similar). This is really handy when making use of PHP or other server-side languages where we can dynamically include the navigation on each page. It's also worth noting that I could have done this with simple background-position changes, but since I wanted the rule to apply to active tabs as well (not just hovers) I can't depend on the right image being loaded so I just do an image swap.
So since we're mocking up the home page we'll add a id="home" to the body tag making that tab active, and we now have a completed header with a functional navigation!
http://just-in.org/etc/tut/11-header.jpg
With that out of the way, I'm going to add one little bit of visual sugar to the design. If you remember, our layout had a drop shadow below the header itself. Drop shadows can be tricky to make when they fall on top of several different colored elements, because IE6 and below does not support alpha PNGs. To combat this many people put the the dropshadows into the tops and sides of the layout backgrounds, and try to line them up to give the illusion of a continuous shadow. We could do this, but it'd involve several more tags and let's face it the shadow isn't _that_ necessary to the design.
So my choice here is to actually use a repeated PNG to give a nice drop-shadow effect to those who can handle it, and I'm absolutely placing it in the window so that it doesn't interfere with any existing markup:
I place <div id="shadow"><!-- --></div> right before I close out the body tag (since there is no parent container with position: relative, I can absolutely position the shadow div with relation to the window which is what I want). This will look bad in IE6 though, so in my CSS I will add a rule to hide it from IE6:
Code:
#shadow {
position: absolute;
top: 200px;
left: 0;
width: 100%;
height: 9px;
background: url(img/bg_shadow.png) left top repeat-x !important;
background: none;
}
Notice that there are two background declarations. The first one is appended with an "!important" declaration, which tells most modern browsers that this background property is more important than the other so it'll use the important one. Because IE6 doesn't acknowledge !important, we can follow that rule up with a rule that tells IE6 to display nothing at all.
This is one of those simple things where instead of trying to over-engineer the design just so it will look the same on a legacy browser, you decide that you can do without some of the eye-candy so long as the content is accessible and thoughtful. I think that's something we all should come to grips with, instead of always springing straight to complicated hacks and the like to make things look the same cross-browser.