Design and Code a Slick Website From Scratch: Part 2
With the Internet becoming more and more popular every minute, a great-looking website is somewhat of a must-have. You could obviously pay a web designer to design one for you, but wouldn’t it be really cool to design and code it yourself? “Difficult”, you may say; but it’s actually not too hard once you’ve learned how to do it!
In this second part of the tutorial, we will code our design into a standards-compliant, cross-browser xHTML, CSS, and JavaScript/jQuery layout. Fire up Coda, or your editor of choice... it’s coding time!
Step One – What We Will Be Making
You might think that we'll simply use our previously designed layout as some kind of base and then code a much less complex design in order to make things simpler for us, but that is not the case! At the end of this tutorial, this is what your layout will look like in a browser:



Note that this is not a Photoshop version but the actual result in Firefox. It was taken using the Screengrab! Plugin, so this is exactly what you will see once finished.
Some considerations about the design:
- The slideshow fully works with smooth transitions
- The heading are not images
- The CSS is valid with both the 2.1 and 3.0 specifications
- The xHTML validates with a strict 1.0 Doctype
Step Two – Requirements
Even though I’ll try to be as clear and concise as possible throughout this tutorial, saying that a complete beginner could follow and understand these would be wishful thinking. Sure, copy & pasting is possible, but to understand all the explanations, you’ll need to have some knowledge of web techniques:
- A solid knowledge of both HTML and CSS is strongly recommended, but you’ll probably manage to follow knowing just the basics as well
- An idea of how JavaScript, and more precisely jQuery, works is important
If you don’t know anything about those things you can always go ahead and learn them. Here are some useful links to do so:
- 30 HTML Best Practices for Beginners by Jeffrey Way
- HTML & CSS – The VERY basics by Chris Coyier
- How jQuery Works by John Resig
Step Three – Setting Up Our Developer Environment
In this part of the tutorial, I’ll just try to explain my way of doing things when I’m coding a web site. The first and probably most important thing is about your tools. What apps are you going to use to code, to debug, to test?
In my case, Dreamweaver is the choice for code. “Oh gosh, just another WYSIWYG web developer", you might think, but the answer is no, I don’t use the WYSIWYG mode. I use Dreamweaver because I simply love its auto-completion features and its syntax highlighting. If you don’t feel like paying 799$ for an application however, there are a number of great code editors out there for free or for a whole lot less. I’m thinking about Coda, Text Mate, Espresso or CSS Edit for Mac OS X, and Aptana Studio, Notepad++ or E Text Editor for Windows. You could obviously just use Notepad or Text Edit, but why do so when so many great tools are available free?
The next thing we need to choose is a development browser. We need a browser with great debugging tools. Even though I’m a hard-core Opera user in everyday life, I use Firefox during my development cycles because of its outstanding tool: Firebug. Sure, Opera has Dragonfly, and Safari 4 is shipped with some great tools as well, but Firebug is still one step ahead, and this makes me choose Firefox as my development browser. You should be sure to use a standard-compliant browser in any case. In other words, do not use Internet Explorer as your main testing environment. Even though my choice is Firefox for testing during the development cycle, I have all the recent browsers installed on my computer to check that everything works just fine on all of them. My designs are therefore tested in Firefox 3+, Opera 9.5+, Safari 3+, Chrome 1+, and Internet Explorer 7+. This way, they should be correctly displayed for about 95% of the internet users. * Editor's note: this figure will vary considerably depending on the target audience of the site.
Okay, now that we’ve got the tools to work with, we also need a directory structure. In order to keep things clear, I’ve decided to create a new “site" on my local server just by creating a new folder in the www/ folder. I’m using WAMP as my localhost. Within this site, we will need to create three folders, js/, css/, and img/. I guess the names are pretty self-explanatory.



Now that we have our environment set up, we can start coding!
Step 4 – The xHTML
I’ve already mentioned it, but in this tutorial, we will be sure to build valid xHTML. What does that mean?
Most pages on the World Wide Web are written in computer languages (such as HTML) that allow Web authors to structure text, add multimedia content, and specify what appearance, or style, the result should have.
As for every language, these have their own grammar, vocabulary and syntax, and every document written with these computer languages are supposed to follow these rules. [...]
However, Just as texts in a natural language can include spelling or grammar errors, documents using Markup languages may (for various reasons) not be following these rules. [...]
With these concepts in mind, we can define "markup validation" as the process of checking a Web document against the grammar (generally a DTD) it claims to be using.
W3C Validation Service
But why even bother validating a page? Well, there are a few advantages, the first one being SEO. Google’s crawler gives better ranking to valid pages. The second one is accessibility. People who are using screen readers may not be able to see your site correctly if your markup is invalid. Last, but not least, the ability to produce valid code is something showing that you’re not a simple Sunday-coder.
What we must do now is think a bit of how we are going to structure our design, which tags we are going to use, the IDs we are going to give them, etc. Here’s what I’ve come up with:



Now that we know what we are going to produce, let’s start by defining the basics of our document!
The Basics
I’ve already told you that we are going to use xHTML Strict. This means we have to keep our structure logic separated from our layout logic. In order to tell the browser what “grammar" we are using, we need to define a so-called DTD or Document Type Definition. The xHTML 1.0 Strict Doctype looks like this:
1 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
This code should be put first in all your HTML files. The lack of such a definition will result in a failed validation.
Next, we just need to define the basics of our page: the head and the body. You’ll want a title tag in your head section in order to display a correct name in the browser’s title bar instead of something like “Untitled 1". I decided to put some meta-tags as well for SEO, even though we all know they are not so useful today.
1 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
2 |
html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" > |
3 |
<head>
|
4 |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
5 |
<meta name="keywords" content="Roadside, Studio, Design, Web, Icons, Logos" /> |
6 |
<meta name="description" content="Roadside Studio is a web design agency that makes beautiful websites!" /> |
7 |
<meta name="author" content="Felix Boyeaux" /> |
8 |
<meta name="robots" content="all" /> |
9 |
|
10 |
<title>Roadside Studio</title> |
11 |
</head>
|
12 |
<body>
|
13 |
<!-- The content will go here -->
|
14 |
</body>
|
15 |
</html>
|
Once this is done, we can start coding the actual content.
The Status Bar
Remember how I made you create a whole bunch of layer groups and rename them to something that reflected their function? Well you’ll now understand why. Take a look at this layer palette:



Can you see what I mean now? Indeed, this gives us the structure of our HTML: we’ve got a wrapping folder called Status Bar, in which we have subfolders. Those folders represent the block elements of our page! However, this is not foolproof. Experience demonstrates that we need some more wrapping blocks in order to centre the content of the bar and still have the bar’s background take up 100% of the width. We also need a wrapper around the welcome message and the action bar in order to make the search field float on the right. This is what your code should look like:
1 |
<div id="status-bar"> |
2 |
<div id="status-bar-content"> |
3 |
<form action="#search" method="post" id="search-form"> |
4 |
<p>
|
5 |
<input type="text" name="query" value="Search" /> |
6 |
<input type="submit" name="submit" value="Search!" /> |
7 |
</p>
|
8 |
</form>
|
9 |
<div id="status-bar-commands"> |
10 |
<p id="welcome">Welcome, Guest</p> |
11 |
<p id="action-bar"> |
12 |
<a href="#login" title="Login">Login</a> |
13 |
<a href="#sitemap" title="Sitemap">Sitemap</a> |
14 |
<a href="#license" title="License">License</a> |
15 |
</p>
|
16 |
</div>
|
17 |
</div>
|
18 |
</div>
|
The Div tag with an ID of status-bar is our wrapping block, as you may have understood. The status-bar-content block is needed to centre the content of this bar. You should also notice the paragraph tags inside the form tags. This is needed for xHTML 1.0 Strict to validate. The last important thing to think of in this code snippet is the fact that we did not replace our paragraph tags with divs. This is what web designers call semantic coding. A paragraph should always be wrapped in
tags to emphasis the fact that it is readable text. This also makes things easier for screen readers to read.
Great! That was it for the status bar. Not so complicated, huh? The key is to proceed logically from the layer hierarchy in our PSD in order to build our markup the right way. Just keep in mind to keep your HTML semantic. Use paragraph tags for paragraphs, blockquotes for quotes obviously, and so on.
The Header
We will need to take a look at the layer palette to have an idea of how to build it. This is what we’ve got for the header:



Now let’s translate this structure into code. We’ll need a wrapper, a logo block, and two text blocks: one for the header, one for the subtitle. However, in this case we won’t use paragraph tags. Why not? Well simply because we can be even more semantic than that, using header tags. Since the header text is the first heading in our document, we’ll wrap it with an h1 tag. The subtitle is going to be an h2 tag considering it is the second heading in our document.
1 |
<div id="header"> |
2 |
<div id="logo"> |
3 |
<h1><a href="#home" title="Home Page">Roadside</a></h1> |
4 |
<h2>Studio</h2> |
5 |
</div>
|
6 |
</div>
|
One thing we did here was add a link to the home page on the logo. This is a convention that pretty much every web designer use. It is also well known from the users, so not offering such a link could cause some confusion with your readers. Other than that, there isn't more to say about this part of the design, so let’s just proceed to the content part.
The Tabs
Before starting with the actual tabs, we’ll need to add a wrapping div with an id of content to contain the tabs, the page wrapper, and both the twitter and the blog module. Once that is done, we’ll have to think a little bit about the menu and how it is going to be structured. The best way to code a menu is probably an unordered list, even though we want a horizontal menu. Why a list? Well list are good for displaying items with the same value, without emphasizing some and not others. This is exactly what we want. In each list item, we obviously add an anchor tag. This anchor link doesn’t link to anything real; the href attribute is just equal to #home for our tutorial.
1 |
<div id="content"> |
2 |
<ul id="tabs"> |
3 |
<li id="previous"> |
4 |
<a href="#previous" title="Previous"><</a> |
5 |
</li>
|
6 |
<li id="home" class="current"> |
7 |
<a href="#home" title="Home">Home</a> |
8 |
</li>
|
9 |
<li id="portfolio"> |
10 |
<a href="#portfolio" title="Portfolio">Portfolio</a> |
11 |
</li>
|
12 |
<li id="about"> |
13 |
<a href="#about" title="About">About</a> |
14 |
</li>
|
15 |
<li id="contact"> |
16 |
<a href="#contact" title="Contact">Contact</a> |
17 |
</li>
|
18 |
<li id="next"> |
19 |
<a href="#next" title="Next">></a> |
20 |
</li>
|
21 |
</ul>
|
22 |
</div>
|
You should notice that we didn’t wrap our tabs up in a div with an id of tabs, simply because the ul tag does this for us already. You should always try to remove as many unnecessary div blocks as possible in order to make the page faster and cleaner. You may also ask yourselves what < and > stands for. Well it stands for “lower than", and gt for “greater than" and those are simply the HTML values for < and >.
Don’t worry too much about the fact that our horizontal tab menu is a vertical list for the moment; we’ll make sure that it’ll look appropriate when we write our CSS.
The Wrapper
The “wrapper" is what I call the box with the slideshow and the welcome message. We’ll create a div with an ID of “page-wrapper" to be sure that the box will be correctly defined. This div is obviously nested in the content div too.
Now we need to code the slideshow part. We’ll create a container with an ID of “slideshow". Inside this, we create a div called “slides" which is going to contain all the images we want to cycle through. There’s also a link around them in order to redirect the reader to the portfolio section of the site. The div with an ID of “slideshow-commands" contains previous and next commands, and the title of the current slide.
1 |
<div id="page-wrapper"> |
2 |
<div id="slideshow"> |
3 |
<div id="slides"> |
4 |
<a href="#portfolio.work1" title="See details" class="thumb default-slide"> |
5 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/./img/slideshow/1.png" alt="Flex Engine Web Design" class="slideshow-image" /> |
6 |
</a>
|
7 |
<a href="#portfolio.work2" title="See details" class="thumb"> |
8 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/./img/slideshow/2.png" alt="Concept Labs Portfolio" class="slideshow-image" /> |
9 |
</a>
|
10 |
<a href="#portfolio.work3" title="See details" class="thumb"> |
11 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/./img/slideshow/3.png" alt="Everlast Studio" class="slideshow-image" /> |
12 |
</a>
|
13 |
</div>
|
14 |
<div id="slideshow-commands"> |
15 |
<a href="#previous" title="Previous" id="previous-slide"><</a> |
16 |
<a href="#next" title="Next" id="next-slide">></a> |
17 |
<h4>
|
18 |
<a href="#portfolio.work1" title="See details" id="slide-title"> |
19 |
Flex Engine Web Design |
20 |
</a>
|
21 |
</h4>
|
22 |
</div>
|
23 |
</div>
|
24 |
</div>
|
The important thing here is the way we added all our slide images in a container to make the sliding easier. However, we need to have a default slide. In this case, I’ve added a class “default-slide" to the anchor containing the default image. To make styling easier, just add a class “thumb" to those images as well. Multiple classes can be set to one element by separating them with spaces. The alt attribute on the images is mandatory for a valid code. It will also be important for our slideshow since this is where we’ll fetch the title of the slide.
The next step of this “page-wrapper" is the displayed message and the contact information. This one will be pretty easy. We need a heading, which is going to be an h3 because it’s our third heading on the page, a paragraph tag containing the message itself, and a paragraph tag containing the contact info.
1 |
<div id="message"> |
2 |
<h3>We build great websites!</h3> |
3 |
<p>
|
4 |
Curabitur nec sem in risus adipiscing feugiat. Etiam elementum malesuada purus. |
5 |
Quisque nec mi eu mauris ornare aliquam. Praesent adipiscing, |
6 |
metus sed luctus condimentum, quam turpis interdum tortor, |
7 |
in dignissim magna urna tempor odio. Integer porttitor. Nam dolor urna, |
8 |
ultricies vitae, porttitor ut, dignissim vitae, elit. |
9 |
</p>
|
10 |
<p id="contact-info"> |
11 |
<span id="phone">+33 1 23 45 67 89</span> |
12 |
<span id="address"> |
13 |
34, Avenue des Champs-<br /> |
14 |
Elysées, 75006, Paris,<br /> |
15 |
France |
16 |
</span>
|
17 |
</p>
|
18 |
</div>
|
Just notice how we put span tags around the phone number and the address to be able to style them separately. Don’t forget that new lines in your code have no influence whatsoever on the text that is printed on the screen. We can use this to make our code beautiful, and indent the paragraph correctly.
Once this is done, it’s time for a little break to look at what we’ve done. This is the entire code so far:
1 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
2 |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" > |
3 |
<head>
|
4 |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
5 |
<meta name="keywords" content="Roadside, Studio, Design, Web, Icons, Logos" /> |
6 |
<meta name="description" content="Roadside Studio is a web design agency that makes beautiful websites!" /> |
7 |
<meta name="author" content="Felix Boyeaux" /> |
8 |
<meta name="robots" content="all" /> |
9 |
|
10 |
<title>Roadside Studio</title> |
11 |
</head>
|
12 |
<body>
|
13 |
<!-- STATUS BAR -->
|
14 |
<div id="status-bar"> |
15 |
<div id="status-bar-content"> |
16 |
<form action="#search" method="post" id="search-form"> |
17 |
<p>
|
18 |
<input type="text" name="query" value="Search" /> |
19 |
<input type="submit" name="submit" value="Search!" /> |
20 |
</p>
|
21 |
</form>
|
22 |
<div id="status-bar-commands"> |
23 |
<p id="welcome">Welcome, Guest</p> |
24 |
<p id="action-bar"> |
25 |
<a href="#login" title="Login">Login</a> |
26 |
<a href="#sitemap" title="Sitemap">Sitemap</a> |
27 |
<a href="#license" title="License">License</a> |
28 |
</p>
|
29 |
</div>
|
30 |
</div>
|
31 |
</div>
|
32 |
<!-- HEADER -->
|
33 |
<div id="header"> |
34 |
<div id="logo"> |
35 |
<h1><a href="#home" title="Home Page">Roadside</a></h1> |
36 |
<h2>Studio</h2> |
37 |
</div>
|
38 |
</div>
|
39 |
<!-- CONTENT -->
|
40 |
<div id="content"> |
41 |
<!-- TABS -->
|
42 |
<ul id="tabs"> |
43 |
<li id="previous"> |
44 |
<a href="#previous" title="Previous"><</a> |
45 |
</li>
|
46 |
<li id="home" class="current"> |
47 |
<a href="#home" title="Home">Home</a> |
48 |
</li>
|
49 |
<li id="portfolio"> |
50 |
<a href="#portfolio" title="Portfolio">Portfolio</a> |
51 |
</li>
|
52 |
<li id="about"> |
53 |
<a href="#about" title="About">About</a> |
54 |
</li>
|
55 |
<li id="contact"> |
56 |
<a href="#contact" title="Contact">Contact</a> |
57 |
</li>
|
58 |
<li id="next"> |
59 |
<a href="#next" title="Next">></a> |
60 |
</li>
|
61 |
</ul>
|
62 |
<!-- PAGE WRAPPER -->
|
63 |
<div id="page-wrapper"> |
64 |
<!-- SLIDESHOW -->
|
65 |
<div id="slideshow"> |
66 |
<div id="slides"> |
67 |
<a href="#portfolio.work1" title="See details" class="thumb default-slide"> |
68 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/./img/slideshow/1.png" alt="Flex Engine Web Design" class="slideshow-image" /> |
69 |
</a>
|
70 |
<a href="#portfolio.work2" title="See details" class="thumb"> |
71 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/./img/slideshow/2.png" alt="Concept Labs Portfolio" class="slideshow-image" /> |
72 |
</a>
|
73 |
<a href="#portfolio.work3" title="See details" class="thumb"> |
74 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/./img/slideshow/3.png" alt="Everlast Studio" class="slideshow-image" /> |
75 |
</a>
|
76 |
</div>
|
77 |
<div id="slideshow-commands"> |
78 |
<a href="#previous" title="Previous" id="previous-slide"><</a> |
79 |
<a href="#next" title="Next" id="next-slide">></a> |
80 |
<h4>
|
81 |
<a href="#portfolio.work1" title="See details" id="slide-title"> |
82 |
Flex Engine Web Design |
83 |
</a>
|
84 |
</h4>
|
85 |
</div>
|
86 |
</div>
|
87 |
<!-- MESSAGE -->
|
88 |
<div id="message"> |
89 |
<h3>We build great websites!</h3> |
90 |
<p>
|
91 |
Curabitur nec sem in risus adipiscing feugiat. Etiam elementum malesuada purus. |
92 |
Quisque nec mi eu mauris ornare aliquam. Praesent adipiscing, |
93 |
metus sed luctus condimentum, quam turpis interdum tortor, |
94 |
in dignissim magna urna tempor odio. Integer porttitor. Nam dolor urna, |
95 |
ultricies vitae, porttitor ut, dignissim vitae, elit. |
96 |
</p>
|
97 |
<p id="contact-info"> |
98 |
<span id="phone">+33 1 23 45 67 89</span> |
99 |
<span id="address"> |
100 |
34, Avenue des Champs-<br /> |
101 |
Elysées, 75006, Paris,<br /> |
102 |
France |
103 |
</span>
|
104 |
</p>
|
105 |
</div>
|
106 |
</div>
|
107 |
</div>
|
108 |
</body>
|
109 |
</html>
|
You can check its validity now at http://validator.w3.org/ and see that it is valid. Good, we can now continue with the coding of the modules.
The Blog Module
The code is pretty straightforward here. We’ll need to add a containing div with an ID of “blog" and a class of “module" to be able to style the two modules together since they are pretty much the same. The heading will be an h4 whereas titles will be h5. This will make a clear outline with a solid hierarchy in our document. The last thing to consider here is the few lines of each entry. We will put it in blockquotes tags. Why? Well even though it isn’t a proper quote, it is still text taken from another part of the web site, so it is actually appropriate to use blockquotes here. We also just put a 'Read More' link wrapped in a paragraph tag to make things valid.
1 |
<div class="module" id="blog"> |
2 |
<h4 class="module-header-bar">Latest entries from the blog</h4> |
3 |
<div class="blog-entry"> |
4 |
<h5><a href="#blogentry1" title="Vivamus sed risus">Vivamus sed risus</a></h5> |
5 |
<p class="meta">By Jonathan Davidson - 05 / 08 / 09</p> |
6 |
<blockquote class="content"> |
7 |
<p>
|
8 |
Vivamus sed risus quis felis sagittis cursus. Duis blandit tristique turpis. Nulla feugiat vehicula metus. |
9 |
</p>
|
10 |
</blockquote>
|
11 |
</div>
|
12 |
<div class="blog-entry"> |
13 |
<h5><a href="#blogentry2" title="Pellentesque pulvinar">Pellentesque pulvinar</a> |
14 |
</h5>
|
15 |
<p class="meta">By The Team - 05 / 01 / 09</p> |
16 |
<blockquote class="content"> |
17 |
<p>
|
18 |
Pellentesque pulvinar dolor nec orci. Pellentesque scelerisque elit. |
19 |
</p>
|
20 |
</blockquote>
|
21 |
</div>
|
22 |
<div class="blog-entry"> |
23 |
<h5><a href="#blogentry3" title="Cras in nibh">Cras in nibh</a></h5> |
24 |
<p class="meta">By Nicholas Denman - 05 / 01 / 09</p> |
25 |
<blockquote class="content"> |
26 |
<p>
|
27 |
Quisque dapibus, justo a bibendum pellentesque, tellus felis cursus libero, posuere sodales diam ipsum in lorem. |
28 |
</p>
|
29 |
</blockquote>
|
30 |
</div>
|
31 |
<p id="read-more-wrapper"> |
32 |
<a href="#blog" title="Read More"> |
33 |
Read More |
34 |
</a>
|
35 |
</p>
|
36 |
</div>
|
You should see that we’ve added paragraph tags within the blockquotes. This is something obligatory to pass validation. Instead of adding Ids to all entry elements, we added classes, to be able to put them several times. You’ll therefore see a paragraph with an ID of “meta" or a blockquote with a class of “content" for instance. Each entry is wrapped in its own div as well just to make spacing easier.
The Twitter Module
The Twitter module will be similar to the blog module, so I’ll go over this more quickly. Just remember that the structure behind the HTML we’re coding is give by our layer palette. In this case, for example, this is what the Twitter Module layer group looks like:



We’ll therefore need a header bar wrapper, and containers for each tweet, but also a block containing the button. This is what the code would look like:
1 |
<div class="module" id="twitter"> |
2 |
<h4 class="module-header-bar">Follow the Roadside Team on Twitter</h4> |
3 |
<div class="tweet"> |
4 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/img/team/1.png" alt="Jonathan Davidson" /> |
5 |
<h5><a href="#@JonathanDavidson" title="Jonathan Davidson">Jonathan Davidson</a></h5> |
6 |
<blockquote>
|
7 |
<p>
|
8 |
Proin et libero. Curabitur molestie mauris eu massa. |
9 |
</p>
|
10 |
</blockquote>
|
11 |
</div>
|
12 |
<div class="tweet"> |
13 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/img/team/2.png" alt="Nicholas Denman" /> |
14 |
<h5><a href="#@NicholasDenman" title="Nicholas Denman">Nicholas Denman</a></h5> |
15 |
<blockquote>
|
16 |
<p>
|
17 |
Etiam felis ligula. |
18 |
</p>
|
19 |
</blockquote>
|
20 |
</div>
|
21 |
<div class="tweet"> |
22 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/img/team/3.png" alt="Jessica Marshall" /> |
23 |
<h5><a href="#@JessicaMarshall" title="JessicaMarshall">Jessica Marshall</a></h5> |
24 |
<blockquote>
|
25 |
<p>
|
26 |
Pellentesque est massa, posuere eu. |
27 |
</p>
|
28 |
</blockquote>
|
29 |
</div>
|
30 |
<div class="tweet"> |
31 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/img/team/4.png" alt="Ann De Wever" /> |
32 |
<h5><a href="#@AnnDeWever" title="Ann De Wever">Ann De Wever</a></h5> |
33 |
<blockquote>
|
34 |
<p>
|
35 |
Nulla facilisi. Nam lacinia tristique ante. |
36 |
</p>
|
37 |
</blockquote>
|
38 |
</div>
|
39 |
<p id="get-tweets-wrapper"> |
40 |
<a href="#twitter"> |
41 |
Get More Tweets! |
42 |
</a>
|
43 |
</p>
|
44 |
</div>
|
Nothing surprising here, we still use blockquotes for the content of the tweet. We are also linking to the twitter page through the h5. We are also using the same syntax for the "Get More Tweets" link as we did for the Read More link.
The Footer
The last part of our HTML document is going to be the footer. It is going to be very easy to build. We just need a wrapper with an ID of “footer", another containing div for the image, and a paragraph for our legal notice and company name.
1 |
<div id="footer"> |
2 |
<div id="footer-image"></div> |
3 |
<p id="footer-text"> |
4 |
Copyright © 2009 Roadside Studio<br /> |
5 |
All Rights Reserved |
6 |
</p> |
7 |
</div> |
Really nothing too fancy there. Just notice that we replaced the copyright symbol with © because it wouldn’t display correctly otherwise.
Finished
Okay, well believe it or not, but we are actually done with our markup. You’ve realised that it is actually not that hard to produce correct and valid HTML code just by following some layer groups. The key is to proceed logically and slowly, to be sure not to miss anything.
This is the code we’ve made:
1 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
2 |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" > |
3 |
<head>
|
4 |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
5 |
<meta name="keywords" content="Roadside, Studio, Design, Web, Icons, Logos" /> |
6 |
<meta name="description" content="Roadside Studio is a web design agency that makes beautiful websites!" /> |
7 |
<meta name="author" content="Felix Boyeaux" /> |
8 |
<meta name="robots" content="all" /> |
9 |
|
10 |
<link rel="stylesheet" media="screen" type="text/css" title="Style" href="css/style.css" /> |
11 |
|
12 |
<title>Roadside Studio</title> |
13 |
</head>
|
14 |
<body>
|
15 |
<!-- STATUS BAR -->
|
16 |
<div id="status-bar"> |
17 |
<div id="status-bar-content"> |
18 |
<form action="#search" method="post" id="search-form"> |
19 |
<p>
|
20 |
<input type="text" name="query" value="Search" /> |
21 |
<input type="submit" name="submit" value="Search!" /> |
22 |
</p>
|
23 |
</form>
|
24 |
<div id="status-bar-commands"> |
25 |
<p id="welcome">Welcome, Guest</p> |
26 |
<p id="action-bar"> |
27 |
<a href="#login" title="Login">Login</a> |
28 |
<a href="#sitemap" title="Sitemap">Sitemap</a> |
29 |
<a href="#license" title="License">License</a> |
30 |
</p>
|
31 |
</div>
|
32 |
</div>
|
33 |
</div>
|
34 |
<!-- HEADER -->
|
35 |
<div id="header"> |
36 |
<div id="logo"> |
37 |
<h1><a href="#home" title="Home Page">Roadside</a></h1> |
38 |
<h2>Studio</h2> |
39 |
</div>
|
40 |
</div>
|
41 |
<!-- CONTENT -->
|
42 |
<div id="content"> |
43 |
<!-- TABS -->
|
44 |
<ul id="tabs"> |
45 |
<li id="previous"> |
46 |
<a href="#previous" title="Previous"><</a> |
47 |
</li>
|
48 |
<li id="home" class="current"> |
49 |
<a href="#home" title="Home">Home</a> |
50 |
</li>
|
51 |
<li id="portfolio"> |
52 |
<a href="#portfolio" title="Portfolio">Portfolio</a> |
53 |
</li>
|
54 |
<li id="about"> |
55 |
<a href="#about" title="About">About</a> |
56 |
</li>
|
57 |
<li id="contact"> |
58 |
<a href="#contact" title="Contact">Contact</a> |
59 |
</li>
|
60 |
<li id="next"> |
61 |
<a href="#next" title="Next">></a> |
62 |
</li>
|
63 |
</ul>
|
64 |
<!-- PAGE WRAPPER -->
|
65 |
<div id="page-wrapper"> |
66 |
<!-- SLIDESHOW -->
|
67 |
<div id="slideshow"> |
68 |
<div id="slides"> |
69 |
<a href="#portfolio.work1" title="See details" class="thumb default-slide"> |
70 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/./img/slideshow/1.png" alt="Flex Engine Web Design" class="slideshow-image" /> |
71 |
</a>
|
72 |
<a href="#portfolio.work2" title="See details" class="thumb"> |
73 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/./img/slideshow/2.png" alt="Concept Labs Portfolio" class="slideshow-image" /> |
74 |
</a>
|
75 |
<a href="#portfolio.work3" title="See details" class="thumb"> |
76 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/./img/slideshow/3.png" alt="Everlast Studio" class="slideshow-image" /> |
77 |
</a>
|
78 |
</div>
|
79 |
<div id="slideshow-commands"> |
80 |
<a href="#previous" title="Previous" id="previous-slide"><</a> |
81 |
<a href="#next" title="Next" id="next-slide">></a> |
82 |
<h4>
|
83 |
<a href="#portfolio.work1" title="See details" id="slide-title"> |
84 |
Flex Engine Web Design |
85 |
</a>
|
86 |
</h4>
|
87 |
</div>
|
88 |
</div>
|
89 |
<!-- MESSAGE -->
|
90 |
<div id="message"> |
91 |
<h3>We build great websites!</h3> |
92 |
<p>
|
93 |
Curabitur nec sem in risus adipiscing feugiat. Etiam elementum malesuada purus. |
94 |
Quisque nec mi eu mauris ornare aliquam. Praesent adipiscing, |
95 |
metus sed luctus condimentum, quam turpis interdum tortor, |
96 |
in dignissim magna urna tempor odio. Integer porttitor. Nam dolor urna, |
97 |
ultricies vitae, porttitor ut, dignissim vitae, elit. |
98 |
</p>
|
99 |
<p id="contact-info"> |
100 |
<span id="phone">+33 1 23 45 67 89</span> |
101 |
<span id="address"> |
102 |
34, Avenue des Champs-<br /> |
103 |
Elysées, 75006, Paris,<br /> |
104 |
France |
105 |
</span>
|
106 |
</p>
|
107 |
</div>
|
108 |
</div>
|
109 |
<!-- BLOG MODULE -->
|
110 |
<div class="module" id="blog"> |
111 |
<h4 class="module-header-bar">Latest entries from the blog</h4> |
112 |
<div class="blog-entry"> |
113 |
<h5><a href="#blogentry1" title="Vivamus sed risus">Vivamus sed risus</a></h5> |
114 |
<p class="meta">By Jonathan Davidson - 05 / 08 / 09</p> |
115 |
<blockquote class="content"> |
116 |
<p>
|
117 |
Vivamus sed risus quis felis sagittis cursus. Duis blandit tristique turpis. Nulla feugiat vehicula metus. |
118 |
</p>
|
119 |
</blockquote>
|
120 |
</div>
|
121 |
<div class="blog-entry"> |
122 |
<h5><a href="#blogentry2" title="Pellentesque pulvinar">Pellentesque pulvinar</a></h5> |
123 |
<p class="meta">By The Team - 05 / 01 / 09</p> |
124 |
<blockquote class="content"> |
125 |
<p>
|
126 |
Pellentesque pulvinar dolor nec orci. Pellentesque scelerisque elit. |
127 |
</p>
|
128 |
</blockquote>
|
129 |
</div>
|
130 |
<div class="blog-entry"> |
131 |
<h5><a href="#blogentry3" title="Cras in nibh">Cras in nibh</a></h5> |
132 |
<p class="meta">By Nicholas Denman - 05 / 01 / 09</p> |
133 |
<blockquote class="content"> |
134 |
<p>
|
135 |
Quisque dapibus, justo a bibendum pellentesque, tellus felis cursus libero, posuere sodales diam ipsum in lorem. |
136 |
</p>
|
137 |
</blockquote>
|
138 |
</div>
|
139 |
<p id="read-more-wrapper"> |
140 |
<a href="#blog" title="Read More"> |
141 |
Read More |
142 |
</a>
|
143 |
</p>
|
144 |
</div>
|
145 |
<!-- TWITTER MODULE -->
|
146 |
<div class="module" id="twitter"> |
147 |
<h4 class="module-header-bar">Follow the Roadside Team on Twitter</h4> |
148 |
<div class="tweet"> |
149 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/img/team/1.png" alt="Jonathan Davidson" /> |
150 |
<h5><a href="#@JonathanDavidson" title="Jonathan Davidson">Jonathan Davidson</a></h5> |
151 |
<blockquote>
|
152 |
<p>
|
153 |
Proin et libero. Curabitur molestie mauris eu massa. |
154 |
</p>
|
155 |
</blockquote>
|
156 |
</div>
|
157 |
<div class="tweet"> |
158 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/img/team/2.png" alt="Nicholas Denman" /> |
159 |
<h5><a href="#@NicholasDenman" title="Nicholas Denman">Nicholas Denman</a></h5> |
160 |
<blockquote>
|
161 |
<p>
|
162 |
Etiam felis ligula. |
163 |
</p>
|
164 |
</blockquote>
|
165 |
</div>
|
166 |
<div class="tweet"> |
167 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/img/team/3.png" alt="Jessica Marshall" /> |
168 |
<h5><a href="#@JessicaMarshall" title="JessicaMarshall">Jessica Marshall</a></h5> |
169 |
<blockquote>
|
170 |
<p>
|
171 |
Pellentesque est massa, posuere eu. |
172 |
</p>
|
173 |
</blockquote>
|
174 |
</div>
|
175 |
<div class="tweet"> |
176 |
<img src="http://nettuts.s3.amazonaws.com/336_siteFromScratch/img/team/4.png" alt="Ann De Wever" /> |
177 |
<h5><a href="#@AnnDeWever" title="Ann De Wever">Ann De Wever</a></h5> |
178 |
<blockquote>
|
179 |
<p>
|
180 |
Nulla facilisi. Nam lacinia tristique ante. |
181 |
</p>
|
182 |
</blockquote>
|
183 |
</div>
|
184 |
<p id="get-tweets-wrapper"> |
185 |
<a href="#twitter"> |
186 |
Get More Tweets! |
187 |
</a>
|
188 |
</p>
|
189 |
</div>
|
190 |
</div>
|
191 |
<div id="footer"> |
192 |
<div id="footer-image"></div> |
193 |
<p id="footer-text"> |
194 |
Copyright © 2009 Roadside Studio<br /> |
195 |
All Rights Reserved |
196 |
</p>
|
197 |
</div>
|
198 |
</body>
|
199 |
</html>
|
You can check its validity once again and see that it is successfully check as xHTML 1.0 Strict!
Step Five – The CSS
The Cascading Style Sheet language is one with an extremely easy syntax and is therefore very easy to learn. However, primarily due to browser inconsistencies, it can be utterly hard to master. We will try to keep the CSS as simple and concise as possible, while still trying to make it work on all modern browsers. To do this, there is one concept we need to master. I’m talking about the box model.
The box model is the way a box is displayed in your web page. But one image would probably be better than a long explanation.



This is the W3C’s standard box model. What is important to grasp here is that the actual width of the box is not the one defined by the width property, but the addition of the width, the padding, and the border. So let’s say we have a box with a width set to 200px, 25px padding on both sides and a border that is 5px thick around this box. The actual displayed width of the box will be 260px and not 200px as we wanted it to be. But that is fine, if we want a box that is strictly 200px wide, we’ll just need to set the width property to 140px and we’re all set. The important thing is just to know how this actually works. This will avoid a lot of headaches later on.
Okay, now that you are familiar with the concept of the W3C’s box model, we can get started coding our design.
The CSS Reset
I was talking about browser inconsistencies before. Those include some browser setting a margin of 10px to each block, some setting it to 15px and more of such issues. This can obviously cause some problems while coding because we won’t necessarily reset all those properties in our code. To solve this problem and hence help us produce pixel-perfect sites, we’ll want to use a CSS Reset. There are a lot of them available out there, but in my honest opinion, Eric Meyer’s is still the best one. I just like the way it resets pretty much everything and allows us full control over our layout. You can fetch it over here: http://meyerweb.com/eric/tools/css/reset/ . I’ve decided to put this in its own CSS file called reset.css and I then put it in the CSS folder of our template.
1 |
html, body, div, span, applet, object, iframe, |
2 |
h1, h2, h3, h4, h5, h6, p, blockquote, pre, |
3 |
a, abbr, acronym, address, big, cite, code, |
4 |
del, dfn, em, font, img, ins, kbd, q, s, samp, |
5 |
small, strike, strong, sub, sup, tt, var, |
6 |
b, u, i, center, |
7 |
dl, dt, dd, ol, ul, li, |
8 |
fieldset, form, label, legend, |
9 |
table, caption, tbody, tfoot, thead, tr, th, td { |
10 |
margin: 0; |
11 |
padding: 0; |
12 |
border: 0; |
13 |
outline: 0; |
14 |
font-size: 100%; |
15 |
vertical-align: baseline; |
16 |
background: transparent; |
17 |
}
|
18 |
body { |
19 |
line-height: 1; |
20 |
}
|
21 |
ol, ul { |
22 |
list-style: none; |
23 |
}
|
24 |
blockquote, q { |
25 |
quotes: none; |
26 |
}
|
27 |
blockquote:before, blockquote:after, |
28 |
q:before, q:after { |
29 |
content: ''; |
30 |
}
|
31 |
|
32 |
/* remember to define focus styles! */
|
33 |
:focus { |
34 |
outline: 0; |
35 |
}
|
36 |
|
37 |
/* tables still need 'cellspacing="0"' in the markup */
|
38 |
table { |
39 |
border-collapse: collapse; |
40 |
border-spacing: 0; |
41 |
}
|
I just decided to remove the content: none; line because it made the CSS validation fail. * Editor's note: remember folks, validation should work for you, not against. It's okay if your page doesn't validate IF you know exactly why. Since I knew I wasn’t going to need inserts and deletes, I removed those resets as well, just to make this thing a little more lightweight.
If you reload the index.html file in your browser, you’ll see that nothing has changed. This is due to the fact that we didn’t yet link to the stylesheet in out HTML. We will not add a link tag in out head section though. Instead, we’ll just call the reset.css file from our main stylesheet using the @import command when we start building it.
The Typography
I usually split my CSS in two parts. One that controls the layout of the page, this is my main stylesheet, and one controlling the typography. This includes text align, font colour, font size, letter spacing, line height and so on. This is a good thing to do because it allows you more flexibility in your coding process. Let’s say you want to change the h1’s font size to 48px instead of 36px, well instead of starting digging in your style.css which probably is several hundred lines long, you can just open you typography stylesheet, find the styles related to the h1 tag, change the font size and you’re done!
When coding our typography stylesheet, our Photoshop layout will be extremely useful. We can grab the Type Tool (T) in Photoshop, and start highlighting the different text blocks our design. That way, we can see that the h1 is going to have a font size of 48px, a colour of #4d4d4d, and a font set to Myriad Pro. This last point will cause some problems. Myriad Pro is not a standard web font, so we cannot define a font-family starting with Myriad Pro and think that everyone will see our design the way they should. We are going to solve this problem later on using some more advanced web techniques, but for now, we’ll just define a font-family property with Myriad Pro included, and some other fallback fonts in case the reader doesn’t have Myriad Pro installed on his computer.
If we continue like this, scanning through our PSD to get all the font information, we can see that our h3 tags should have a font size of 24px, that our h5 tags have a colour of #6eb9cc and so on. If we proceed logically, this is what we will come up with:
1 |
h1 { |
2 |
color: #4d4d4d; |
3 |
font-family: "Myriad Pro", Helvetica, Arial, sans-serif; |
4 |
font-size: 48px; |
5 |
font-weight: normal; |
6 |
}
|
7 |
|
8 |
h1 a { color: #4d4d4d; text-decoration: none; } |
9 |
|
10 |
h2 { |
11 |
color: #6ec9cc; |
12 |
font-family: "Myriad Pro", Helvetica, Arial, sans-serif; |
13 |
font-size: 12px; |
14 |
letter-spacing: 28px; |
15 |
text-transform: uppercase; |
16 |
}
|
17 |
|
18 |
h3 { |
19 |
color: #6ec9cc; |
20 |
font-family: "Myriad Pro", Helvetica, Arial, sans-serif; |
21 |
font-size: 24px; |
22 |
font-weight: normal; |
23 |
}
|
24 |
|
25 |
h4 { |
26 |
color: #ffffff; |
27 |
font-family: Arial, Helvetica, sans-serif; |
28 |
font-size: 12px; |
29 |
font-weight: normal; |
30 |
text-align: center; |
31 |
}
|
32 |
|
33 |
h4 a { color: #ffffff; text-decoration: none; } |
34 |
|
35 |
h5 { |
36 |
color: #6ec9cc; |
37 |
font-family: "Myriad Pro", Helvetica, Arial, sans-serif; |
38 |
font-size: 18px; |
39 |
font-weight: normal; |
40 |
}
|
41 |
|
42 |
h5 a { color: #6ec9cc; text-decoration: none; } |
43 |
|
44 |
/* Paragraph styling */
|
45 |
|
46 |
p { |
47 |
color: #525252; |
48 |
font-family: Arial, Helvetica, sans-serif; |
49 |
font-size: 12px; |
50 |
}
|
51 |
|
52 |
p.meta { color: #707070; font-size: 10px; text-align: right; } |
53 |
|
54 |
p#footer-text { text-align: center; } |
55 |
|
56 |
div#message p { color: #4d4d4d; line-height: 20px; } |
57 |
|
58 |
/* Link styling */
|
59 |
|
60 |
a { |
61 |
color: #999999; |
62 |
text-decoration: none; |
63 |
}
|
64 |
|
65 |
a:hover { text-decoration: none; } |
66 |
|
67 |
p#action-bar a { color: #ffffff; } |
68 |
|
69 |
p#action-bar a:hover { color: #6eb9cc; text-decoration: none; } |
I don’t think there is very much I need to explain. This is just the very basic appearance styling. Note that I’m defining styling for standard paragraph tags and standard anchor tags before starting to define the appearance of more specific text blocks such a meta paragraphs for instance. This is part of a "Don’t Repeat Yourself" concept of coding. The fallbacks font I decided to use are Helvetica and Arial, they are not great replacements for Myriad, but we will probably don’t need them anyway as I’ll explain later. It is just to be sure.
One thing I want to talk about is the coding style here. Of course, indents are important for the readability of the code, but not only. At first glance, you may think my code looks a little bit messy, but if you look at it more carefully, you’ll notice that I’m following a very strict syntax. The first point of this syntax is to order properties alphabetically. This greatly helps finding a property when you want to edit it later on. Next is the fact that I keep my styling on one single line if I don’t use more than three properties for the element and that it is not a default styling being declared such as for the p tag. While it can be argued whether it is readable or not, it drastically diminishes the file size. In my opinion, it is not hard to read even though the declarations are kept on one single line. It even makes the CSS more concise and easier to browse.
The most important thing with your coding style is consistency. If you don’t want to use one-line declaration, just don’t. You need to feel comfortable with the way you code. I’m not saying my way is the best one; I just like it that way. I encourage you however to find your own style to code even faster!
Setting up our main stylesheet
When we were done with the reset, I told you not to include it in the HTML file directly using a link tag because we were going to call it from our main stylesheet. You could obviously include all your CSS files directly in the HTML code, but I decided not to, since it keeps the head section tidier.
We’ll need to create our master stylesheet. I usually call those style.css, but you could call it main.css, master.css, screen.css or whatever. Within this stylesheet, we’ll need to include first our reset, then our typography stylesheet. To do so, I’m using the @import rule. Your first lines in the style.css file should look like this:
1 |
@import url('reset.css'); |
2 |
@import url('typography.css'); |
With those few lines, we include our two stylesheets in the style.css file, and we just have to call one file in our head section.
1 |
<link title="Style" href="css/style.css" rel="stylesheet" media="screen" type="text/css" /> |
If we look at our web page now, this is what we would see:



I’d have to agree with you if you’d say that it doesn’t look awesome for the moment, but you can still see some details looking exactly as we want them to such as the meta paragraphs or even the logo. Okay, now that out master stylesheet is set up, we can start styling the page for real!
The Body
We just need to set some basic styling for the body tag. This includes centring the design using margin: auto, setting a background colour, and setting the width to 100%.
1 |
body { |
2 |
background-color: #f8f8f8; |
3 |
margin: auto; |
4 |
width: 100%; |
5 |
}
|
The Status Bar
As always, we’ll just start from the top and design our way down to the footer. I like coding my designs divided in blocks. I start with the header for instance, then take a break, design the content and so on. It helps motivating me. This also involves completely finishing an area before starting another.
So, before we start the actual CSS coding of the status bar, let’s take some time and see what images we need for it. The first is a background image, which is a simple gradient that will be repeated on the x-axis. The second is a background for the action bar: a rounded rectangle. We could obviously have used border-radius property here, but I decided to use an image in order to make it pixel-perfect through all browsers. The last image we need for our status bar is a background for the search box.
Let’s start with the background image. As I’ve said, we will repeat this image on the x-axis, so we just need an image that is 1px wide. This will drastically reduce its size. So start by grabbing the Single Column Marquee Tool in Photoshop, go to the Status Bar / Box layer group, hide the “Border" layer, and merge the “Background" and the “Shadow" layer together. Once this is done, select a slice of this recently created layer with your selection tool, copy it, and paste it in a new document. This document should be 1*50px. Because of some box model quirks, we’ll need to reduce this height to 40px. Just crop the 10 top pixels and then save it for Web & Devices (Alt + Shift + Ctrl + S) in PNG 24, and call it status-bar-bg.png. Save For Web & Devices offer great compression tools in order to make the file sizes as small as possible. This is very important when working with the web, and that is why you should always use that tool.



Now, the action bar background; open the “Action Bar" layer group, and select the layer called “Shape". Select the entire document (Ctrl + A), copy the layer, and paste it on a new document. You’ll need to rasterize the vector shape in order to copy it correctly. Don’t forget to set the layer’s opacity to 55% again. Save this for Web & Devices again, and call it action-bar-bg.png.

Final step for converting the design into images will be the Search Field. Just go to the “Search Field" layer group, hide the “Search" layer, and merge the magnifier and the shape together. Again, select the entire document with Ctrl + A, and copy it onto a new document. Save it as search-field.png.

Okay, now that we are done with the images, we can start coding. The first thing we want to do is to set up the container. Set its width and height, as well as a background image and a border.
1 |
div#status-bar { |
2 |
background: url('../img/status-bar-bg.png') repeat-x; |
3 |
border-bottom: 2px groove #ffffff; |
4 |
height: 40px; |
5 |
width: 100%; |
6 |
}
|
The groove style for the border gives us this nice look we were struggling to obtain in Photoshop. We’ve set a width of 40px even though our background is 50px because of the box model.
Then we want to make sure the content of this bar is centred. The thing here is that we want the background to take 100% of the width while the content should be centred. This is why we used a wrapping div that contains pretty much everything we put in our status bar. We should apply a width of 800px to it as well as some margin.
1 |
div#status-bar-content { |
2 |
margin: 10px auto 0px auto; |
3 |
width: 800px; |
4 |
}
|
In order to place the two parts of this status bar, the left and the right, correctly, we are setting width and float properties.
1 |
div#status-bar-commands { |
2 |
width: 400px; |
3 |
}
|
4 |
|
5 |
form#search-form { |
6 |
float: right; |
7 |
width: 200px; |
8 |
}
|
Now we need to style the status-bar-commands in order to make the action bar float in the middle of the status bar. We also put the right background image to the status bar. Paddings and margins are obviously also used to make things look the way they should. Keep the box model in mind while setting those properties up! That is the reason why we set the action bar’s height to 14px instead of 30px; we’ve got 8px padding.
1 |
p#welcome { |
2 |
float:left; |
3 |
padding-top: 7px; |
4 |
width: 150px; |
5 |
}
|
6 |
|
7 |
p#action-bar { |
8 |
background: url('../img/action-bar-bg.png') no-repeat; |
9 |
height: 14px; |
10 |
margin-left:200px; |
11 |
padding: 8px 28px; |
12 |
width: 154px; |
13 |
}
|
14 |
|
15 |
p#action-bar a:before { |
16 |
content: '| '; |
17 |
}
|
18 |
|
19 |
p#action-bar a[title="License"]:after { |
20 |
content: ' |'; |
21 |
}
|
We’re adding “|"s to separate the links in the action bar. I chose to do so because it is more semantically correct. Indeed, those pipes have absolutely nothing to do with our content, so putting them in the HTML wouldn’t actually be right. Notice the pretty complex last selector that selects the last link and adds a pipe after it as well as before it.
The last point will be styling the search field and add the background image to it. We’ll need to reset some browser default style that is added to inputs, and we also need to hide the submit button. This is maybe not the best thing to do when we’re talking about accessibility, but still, I chose to make design go before accessibility on this one.
1 |
form#search-form input[type="text"] { |
2 |
background: url(../img/search-field.png) no-repeat; |
3 |
border:none; |
4 |
height:20px; |
5 |
padding: 5px 0px 0px 30px; |
6 |
width:170px; |
7 |
}
|
8 |
|
9 |
form#search-form input[type="submit"] { |
10 |
display: none; |
11 |
}
|
This is what we should have now:



It’s looking pretty similar to our PSD doesn’t it? Well that’s exactly what we want! Let’s now proceed with the header.
The Header
The header is fairly basic so It will actually be pretty easy to code.
The first thing we need to do though is to prepare our image. Just navigate to the “Header" layer group, and merge the “Image" layer and the “Shape" layer together. Now select the document with Ctrl + A, and finally copy and paste it in a new document. The file should be 1600*250px.
We’ve got a problem now though. We don’t want the header image to repeat itself over the header if the reader’s screen resolution is wider than 1600px. We therefore need to fade out the edges by adding a layer mask to it, and making the left and right edges fade out to transparency. However, transparency on such big images can be extremely long to load, so I’ve just filled the background with #6eb9cc.
This image is huge, so we need to compress it in order to make it load faster. I’ve chosen to save it in PNG 8 with only 256 colours. This will reduce the size with almost 80% compared to PNG 24, which is huge! Call this file header-image.png.
Okay, to now the code. We want the header image to be centred within the “header" div. But in order to let widescreens display our design correctly, we need to apply a background colour as well so that it can fade out nicely. We also set a border. Instead of using groove, I’m using the ridge style, which is the exact opposite, because it puts the start colour at the top and not at the bottom, which is what we want in this case. I’m just applying some styling to the logo as well to place it correctly.
1 |
div#header { |
2 |
background: url('../img/header.png') no-repeat; |
3 |
background-color: #6eb9cc; |
4 |
border-bottom: 2px ridge #ffffff; |
5 |
height: 250px; |
6 |
width: 100%; |
7 |
}
|
8 |
|
9 |
div#logo { |
10 |
margin: auto; |
11 |
padding-top: 35px; |
12 |
width: 800px; |
13 |
}
|
That’s actually all we have to do with our header. We can now check the result in a browser:



The Content Box
We have to break our semantic rule here a little bit. Indeed, in order to put the top and bottom shadow to the content div, we need to create to empty divs in our markup: one with an ID of “content-top-shadow" and the other with an ID of “content-bottom-shadow". Those the first div should be placed between the header div and the content div, and the other one should be placed between the content and the footer. I know we could have used CSS 3’s multiple backgrounds to solve this problem, but the issue is that multiple backgrounds are not yet supported by a lot of browsers, so we will just stick with this technique for now.
Before we code we need to fetch out images. Just go to the “Content" / “Box" layer group, and merge the background shape with the two shadow layers. Then use the Single Column Marquee Tool and select a 1px slice of the background. Copy and paste it in a new document. Now use the Crop Tool and crop the top 20px of the image. Save this for Web & Devices as PNG 24, and call it content-top-shadow.png. Then do Edit->Transform->Rotate 180, and save it again, this time as content-bottom-shadow.png.
To the div#content, we are just adding some basic box layout such as padding and width, but the interesting part here are the two “content-shadow" containers. We’re obviously setting up a height and width, and a background image, which is repeated on the x-axis. This produces the illusion of a shadow. I’m also just applying a clear: both; to the content-bottom-shadow, because I know my modules will float and that it won’t work otherwise.
1 |
div#content { |
2 |
margin: auto; |
3 |
padding-bottom: 50px; |
4 |
position: relative; |
5 |
width: 800px; |
6 |
}
|
7 |
|
8 |
div#content-top-shadow { |
9 |
background: url('../img/content-top-shadow.png') repeat-x; |
10 |
height: 20px; |
11 |
width: 100%; |
12 |
}
|
13 |
|
14 |
div#content-bottom-shadow { |
15 |
background: url('../img/content-bottom-shadow.png') repeat-x; |
16 |
clear: both; |
17 |
height: 20px; |
18 |
width: 100%; |
19 |
}
|
Just notice that we set position: relative; the content div. This will come in handy later on when we will place our tabbed navigation menu.
Good, now that we are finished with finished this box, we can start styling the content!
The Page Wrapper
Instead of starting with styling the menu, we will just make sure our page wrapper is displayed correctly first.
To start with, we will add some basic box styling to the page wrapper. We are define width, height, padding and margin as we chose to do in our PSD, while keeping the W3C’s box model in mind (yes, it is still haunting us!), and we add a white background colour and a border. Because we will use the float property to display the tabbed navigation menu, we need to clear: both; here, and since we are using a fix height, we also want to hide any overflow in order not to break our layout. Overflow shouldn’t happen, but we never know.
1 |
div#page-wrapper { |
2 |
background-color: #ffffff; |
3 |
border: 1px solid #bababa; |
4 |
clear: both; |
5 |
height: 233px; |
6 |
margin-top: 75px; |
7 |
overflow: hidden; |
8 |
padding: 15px; |
9 |
width: 768px; |
10 |
}
|
We now want to design our slideshow box. This is really basic styling. Thanks to the box model, we can use the border property to display the vertical separator we want between the slideshow and the message.
1 |
div#slideshow { |
2 |
border-right: 1px solid #b2b2b2; |
3 |
float: left; |
4 |
padding-right: 15px; |
5 |
width: 375px; |
6 |
}
|
Now we want to make sure we only display one thumbnail when the page is loaded, because the way it is coded at the moment displays all three thumbs at the same time, which completely breaks our design. We could obviously let our JavaScript fix this for us, but it is just not acceptable to make it impossible for people without JS activated to see our page. After adding some styling to each thumbnail, we therefore hide all the thumbnails, and then just display the one with a class of “default-slide".
1 |
div#slides { |
2 |
border: 1px solid #a7a7a7; |
3 |
height: 200px; |
4 |
width: 370px; |
5 |
}
|
6 |
|
7 |
div#slides a.thumb { |
8 |
display:none; |
9 |
}
|
10 |
|
11 |
div#slides a.default-slide { |
12 |
display:block; |
13 |
}
|
Once we did this, the last step is to style the slideshow commands. We need to cut out some images from the PSD. You are starting to get used to the process, so just navigate to “Content" / “Wrapper" / “Slideshow" / “Commands" layer group, and rasterize all the layers. Then copy the left arrow, the right arrow, and the background to new documents, and save them as commands-previous-slide.png, commands-next-slide.png and commands-bg.png respectively.
We then need to include those into our template. I’m first defining the box layout, with its background-image, width and height and also a position: relative; to be able to centre it under the thumbnail.
We can then use a basic image replacement technique to make our previous and next commands look nice.
Finally, a margin-top on the title is necessary to centre it vertically.
1 |
div#slideshow-commands { |
2 |
background: url('../img/commands-bg.png') no-repeat; |
3 |
height: 19px; |
4 |
left: 15px; |
5 |
padding: 3px 25px; |
6 |
position: relative; |
7 |
width: 290px; |
8 |
}
|
9 |
|
10 |
a#previous-slide { |
11 |
background: url('../img/commands-previous-slide.png') no-repeat; |
12 |
display: block; |
13 |
float: left; |
14 |
height: 12px; |
15 |
margin-top: 2px; |
16 |
text-indent: -9000px; |
17 |
width: 9px; |
18 |
}
|
19 |
|
20 |
a#next-slide { |
21 |
background: url('../img/commands-next-slide.png') no-repeat; |
22 |
display: block; |
23 |
float: right; |
24 |
height: 12px; |
25 |
margin-top: 2px; |
26 |
text-indent: -9000px; |
27 |
width: 9px; |
28 |
}
|
29 |
|
30 |
div#slideshow-commands h4 { |
31 |
margin-top:1px; |
32 |
width:100%; |
33 |
}
|
Okay great, our slideshow is now displaying correctly. We just want to style the message and we’ll be done with the wrapper. Styling will be pretty easy because most of it was made in the typography.css file.
We are first setting up some box styling in order to make the message have a 15px left margin, and we are also applying a margin-bottom to the title to make things breathe.
1 |
div#message { |
2 |
margin-left: 410px; |
3 |
width: 350px; |
4 |
}
|
5 |
|
6 |
div#message h3 { |
7 |
margin-bottom: 20px; |
8 |
}
|
The hardest part of this will be styling the contact information. Before we get started, make sure to save the Phone and the Mail icon into two separate files and call them phone-icon.png and address-icon.png respectively. I feel that you all probably know how to do so by now so I don’t think it’s necessary to explain once again.
We will apply those images with a background image, but to be able to do so, we need to use the span tags as blocks, hence the display: block; on the span tags. The rest is simple, we add a background image to each span, make one float left, and use paddings to indent the text away from the icon.
1 |
p#contact-info span { |
2 |
display: block; |
3 |
}
|
4 |
|
5 |
span#phone { |
6 |
background: url('../img/phone-icon.png') no-repeat 0px 1px; |
7 |
float: left; |
8 |
margin-top: 25px; |
9 |
padding-left: 35px; |
10 |
width: 125px; |
11 |
}
|
12 |
|
13 |
span#address { |
14 |
background:url('../img/mail.png') no-repeat 160px 30px; |
15 |
padding:5px 0px 0px 195px; |
16 |
}
|
If we take a look at the design now this is what we will see:



It still doesn’t look great just yet, but we are really starting to get somewhere. The next step is going to make it look even better!
The Navigation Menu
This will be a tough nut to crack. It is a pretty complex menu we are using here, and the fact that it is lined up to the right doesn’t make things easier. However, the fact that we already designed the menu in Photoshop will obviously help us a little bit.
Sprites
We are going to use something called CSS Sprites. Instead of using an image for each link, we will just combine them all into one big image, called sprite. This technique has numerous advantages. Instead of loading about twenty images, including hover and active states, we just have to load one. This can drastically reduce the loading time and is also good for your server.
So, how do we do such a sprite? Start by creating a new document that is 425*115px. Then drag and drop the tabs menu from our PSD to this file. Remove all unnecessary spacing with Ctrl + T and finally remove the hover and active state we put to Home and Portfolio in order to make our design look real. This line just contains our default buttons: when they are neither hovered nor active. This is what it should look like:



Then duplicate this layer group twice, and place them with 5px space. The second line will be our hovered state, so the font colour should be #6eb9cc. The third is active state, so the font should be bold. This is what our sprite looks like once finished:



You should obviously make your background transparent. I just added a white background to make it more legible as a screenshot.
Once this is done, Save it for Web and Devices in PNG 24, and call it tabs-sprite.png.
The important thing to keep in mind when designing sprites is to keep the width of each element constant, and to align them nicely in order to be sure to use background-position later on without problems.
Okay, we now have out sprite. You may wonder how we are going to apply this to our unordered list that really doesn’t look like a horizontal tabbed navigation menu. The answer is to come.
Before we actually start using our background images, we just want to place the menu right. This is where a relative positioning on the content comes in handy. By using an absolute positioning on the tabs, we can now place it referring to its parent and not the window. This means that the (0, 0) coordinate will not be the top left of the window, but of the “content"! This gives us a lot of flexibility in our coding.
After placing the list, we now need to style the bullet points. By floating them to the left, we make the items being displayed on one single row. After adding width and height properties too, we set the background image to our sprite file. This means that each element of the unordered menu list will share the same background, and this is the subtlety of CSS Sprites.
We are also using image replacement to remove the raw text links and to make the link clickable over the entire tab.
1 |
ul#tabs { |
2 |
margin-top: 30px; |
3 |
position: absolute; |
4 |
right: 0px; |
5 |
top: -65px; |
6 |
}
|
7 |
|
8 |
ul#tabs li { |
9 |
background: url('../img/tabs-sprite.png') no-repeat; |
10 |
float: left; |
11 |
height: 35px; |
12 |
margin-right: 1px; |
13 |
width: 70px; |
14 |
}
|
15 |
|
16 |
ul#tabs li a { |
17 |
display: block; |
18 |
height: 100%; |
19 |
text-indent: -9000px; |
20 |
width: 100%; |
21 |
}
|
Right, the next step will be to style each tab. We need to apply regular background position, then hover background position, and finally active and current position. This is for instance what it looks like for the “previous" tab:
1 |
ul#tabs li#previous { |
2 |
background-position: 0px 0px; |
3 |
width:80px; |
4 |
}
|
5 |
|
6 |
ul#tabs li#previous:hover { |
7 |
background-position: 0px -40px; |
8 |
}
|
9 |
|
10 |
ul#tabs li#previous.current, ul#tabs li#previous:active { |
11 |
background-position: 0px -80px; |
12 |
}
|
Just don’t worry too much about the width we set to it, it is simply because the “previous" tab is wider than the standard tabs. We don’t have to bother with this with the other tabs.
Just do so for each tab, and don’t forget to replace the pixel values with the correct ones. You can use Photoshop’s Ruler Tool (I) to help you. This is what the complete code looks like:
1 |
ul#tabs li#previous { |
2 |
background-position: 0px 0px; |
3 |
width:80px; |
4 |
}
|
5 |
|
6 |
ul#tabs li#previous:hover { |
7 |
background-position: 0px -40px; |
8 |
}
|
9 |
|
10 |
ul#tabs li#previous.current, ul#tabs li#previous:active { |
11 |
background-position: 0px -80px; |
12 |
}
|
13 |
|
14 |
ul#tabs li#home { |
15 |
background-position: -80px 0px; |
16 |
}
|
17 |
|
18 |
ul#tabs li#home:hover { |
19 |
background-position: -80px -40px; |
20 |
}
|
21 |
|
22 |
ul#tabs li#home.current, ul#tabs li#home:active { |
23 |
background-position: -80px -80px; |
24 |
}
|
25 |
|
26 |
ul#tabs li#portfolio { |
27 |
background-position: -150px 0px; |
28 |
}
|
29 |
|
30 |
ul#tabs li#portfolio:hover { |
31 |
background-position: -150px -40px; |
32 |
}
|
33 |
|
34 |
ul#tabs li#portfolio.current, ul#tabs li#portfolio:active { |
35 |
background-position: -150px -80px; |
36 |
}
|
37 |
|
38 |
ul#tabs li#about { |
39 |
background-position: -220px 0px; |
40 |
}
|
41 |
|
42 |
ul#tabs li#about:hover { |
43 |
background-position: -220px -40px; |
44 |
}
|
45 |
|
46 |
ul#tabs li#about.current, ul#tabs li#about:active { |
47 |
background-position: -220px -80px; |
48 |
}
|
49 |
|
50 |
ul#tabs li#contact { |
51 |
background-position: -290px 0px; |
52 |
}
|
53 |
|
54 |
ul#tabs li#contact:hover { |
55 |
background-position: -290px -40px; |
56 |
}
|
57 |
|
58 |
ul#tabs li#contact.current, ul#tabs li#contact:active { |
59 |
background-position: -290px -80px; |
60 |
}
|
61 |
|
62 |
ul#tabs li#next { |
63 |
background-position: -360px 0px; |
64 |
width: 65px; |
65 |
}
|
66 |
|
67 |
ul#tabs li#next:hover { |
68 |
background-position: -360px -40px; |
69 |
}
|
70 |
|
71 |
ul#tabs li#next.current, ul#tabs li#next:active { |
72 |
background-position: -360px -80px; |
73 |
}
|
Well that was all for the tabs! This is what our template looks like now:



The Blog Module
We’ll start off with the basics as usual. Some obvious layout styling gives us something like this:
1 |
div#blog { |
2 |
float: left; |
3 |
margin: 50px 15px 0px 0px; |
4 |
width: 385px; |
5 |
}
|
After this, we’ll just style the header bar. We need to make create an image to use as background here. Just go to the right layer group, hide the text layer, and merge the icon and the shape. Save this as blog-header-bar.png.
We can add this background image once we’ve set the height, width, padding and margin:
1 |
div#blog h4.module-header-bar { |
2 |
background: url('../img/blog-header-bar.png') no-repeat; |
3 |
height: 29px; |
4 |
margin-bottom: 15px; |
5 |
padding-top: 13px; |
6 |
width: 385px; |
7 |
}
|
The next step will be to style each entry. Since most of the job was done in typography.css, we don’t need to do very much here, just add some margins and paddings basically.
1 |
div#blog div.blog-entry { |
2 |
margin-left:15px; |
3 |
}
|
4 |
|
5 |
div#blog div.blog-entry h5 { |
6 |
float:left; |
7 |
width:200px; |
8 |
}
|
9 |
|
10 |
div#blog div.blog-entry blockquote { |
11 |
clear:both; |
12 |
padding:10px 0px 10px 15px; |
13 |
}
|
14 |
|
15 |
div#blog div.blog-entry p.meta { |
16 |
padding-top:4px; |
17 |
}
|
The final step is to style the "Read More" link. Because we are going to use three states for this button (regular, hover and active) we will use a sprite here as well. Just drag the right layer group in a new document, and duplicate it twice. I left 10px between each state. For the hover state, I just changed the text colour to #6eb9cc, and for the active state, I just reversed both the Gradient Overlay and the Stroke to create a 3D effect when clicking on it. This is what my sprite looks like:

I saved it as read-more-button.png. To apply this, we will basically do as we did for the tabs. We also need to make the button float right and have some margins.
1 |
p#read-more-wrapper { |
2 |
float:right; |
3 |
margin-top:10px; |
4 |
width:215px; |
5 |
}
|
6 |
|
7 |
p#read-more-wrapper a { |
8 |
background:url('../img/read-more-button.png') no-repeat; |
9 |
border:none; |
10 |
display:block; |
11 |
height:30px; |
12 |
text-indent:-9000px; |
13 |
width:214px; |
14 |
}
|
15 |
|
16 |
p#read-more-wrapper a:hover { |
17 |
background-position: 0px -30px; |
18 |
}
|
19 |
|
20 |
p#read-more-wrapper a:active { |
21 |
background-position: 0px -60px; |
22 |
}
|
We are now done we the blog module! Let’s take a look at what it looks like.



The Twitter Module
This is pretty much the same as the blog module, so I’ll just go through this more quickly.
I guess there is no need to explain how you should do to get the header bar background. Just remember to hide the text before merging. Call this image twitter-header-bar.png.
We add some margins and a width to the box, and then append the header bar’s background just as we did for the blog.
1 |
div#twitter { |
2 |
margin: 38px 0px 0px 415px; |
3 |
width: 375px; |
4 |
}
|
5 |
|
6 |
div#twitter h4.module-header-bar { |
7 |
background: url('../img/twitter-header-bar.png') no-repeat; |
8 |
height: 40px; |
9 |
padding-top: 26px; |
10 |
width: 385px; |
11 |
}
|
After that, we just style each tweet. Just notice that we make the picture float in order to make it appear on the left of the name. Margins and paddings are set using the box model.
1 |
div#twitter div.tweet { |
2 |
margin: 3px 0px 17px 30px; |
3 |
}
|
4 |
|
5 |
div#twitter div.tweet img { |
6 |
border: 1px solid #757575; |
7 |
float: left; |
8 |
height: 29px; |
9 |
margin-right: 15px; |
10 |
width: 29px; |
11 |
}
|
12 |
|
13 |
div#twitter div.tweet h5 { |
14 |
position: relative; |
15 |
top: -3px; |
16 |
}
|
The reason we positioned the h4 the way we did is because the default line-height of Myriad Pro is a little bit unconventional. Don’t worry however if you don’t want to have your code filled with position: relative, it is just a minor detail we are fixing here.
For the Get More Tweets buttons, just replace the text in your Read More sprite, and save it again, this time as get-more-tweets-button.png. After that, we use exactly the same technique we used for the Read More button.
1 |
p#get-tweets-wrapper { |
2 |
float:right; |
3 |
margin-top:9px; |
4 |
width:215px; |
5 |
}
|
6 |
|
7 |
p#get-tweets-wrapper a { |
8 |
background: url('../img/get-tweets-button.png') no-repeat; |
9 |
border: none; |
10 |
display: block; |
11 |
height: 30px; |
12 |
text-indent: -9000px; |
13 |
width: 214px; |
14 |
}
|
15 |
|
16 |
p#get-tweets-wrapper a:hover { |
17 |
background-position: 0px -30px; |
18 |
}
|
19 |
|
20 |
p#get-tweets-wrapper a:active { |
21 |
background-position: 0px -60px; |
22 |
}
|
By finishing this Twitter module, we also finish the content styling! I know it was really long, but just look at what we produced. I believe it was worth it!



It’s really starting to look awesome!
The Footer
Our footer is made of two parts. The first one is the image, and the other one is the text part.
For the same reasons we had to edit the header image a bit, we need to make the edges of the footer image fade out to #6eb9cc as well. Just copy the image on a new document, and use the Gradient Tool (G) to do so. Save this in PNG 8 and call it footer-image.
To add this to our document, the code we’ll use is almost exactly the same as the one we used for the header.
1 |
div#footer-image { |
2 |
background: url('../img/footer-image.png') no-repeat #6eb9cc; |
3 |
border-top: 2px groove #ffffff; |
4 |
border-bottom:2px ridge #ffffff; |
5 |
height:50px; |
6 |
width:100%; |
7 |
}
|
Finally, for the footer text, we are adding the already created content-top-shadow.png image as a background image to create the shadow effect. We are also obviously setting height, width and some padding.
1 |
p#footer-text { |
2 |
background: url('../img/content-top-shadow.png') repeat-x; |
3 |
height: 37px; |
4 |
padding-top: 13px; |
5 |
width: 100%; |
6 |
}
|
Done with the CSS
And that was it; we are now done with the CSS! That was pretty difficult wasn’t it? The important thing to remember when coding a layout is to proceed logically, always remembering the box model. Once you know what you are doing with it, you’ll code much more efficiently and you won’t have to struggle that much with cross-browser bugs. This is what our page looks like in Firefox:



I can assure you that this page looks exactly the same in IE 8, Safari 3 and 4, Chrome 1 and 2, Firefox 3, and Opera 9.5! However if we now look at how it looks in IE 7, we’ll notice several defects. If you don’t have IE 7 on your computer, just run IE 8 in compatibility mode and you’ll see the page just as you would in IE 7.
Those issues are for instance:
- Status bar is too thin
- Action bar is not correctly positioned, and the lack of :before makes the padding go crazy
- The page wrapper is not correctly positioned
- The slideshow title is not correctly positioned.
This might look like a lot, but it actually isn’t. They can be easily fixed using either the !important hack or a conditional comment. I don’t like CSS Hacks, so I’m going to stick with a conditional stylesheet. But feel free to use whichever technique you want.
Fixing IE Problems
I said we were going to use conditional comments. What are those? Well they are simply a way to target Microsoft’s browsers and use a specific tag or group of tags that we only be shown in IE. Other browsers will just interpret this as a comment and will therefore not display the tag. In our case, we are going to put a link tag to an external stylesheet in this comment.
1 |
<!--[if IE 7]>
|
2 |
<link rel="stylesheet" media="screen" type="text/css" title="Style" href="css/ie7.css" />
|
3 |
<![endif]-->
|
Once this stylesheet is included, we can start fixing the few problems we are facing. Create a new stylesheet called ie7.css, and save it in our css folder.
The first thing we need to do is to fix the height of the status bar. Nothing too complicated, just set a new height, and be sure that the background is attached to the bottom since it is not 50px high but only 40.
1 |
div#status-bar { |
2 |
background-position: bottom; |
3 |
height: 50px; |
4 |
}
|
We then need to fix the problem that we are experiencing due to the fact that IE 7 doesn’t support pseudo-format :before and :after. Instead of adding pipes with background images or something to the links in the action bar, we just space the links a bit more, and centre them. We also need to fix the fact that IE doesn’t understand how to correctly float items that are not situated over the container in the source code. This can be done using an absolute positioning, and fixing the margin-left.
1 |
p#action-bar { |
2 |
margin-left: 50px; |
3 |
position: absolute; |
4 |
text-align: center; |
5 |
top: 10px; |
6 |
}
|
7 |
|
8 |
p#action-bar a { |
9 |
margin-right: 5px; |
10 |
}
|
After this, we have the issue with the position of the page wrapper. Nothing too complicated to solve here, just use the box model to your advantage. We also use this selector to remove the over-spacing on the bottom of the content div.
1 |
div#content { |
2 |
padding-bottom: 0px; |
3 |
padding-top: 75px; |
4 |
}
|
5 |
|
6 |
ul#tabs { |
7 |
top: 10px; |
8 |
}
|
IE doesn’t seem to display our slide title correctly, because we have set a relative positioning to it. Just change this to absolute, and reset the top and left properties.
1 |
div#slideshow-commands h4 { |
2 |
left: 0px; |
3 |
position: absolute; |
4 |
top: 4px; |
5 |
}
|
Finally, it happens that IE doubles the padding between the entry title and its content in the blog module. We can fix this by setting half the value to it.
1 |
div.blog-entry blockquote { |
2 |
padding-top: 5px; |
3 |
}
|
Okay, you can now check our design in IE 7 and see that it works just fine too!
Step Six – The JavaScript
This will not be very complicated. We will use jQuery, the jQuery Cycle Plugin, and Cufón. I’ll explain why and where you can download them as we go.
I’m using JavaScript here following the philosophy of progressive enhancement. Obviously, the slideshow won’t work right now if we don’t have JavaScript enabled, but it could easily if we just added some PHP to the page and changed the next and previous links. However, this is not the subject of the tutorial so I won’t cover it. Just keep in mind that it would only take 5 lines of PHP code to make it work. So that’s for the slideshow being progressively enhanced. We are also smoothing out the heading fonts with a JavaScript code. This enables us to use any font we wish even if the reader doesn’t have it installed on his computer. If the reader does not have JavaScript enabled, the only thing that will happen is that he’ll see a fallback font.
jQuery
We are not going to use the entire power of jQuery in this tutorial. However, it does make things easier for us, so we are going to include it to our project even though it is 19 extra kilobytes.
You can download the minified and YUI compressed version of jQuery over at their official web site (http://jquery.com/) simply by checking the “Production" box and clicking the big “Download" button. Call this file jquery.js and place it in our JS folder.
To use the power of jQuery in our template, we’ll obviously need to call it. You should place the code in your head section.
1 |
<script type="text/javascript" src="js/jquery.js"></script> |
That’s it; jQuery now loads with the page and allows us to use all of its properties and methods!
Cufón
I was talking about a font-smoothing JavaScript code before, but that’s not actually it. Cufón lets us use whichever font we want in our design without the reader having it necessarily installed.
I’m not going to cover the basics of using Cufón since Jeffrey Way already does an outstanding job at this over here: https://code.tutsplus.com
Just download Cufón from this site: http://cufon.shoqolate.com/generate/ , and use the online font converter to convert the Myriad Pro font to a JS file. If you are not sure how to do so, check out Jeff’s tutorial!
Save the Cufón file in the JS folder and call it cufon.js, and the font file myriadpro.font.js.
Once those are in the right directory, we need to call them from our index.html file. Add script tags in the head section of our markup document, and use the src attribute in order to call the files. Don’t forget that the script tag is not auto-closing. You cannot use the syntax <script />. Doing so will result in a failed validation. The syntax you should use is <script></script> even though the tag is empty.
1 |
<script type="text/javascript" src="js/cufon.js"></script> |
2 |
<script type="text/javascript" src="js/myriadpro.font.js"></script> |
If you reload the page, you’ll see that... nothing actually happened. This is because we need to call the Cufón text replacement and specify which tags that should be parsed.
Open a new script tag, but instead of calling an external JS file, we will just write our code directly in our HTML file. We can do this because we are using one single line of code. Should your code be longer however, you should place it in an external file. The method to trigger the replacement is Cufon.replace() and it takes the tag that should be replaced as argument. Because we’ve already called jQuery, we can also use its CSS Selector engine to catch the right tags.
The code you could place in your HTML would look like this:
1 |
<script type="text/javascript"> |
2 |
Cufon.replace('h1, h2, h3, h5'); |
3 |
</script>
|
We are simply targeting the heading tags, and Cufón is making the magic happen. Reload the page and you can now see how Cufón smoothly replaced all our h tags with images built on the fly!
What happens if the reader doesn’t have JavaScript enabled? Well the font used is the one specified in out CSS! If the reader owns Myriad Pro, it is going to be used, even though it won’t be smoothed, and if not, one of our fallback fonts is used. It is the beauty of progressive enhancement.
The Slideshow
Our final step will be about making the slideshow alive. In order to do so, we will use an incredibly useful jQuery plugin called the jQuery Cycle Plugin. You can fetch it over here: http://malsup.com/jquery/cycle/lite/ . We will not use any complicated transitions, so the Lite version will work just fine. The great thing about it is that it is only 3kb!
Make sure you are downloading the YUI compressed version of the plugin, then place it in our JS folder and call it cycle.js. We then obviously need to call it from our HTML. Place the call to the Cycle plugin under the call to jQuery in order to be sure the plugin will be appended to the library!
1 |
<script type="text/javascript" src="js/cycle.js"></script> |
We then need to fire the effect using some JavaScript code. This is where we can specify some options to such as Previous and Next commands, delay etc. We will put this code in a new file called slideshow.js in the JS folder obviously, that we’ll then call from our HTML.
Before starting coding, we need to decide what we want our slideshow to do. The default behaviour is to take every element from a specified container, and then make them slide, hiding the others. This is good since we put all our slideshow images in a container with an id of “Slides". How do we want it to behave? Well, each 5 second, it should change slide, but it should also change slide if we click on the Previous or Next button. We also want the slideshow to pause if we hover our mouse over it. This is good because it gives people time to click if they are interested in the current slide.
Luckily, all this is extremely easy to do using the Cycle plugin. Once the DOM is ready, make jQuery fetch the #slides container, and start the slideshow using the cycle() method. Then using an anonymous object that we pass in as an argument, we can set the behaviour to the one we want.
This is what your code should look like:
1 |
$(document).ready(function() |
2 |
{ |
3 |
$('#slides').cycle({ |
4 |
prev : '#previous-slide', |
5 |
next : '#next-slide', |
6 |
timeout : 5000, |
7 |
pause : 1 |
8 |
}); |
9 |
}); |
What do those properties stand for? Well prev and next are obviously the ID of our Previous and Next commands, delay is the time between each slide in milliseconds, and if pause is set to 1, then the slide will pause on hover.
If we reload the page, we can see the image sliding nicely, and the previous and next commands working just fine! However, the title is inexorably the same. We can solve this little problem by calling a function before each sliding. The function will just get the next slide’s alt attribute and href attribute to be able to replace the h4 and the link correctly. This is what the function looks like:
1 |
function changeTitle() |
2 |
{ |
3 |
var title = $(this).find('img').attr('alt'); |
4 |
var href = $(this).attr('href'); |
5 |
|
6 |
$('#slide-title').text(title).attr('href', href); |
7 |
} |
However, this won’t work unless we specify that this function should be called before each slide change.
To do so, we simply need to specify the property “before" within our anonymous configuration object. This property should be set to the name of the function. You shouldn’t use quotes around the function’s name.
This is what the full working code looks like:
1 |
$(document).ready(function() |
2 |
{ |
3 |
$('#slides').cycle({ |
4 |
prev : '#previous-slide', |
5 |
next : '#next-slide', |
6 |
timeout : 5000, |
7 |
pause : 1, |
8 |
before : changeTitle |
9 |
}); |
10 |
}); |
11 |
|
12 |
function changeTitle() |
13 |
{ |
14 |
var title = $(this).find('img').attr('alt'); |
15 |
var href = $(this).attr('href'); |
16 |
|
17 |
$('#slide-title').text(title).attr('href', href); |
18 |
} |
Great, if we now reload the page we’ll see our slideshow work just as we wanted it to, and this only with a few lines of code! That’s the power of jQuery and its plugins.
Step Seven – Final Thoughts
We’ve now coded our entire website layout using xHTML 1.0, CSS 2.1 and JavaScript based on the template we designed in Part I. You can check every single file from the project and see that they are 100% valid! This is important to remember since it can greatly improve accessibility and the overall quality of your coding.
I sincerely hope you’ve enjoyed this series of tutorial, that you’ve learn some new techniques, and that you’ll now be able to make outstanding web templates yourself! I’ll be glad to see what you’ve managed to do in the comments.
- Follow us on Twitter, or subscribe to the NETTUTS RSS Feed for more daily web development tuts and articles.