Line25

How to Code a Stylish Portfolio Design in HTML/CSS

Read the full post

Over on my Blog.SpoonGraphics design blog this week, I posted a Photoshop design tutorial that takes you through the process of building a stylish portfolio design concept. Follow this second part of the tutorial here on Line25, where we’ll code up the design into a fully working HTML and CSS website. Stick around for part three, when we’ll go a step further and convert the static website into a WordPress build.

The design concept

View the Photoshop tutorial

If you missed the post on Blog.SpoonGraphics, head over to find out how this design was put together in Photoshop. When you’re ready, continue on to start part two: The HTML and CSS.

View part one: Creating the PSD concept

Exporting the image graphics

Before coding up the website, we need to export a series of image graphics from the Photoshop concept. Start by making a selection of the background texture and saving it as a PNG file. This will be used to repeat across the body of the web page.

Another image that needs to be exported is the logo. This image will overlap the header area, so we need to make it a PNG-24 file to make use of Alpha Transparency.

Toggle off the text and button layers from the header and export a selection of the grey background. This image will be used as a background image in the header’s CSS.

A selection across the content area right up to the 960px guides will repeat so the content area can be as long as required.

Once all the interface graphics have been exported it’s time to move on to setting up the actual web page documents.

The HTML structure

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Chris Spooner Design Portfolio</title>

<link href="style.css" rel="stylesheet" type="text/css" media="screen" />

</head>

<body>
	<div id="container">

	
	</div>

</body>

The HTML page begins with a typical document structure comprising of the Doctype, head and body. A link to the CSS stylesheet is added and the document content starts with a container div to enclose all the following elements.

<p id="logo"><a href="#"><img src="images/logo.png" alt="Chris Spooner logo" /></a></p>

<ul id="nav">
	<li><a href="index.html">Home</a></li>
	<li><a href="about.html">About</a></li>
	<li><a href="portfolio.html">Portfolio</a></li>
	<li><a href="contact.html">Contact</a></li>
</ul>

<div id="header">
	<h1>Hello, I'm Chris Spooner.</h1>
	<h2>I craft websites that are beautiful on both the inside and out.</h2>
	
	<p class="btn"><a href="portfolio.html">View my portfolio</a></p>
</div>

Despite the navigation coming first in the concept, we’ll add the logo first in the HTML document to keep everything structured. The logo is added as a <p> element, the navigation items as an unordered list and the intro headings as <H1> and <H2> elements.

<div id="content">
	<h3>About Chris Spooner</h3>
	
	<p>I earn a living by creating custom brands and logo designs from scratch, as well as designing and building high quality websites and blogs, but I also enjoy producing the odd t-shirt graphic, illustration or character design. I pride myself in having the nerdy skills to build top notch creations online, as well as being knowledgeable in the print side of design.</p>
	
	<h3>My latest work</h3>
	
	<p>I’m forever creating design work for both myself as personal projects and as a hired gun for clients from around the world. Here’s a few of my most recent works.</p>
	
	<div class="portfolio-item">
		<a href="#"><img src="images/portfolio-1.jpg" alt="View more info" /></a>
		<p class="btn"><a href="#">See more</a></p>
	</div>
	
	<div class="portfolio-item">
		<a href="#"><img src="images/portfolio-2.jpg" alt="View more info" /></a>
		<p class="btn"><a href="#">See more</a></p>
	</div>
	
	<div class="portfolio-item">
		<a href="#"><img src="images/portfolio-3.jpg" alt="View more info" /></a>
		<p class="btn"><a href="#">See more</a></p>
	</div>
	
	<div class="portfolio-item">
		<a href="#"><img src="images/portfolio-4.jpg" alt="View more info" /></a>
		<p class="btn"><a href="#">See more</a></p>
	</div>
	
</div>

<div id="footer">
	<p id="copyright">&copy; Chris Spooner / SpoonGraphics (Please don’t steal my work)</p>
	<p id="back-top"><a href="#">Going up?</a></p>
</div>

The ordering of the headings continues as the next level is a <H3>. The main body copy is then added within the content div, followed by a series of divs containing portfolio project thumbnails. In the final WordPress theme each of these items will be created as an individual ‘post’. The page is then finished off with a footer area which contains a copyright notice and back to top link.

Full annotated HTML

Here’s an overview of the full HTML page, complete with handy annotations and notes:

View the annotated HTML

The CSS Styling

body, div, h1, h2, h3, h4, h5, h6, p, ul, ol, li, dl, dt, dd, img, form, fieldset, input, textarea, blockquote {
	margin: 0; padding: 0; border: 0;
}

body {
	background: #f2f0eb url(images/bg.png);
	font: 16px Helvetica, Arial, Sans-Serif; color: #636363; line-height: 24px;
}

#container {
	width: 960px; margin: 0 auto;
}

#logo {
	margin: 10px auto 0 auto; position: relative; width: 183px;
}

The CSS file begins with a simple reset to remove the browser defaults, then we can start adding global styling to the body. First the background texture image is added followed by the general font styling for the page. The container div is given its 960px width and margin: 0 auto; used to centre it up on the screen. Our logo can then be positioned centrally with the same margin: 0 auto; declaration.

ul#nav {
	width: 940px; list-style: none; overflow: hidden; margin: -134px auto 25px auto;
}
	ul#nav li {
		width: 126px; height: 33px; float: left; padding: 13px 0 0 0;
		background: url(images/nav-bg.png);
		font-weight: bold; text-align: center; text-transform: uppercase;
	}
		ul#nav li:nth-child(1) {
			margin: 0 60px 0 0;
		}
		ul#nav li:nth-child(2) {
			margin: 0 316px 0 0;
		}
		ul#nav li:nth-child(3) {
			margin: 0 60px 0 0;
		}
		ul#nav li:nth-child(4) {
			margin: 0;
		}

		ul#nav li a {
			color: #616369; text-decoration: none;
		}
			ul#nav li a:hover {
				color: #a12121;
			}

The navigation menu needs a range of properties to convert the basic list into a layout that resembles the concept. The whole <ul> is first moved upwards to overlap the logo using negative margin, then each <li> is given specific dimensions, a background image and font styling to match the PSD. In order to match the layout of the concept, the CSS3 :nth-child(); selector is used so different margins can be added to each of the four list items.
Some basic styling to the anchors finishes off the navigation menu.

#header {
	height: 244px; padding: 52px 0 0 57px;
	background: url(images/home-header.jpg);
}

	#header h1 {
		font: 38px Georgia, Serif; color: #f2f0eb; letter-spacing: 2px; margin: 0 0 20px 0;
		text-shadow: 0px 3px 3px #494949;
	}
	#header h2 {
		width: 510px; font: 30px Georgia, Serif; color: #f2f0eb; letter-spacing: 2px; margin: 0 0 20px 0;
		text-shadow: 0px 3px 3px #494949;
	}
	#header p.btn a {
		display: block; width: 225px; height: 50px; overflow: hidden;
		background: url(images/home-header-btn.jpg); text-indent: -9999px;
	}

The header area makes use of the grey background image, so an exact height is added to match the dimensions of this image. Padding then helps move the text elements away from the edge and into position to match the concept. Each of the headers is then given a range of CSS font styling to match the text as Georgia with increased tracking. The drop shadow effect from Photoshop can be replicated with text-shadow while a width on the H2 will force the long sentence to wrap.
The paragraph element with the btn class can then be converted into a button style graphic using simple CSS image replacement to show the graphic in place of the default HTML wording.

#content {
	background: url(images/content-bg.png) repeat-y;
	padding: 57px 69px 50px 69px; overflow: hidden;
}
	#content h2 {
		font: 30px Georgia, Serif; letter-spacing: 2px; margin: 0 0 20px 0;
	}

	#content h3 {
		font: 26px Georgia, Serif; letter-spacing: 2px; margin: 0 0 20px 0;
	}
	
	#content p {
		margin: 0 0 30px 0;
	}
	
	#content a {
		color: #a12121; text-decoration: none;
	}
		#content a:hover {
			color: #671111;
		}
	
#content .portfolio-item {
	width: 182px; padding: 4px; background: #eee; text-align: center;
	float: left; margin: 0 7px 14px 7px;
}
	#content .portfolio-item p.btn {
		margin: 0;
	}
	#content .portfolio-item p.btn a {
		display: block; width: 183px; height: 29px; padding: 7px 0 0 0;
		background: url(images/see-more-bg.png);
		font-weight: bold; text-align: center; text-transform: uppercase;
		text-decoration: none;
	}

Next up is the main content area. This is first given the repeating background image to fill the whole area with white. Padding then pushes the content away from the edges to match the original design. overflow: hidden; is added to the content div to make sure all floats contained within the div are cleared so they don’t break the layout.
Simple styling is added to the content that makes up the body copy, including headers and paragraph elements. Then the portfolio thumbnails are styled up. These portfolio items are given the light grey background and floated side by side, then the anchor links inside these divs are styled as buttons using a PNG background image.

#footer {
	background: url(images/footer-bg.png) no-repeat; padding: 40px 0 0 0;
	overflow: hidden; margin: 0 0 30px 0;
}
	#footer p#copyright {
		font-size: 12px; float: left; margin: 0 0 0 30px; color: #b8b6b2;
	}
	#footer p#back-top {
		font-size: 12px; float: right; margin: 0 30px 0 0;
	}
		#footer a {
		color: #a12121; text-decoration: none;
	}
		#footer a:hover {
			color: #671111;
		}

The bottom of the page is then finished off with the footer div. The bottom edge of the content area is added as a background image to the footer, then padding is used to push the footer content down below the image. no-repeat is added to the background image to make sure the graphic only appears once. The copyright and back to top links are given basic font styling and floated to the left and right to position them at either sides of the page.

Browser testing

A quick test in the most common browsers shows no problems with Firefox, Safari and Chrome, but as always Internet Explorer has problems. The CSS3 :nth-child(); selectors used in the navigation menu aren’t supported by IE, but instead we can use jQuery to help with a fix.

$(document).ready(function() {
	$("ul#nav li:nth-child(1)").css("margin-right", "60px");
	$("ul#nav li:nth-child(2)").css("margin-right", "316px");
	$("ul#nav li:nth-child(3)").css("margin-right", "60px");
	$("ul#nav li:nth-child(4)").css("margin-right", "0px");
});

To fix this, we just need to use jQuery to add the relevant margins. When the same CSS is applied with jQuery Internet Explorer has no problem implementing it.

Finishing up the inner pages

Now the homepage is complete, we can continue building the inner pages of the site. The overall structure of the pages is roughly the same, with just a shortened header and different content on each.

<div id="header" class="page">
	<h1>About Chris Spooner</h1>
</div>

To style up a different header, we can simply add a class to the header of the inner pages, then give this particular header a smaller size and the plain background image.

We’ve already created the code for the portfolio items, so this can simply be duplicated for each new design project. All that needs changing is the thumbnail image.

On the contact page the form can be styled up using tips from my recent HTML5/CSS3 contact form tutorial. Just adjust the dimensions of the fields and the colours and the form design is all set.

#content #social {
	width: 371px; float: left; 
}		
	#content #social ul {
		list-style: none;
	}
		#content #social ul li {
			float: left; margin: 0 20px 20px 0;
		}
			#content #social ul li a {
				display: block; width: 100px; padding: 5px 0 5px 45px;
				background: url(images/social-icons.png) no-repeat;
			}
				#content #social ul li a.twitter { background-position: 0 -3px; }
				#content #social ul li a.youtube { background-position: -172px -1px; }
				#content #social ul li a.facebook { background-position: -172px -136px; }
				#content #social ul li a.flickr { background-position: 0 -71px; }
				#content #social ul li a.digg { background-position: -172px -71px; }
				#content #social ul li a.lastfm { background-position: 0 -140px; }

The contact form and social links are enclosed in their own divs so they can be floated side by side. Then the social links are laid out with another unordered list. A sprite image is added as the background as this contains every single icon. All you need to do is adjust the background-position so the correct icon appears next to each of the links.

The final portfolio website demo

View the portfolio website demo

Now all the pages are in place the portfolio website design concept is complete. Stay tuned for the next tutorial where we’ll convert the static HTML and CSS design into a fully working WordPress theme.

View the portfolio website demo

Free web shadows pack for every subscriber

Join the mailing list to have new content delivered straight to your email inbox. Every subscriber gets a free pack of realistic web shadows.

Written by Chris Spooner

Chris Spooner is a designer who loves experimenting with new web design techniques collating creative website designs. Check out Chris' design tutorials and articles at Blog.SpoonGraphics or follow his daily findings on Twitter.

57 Comments

  1. idris says:

    this is really awesome
    thank you for sharing such a useful tutorial

  2. Garth says:

    Hey man, this isn't a criticism but I'm just wondering why you wrap your links in p tags? Seems unnecessary to me; couldn't the "btn" class just be on the <a>?

    • I just work on the practice that every inline element should be enclosed within a block element.
      It's just habit really.

      • Garth says:

        Oh yup fair enough, I guess I usually just display:block on my buttons. Each to their own. It must a be a little bit annoying having everyone pick your code apart, as has happened below my comment…

  3. Rob Cubbon says:

    Really great tutorial, Chris. I didn't know about the CSS3 :nth-child(); function – I would have applied a different id or class to the li elements but your way keeps the HTML cleaner.

  4. Neil Sweeney says:

    Very good post, but just to add a thought. With portfolio items in theory the portfolio could be better places as a list.

    Two reasons:
    1. You call each div a "portfolio-item", which suggests the are itemised
    2. You are listing a group of similar things.

    This suggests that semantically you are better off putting them in a ul. Also, it means you only need reference a class once for the whole ul rather than for each div (which also have no semantic meaning).

    Not to say your method is wrong at all, just I'm anal about front-end code and feel they are better off listed.

    Thanks.

    • I actually had this conversation with myself when building it. I came to the conclusion that using Divs would match how posts are usually outputted with WordPress (for when I convert it into a theme later).

      Thinking about it more in depth now, there probably wouldn't be any reason why WordPress posts couldn't be outputted in <li>'s.

      Will have to tweak that before I build the theme.

  5. Hi Chris,

    nice tut, like it! Thanks for publishing this stuff.

    One thing's on my mind though .. why do you use a HTML5 doctype but write the rest of the source-code as HTML4.01? (e.g. <div id="footer'> instead of <footer>).

    Just wondering? Cheers & Ciao ..

    • There's no reason not to use it really. Pros = It's shorter and cleaner, plus you could use elements like <footer> if you go the extra step to fix up older browsers.
      Cons = None. All the elements and tags have the same syntax and work the same. (Even <div id="footer">)

      Also, I can't remember exactly, but I'm sure there's something in WordPress that doesn't validate unless you use the HTML5 doctype. I'll have to rack my brains to remember what it was.

      • Thanks for your reply!

        Maybe an idea for me too, cause thinking about it, you're quite right that there is no reason NOT to use the HTML5-doctype ..(BTW: Checked it on IE7 & 8, and yep, works just fine!)

        So, thanks for the advice, Cheers & Ciao ..!

  6. Nice tutorial. Another good example of using pseudo elements of CSS and an awesome contact form.

  7. Ruben says:

    On the demo page, look at your closing html tags, you messed something up there :P

    </html>>
    </html>

  8. Blake says:

    Chris,
    I'm a newcomer to the world of online graphics arts and website design, but I've already noticed your name around the web in many ways and places (all good though). I think this is an awesome example of your knowledge, experience, and generosity in this community. Thanks for all the great work and inspirational contributions!

  9. Webdesdev says:

    I am waiting for the next step, converting to wordpress.

  10. Another great tutorial!

    Thanks especially for the annotated version of your code – uber useful :)

  11. Rob Russo says:

    Nice cross promotion between your sites. Love it! And your tutorials are great. Thanks for all the inspiration.

  12. Great tutorial but why didn't you just give the li elements an id? I like using nth-child pseudo selectors but it seems a little un-necessary here, especially as you need jQuery for older browsers

  13. Thanks for another great tutorial! I like the logo at the top of the layout.

  14. calixweb says:

    thank you for this tuts !!

  15. designbyarm says:

    thanks you for this nice tutorial

  16. Thanks!

    Waiting for the next tutorial about wordpress ;D!

  17. Mark says:

    Looks like a great tut! Going to try it right now! :)

  18. Zombiriro says:

    Can I download The Files of this tutorial?

    maybe zipped file :)

  19. riccardo says:

    Nice tut and nice layout design! …but why using a mix of older and newer tecniques? you use :nth-child but dont use a css3 gradient.. and the same for html tags… i know there's a lack of support for browsers like our "best friend" IE (but what about html5-shiv and modernizr?).

    I love your style and your pixel precision, but what about the possibility of adapt the layout to different screen? what if someone looks at my portfolio on a smartphone?

    I hope to give you some interesting thoughts with this critics. Thank you for sharing and inspire us.

    ciao!

  20. Bea Litao says:

    This is an awesome tutorial!

    Thank you for taking the time to screenshot how the website would actually look like from designing it in Photoshop to coding it in HTML/CSS!

  21. Avangelist says:

    You're going to need to explain the wrapping the logo in a p tag, what possible benefit does that provide?

    In response to some of the comments on doctype decleration. If you haven't read the W3C schema – do so. I would also recommend reading Adactio's views on it.

  22. bob marteal says:

    Thanks for the walk through. Step by step is such a great way to show the process. Every HTML tut ever should have a annotated Code view.

    Is it a conscious decision not to use other HTML5 semantic tags? Do you just find the divs have some benefit for now or the benefits don't outweigh changing your style? Thanks.

  23. Webdesdev says:

    Guys gys leave him alone, he wrote a nice tuts and we all know these coding thing (html-5, css3). If some newbie is asking these ? it's fine to ans but you gys known everything so just leave this to your styles and wait for the next step tut :)

  24. Cameron says:

    Nice Tutorial Chris. Just completed my first site using mainly html5 and css3 and generally love it – especially the speed factor.

    The client was intense about load speed. No way I could get a good looking 7KB homepage back in the day.

    Thanks again

  25. Ahmed Abbouh says:

    great tutorial but why you used only the HTML5 doctype ?

  26. Ahmed Bolica says:

    Chris You Rock :D Thanks Dear :))

  27. Fernando Avalos says:

    I love your templates, i'm not an actual web designer but i'm trying to learn any tips books or things i should do? i've been getting a lot from your tuts

  28. Ashish says:

    hi, thanks for such a gr8 tutorial!

    But, one thing I never understand that why you put the LOGO IMAGE inside a <P> tag.
    I think there was no need of this and ofcourse this is not the right way to put an image anywhere…

    May be I am wrong :)

  29. Beben Koben says:

    cleary explanation…
    great portfolio, thanks for creativity

  30. Patrick says:

    Nice tute set Chris, learned a lot from this and some others. Looking forward to WP portion.

  31. thanks for your tutorial its so easy to make it great work

  32. nice tut Chris. always doing beautiful :)

  33. The tutorial has been a great inspiration for me . I think it is one of the best ones i have seen . Keep it coming.

  34. Vivek Parmar says:

    Great tut, nicely explained.
    Know how to create portfolio layout using photoshop but did not know how to embeed html and css in it. thanks for sharing

  35. Manuel Cai says:

    This is very helpful :)
    Thank you so much.

  36. I think a modern portfolio today need to show of that the designer/dev creates an experience for the visitor regardless of the platform they use. That means that the website has to include responsive design choices with scaling solutions down to the mobile screen sizes.

  37. Carolyn Lauttenbach says:

    I love that you took this extra step beyond the photoshop tutorial. Can't wait for Part 3 :)

  38. Nancy Paul says:

    Great information but is it friendly for SEO point of view.

  39. Fangirl says:

    I LOVE YOU for making this tutorial! <3 by: One of Your Biggest fan!

  40. Asim Craft says:

    Great Tutorial! Very informative and clear. If your interested, Check out my portfolio http://www.digitaldesignzmedia.com/port.html. Let me know what you think.

  41. Amanda says:

    Great tutorial, it's helping me to learn the code for my designs. Looking forward to trying out the wordpress part.

  42. Rajesh says:

    hi Chris Spoone it is really nice tutorials work i learnt much from this tutorial so " Thinks " Chris Spoone

  43. söve says:

    Very nice tutorials.Thanks for sharing.

  44. Find Ferry says:

    Nice tutorial :-) Thanks from me too :-)

  45. Colin says:

    Hey Chris,

    Really nice tutorial. Just wondering why you decided to put your portfolio thumbnails inside <img> tags instead of adding them to the background of the anchor tags via css?

    Thanks,
    Colin

  46. Sean says:

    And again, helped me a lot.

  47. thanks for your tutorial its so easy to make it .and this is great work

Comments are now closed