Photoshop to HTML Step-By-Step, Layout 1: "MiniMal"

In this walkthrough, Matt shows how to take a web template design in Photoshop and create a finished HTML and CSS template. Full code download included.

Photoshop to HTML Step-By-Step, Layout #1: 'MiniMal'
View Layout » Download Code

A common question we get asked here at Elated is: "How do you take a design in Photoshop and turn it into a finished HTML and CSS website?"

We've given this some thought, and we reckon the best way to answer this question is by example. So this series of tutorials will look at how we took the Photoshop designs for our free PageKits (website templates) and turned them into the finished HTML/CSS templates.

Each tutorial will cover a specific template. In this first tutorial, I'll walk you through our most recent template at the time of writing: MiniMal.

The overview

Like most of our PageKits, the MiniMal design consists of 2 page templates: the homepage template (to be used for the site homepage) and a generic inner page template (to be copied and used for every other page of the website).

There are 3 main steps to creating the MiniMal HTML/CSS layout from the Photoshop PSD file:

  1. Slice the PSD. We need to open the PSD file in Photoshop, identify areas of the PSD (such as photos and logos) that will need to be rendered as images in the HTML layout, then export those areas as GIF, JPEG or PNG images, ready to use in the layout.
  2. Build the HTML. The next step is to create the HTML markup for the 2 pages in the layout. The markup will contain little or no styling. It will just comprise the logical structure of the page, as well as the page content.
  3. Create the CSS. Finally, we need to build the CSS style sheet for the layout. This will apply CSS styles to the markup created in Step 2, in order to lay out the elements in the page, specify colours and images, and so on. The final result should then match the look of the original PSD.

Ready to build the layout? Let's get started!

Step 1. Slicing the PSD

The first step is to slice the PSD. This involves:

  1. Working out which elements in the PSD will need to be rendered as images in the final HTML layout
  2. Extracting those elements and saving them out as image files, ready to use in the HTML and CSS
MiniMal PSD screenshot
The MiniMal PSD. The design features 2 very similar layouts: homepage (left) and inner page (right).

For this PageKit there are 4 image elements to extract:

  1. The logo "bubble" (we'll do the "MiniMal / Food for thought" text as HTML for flexibility)
  2. The whale photo on the homepage
  3. The corresponding "Z" photo on the inner page
  4. A semitransparent background image for the "Page Title / And a little strapline" caption overlay on the inner page

First, create a minimal folder somewhere on your computer to store the layout's HTML, CSS and image files. Create another folder inside the minimal folder, called images. You'll put all your exported images in this folder.

Now let's work through the steps to extract each of the images in turn.

The logo bubble

First we'll extract the logo bubble as follows:

  1. Turn off the MiniMal / Food for thought text layers so that they won't get in the way.
  2. Use the Rectangular Marquee tool to draw a rectangular selection around the bubble.
  3. Choose Edit > Copy Merged to copy all layers (background and bubble).
  4. Choose File > New, and accept the default image dimensions (they default to the size of the copied selection).
  5. Choose Edit > Paste to paste the bubble into the new image.
  6. Choose Image > Trim and select Top Left Pixel Color to trim the whitespace around the bubble (see below).
  7. Choose File > Save for Web & Devices and save the image as a 256-colour PNG image, logo.png, inside the images folder you created earlier.
Trimming the bubble
Using the Trim command to remove whitespace from around the bubble

The photos

Extracting the photos is similar to the bubble process described above. The only differences are:

  • No need to trim, since they're rectangles. Just Control/Command-click the Shape 5 layer thumbnail in the Layers panel to select the rectangular image, then Copy Merged, paste to a new document, and export using Save for Web.
  • Since these images are photos, export them as JPEGs instead of PNGs: whale.jpg and zed.jpg.

The overlay background image

In the PSD, the main image on the inner page design has a "Page Title / And a little strapline" caption sitting on a semitransparent overlay at the bottom of the image.

Many modern browsers support semitransparent backgrounds in CSS using the RGBa alpha transparency colour notation. For example, the following CSS gives a div a black semitransparent background with 80% opacity:


div { background: rgba( 0, 0, 0, 0.8 ); }

However, some common browsers — notably IE7/8 — don't support this CSS feature. So for better compatibility, we'll create the overlay using a repeating semitransparent PNG background image instead.

Here's how to do it:

  1. Turn off the Home group in the Layers panel by clicking its eye icon.
  2. Turn on the Page group by clicking its eye icon.
  3. Open the Page group in the Layers panel, then open up the Left copy group inside.
  4. Alt/Option-click the Shape 8 layer. This hides all layers except the semitransparent overlay.
  5. Make a square 10 x 10-pixel selection inside the overlay using the Rectangular Marquee tool (see below). You might find it helps to zoom in a bit first.
  6. Choose Image > Crop.
  7. Choose File > Save for Web & Devices. Export the image in PNG-24 format with the Transparency checkbox enabled. Call the file photo-overlay-bg.png.
  8. Revert back to the original PSD by choosing File > Revert.
Selecting a 10 x 10-pixel area of the overlay
Selecting a 10 x 10-pixel area of the overlay

We now have the following exported images:

The sliced images
The final sliced images

Step 2. Creating the HTML

Now that we've exported the images we need, it's time to create the markup for the template.

There are 2 HTML files to create:

index.html
The homepage template
page.html
The inner page template

Since these pages will be very similar, we'll build index.html first, then copy and tweak it to make page.html.

So first create a new text file called index.html, inside the minimal folder you created earlier. Open this file in a text editor.

The following sections describe each of the blocks of code that we'll add to the index.html file.

DOCTYPE and head element


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>MiniMal : Homepage</title>
<link rel="stylesheet" type="text/css" href="style.css" />

</head>

The first step is to create the DOCTYPE and head elements. We'll code the markup to XHTML 1.0 Strict, so this is the DOCTYPE we'll use. The head element contains a "Content-Type" meta element to set the page character set to Unicode (utf-8), as well as the page title and a link to the style sheet file that we're going to create later (style.css).

body element, outer container, and page header


<body>

<!-- Begin Outer Container -->

<div id="container">

  <!-- Begin Header -->
  <div id="header"> 
  
    <!-- Begin Title/Strapline -->
    <h1><a href="index.html"><b>Mini</b>Mal</a></h1>
    <h2>Food for thought</h2>
    <!-- End Title/Strapline -->

    <!-- Begin Nav -->
    <ul>
      <li><a href="page.html">About</a></li>
      <li><a href="page.html">Services</a></li>
      <li><a href="page.html">News</a></li>
      <li><a href="page.html">Contact</a></li>
    </ul>
    <!-- End Nav -->
    
  </div>
  <!-- End Header -->

Next comes the body element, and the start of the page content proper. This contains:

  • An outer container div with an ID of container to hold all the page content.
  • A header div to contain the site title/strapline and navigation menu.
  • An h1 heading for the page title, and an h2 heading for the strapline. The page title links to the homepage, and the "Mini" part of the title is bolded using <b> ... </b> tags.
  • A ul list for the navigation. Each li in the list contains the menu item text, linked to the inner page. (In a site based on this template, these would of course link to the individual site pages.)

Subheader


	<!-- Begin Subheader -->
	
	<div id="subheader">
	  <img src="images/whale.jpg" alt="Whale" />
	  <div>
	    <p>Lorem ipsum dolor sit amet, con sectetuer adipiscing elit, sed diam nonnumy nibh eeuismod tempor inci dunt ut labore et dolore magna ali quam erat volupat.</p>
	  </div>
	</div>

	<!-- End Subheader -->

The subheader area comprises the whale photo on the left and the large italic Lorem Ipsum text on the right.

We've created a subheader div to contain the whole subheader. Inside this div, we've inserted the whale image as an img element, and the Lorem Ipsum text as a paragraph within a div. Having the text within its own div will allow us to easily identify and style the text in the CSS.

Content area


  <!-- Begin Content -->

  <div id="content">
    <div class="main">
      <p class="intro">Vel illum dolore eu feugiat nulla facilise at vero eos et accusam et ius to odio dignissim qui blandit prae sent luptatum zzril delenit aigue dous dolore et molestias exceptur sint occaecat cupidiata non simil pro vident tempor sunt in clulpa qui officia deserunt mollit anium ib est abor um et dolor fuga. Et harumd dereud facilis est er expedit distinct. Nam liber tempor cum soluta nobis eligend option congue nihil impediet doming id quod mazim placeat facer possim omnis voluptas assumenda est, omnis repellend.</p>
    </div>
    <div class="sidebar">
      <h2>Recent Tweets</h2>
      <p>Lorem ipsum dolor sit amet, con sectetuer adipiscing elit, sed diam nonnumy nibh eeuismod tempor inci dunt ut labore et dolore magna ali quam erat volupat. Ut wisi enim</p>
      <p>Nibh eeuismod tempor inci dunt ut labore et dolore magna ali quam erat volupat. Ut wisi enim</p>
      <p>Lorem ipsum dolor sit amet, con sectetuer adipiscing elit, sed diam nonnumy nibh eeuismod tempor inci dunt ut labore</p>
    </div>
  </div>
	
  <!-- End Content -->

The content area div (with an ID of content) consists of the main content column (main) and the sidebar column (sidebar). The paragraph of text in the main content column is given an intro class so that it can be styled separately from regular paragraphs (i.e. bolded).

Page footer and closing tags


  <!-- Begin Footer -->
  <div id="footer">
    <p>Elated PageKits &copy; 1996-2010 <a href="http://www.elated.com/">Elated</a> & <a href="http://www.pagekits.com/">PageKits.com</a></p>
  </div>
  <!-- End Footer  -->

</div>
<!-- End Outer Container -->

</body>
</html>

Finally we create the page footer as a div with an ID of footer, and close the outer container div, along with the body and html elements.

The inner page

The inner page design of the PageKit is very similar to the homepage, so the easiest thing to do is copy the homepage file (index.html) to a new file (page.html), and tweak page.html as needed.

The inner page's subheader has a different main photo, and also has the page title and strapline overlaid on the photo. We'll create the page title as an h1 heading, and the strapline as an h2.

So edit page.html and change the line:


 	  <img src="images/whale.jpg" alt="Whale" />

to:


 	  <h1>Page Title</h1>
 	  <h2>And a little strapline</h2>
 	  <img src="images/zed.jpg" alt="Zed" />

The only other change is to add that second paragraph of text to the main content area (shown in bold below):


    <div class="main">
      <p class="intro">Vel illum dolore eu feugiat nulla facilise at vero eos et accusam et ius to odio dignissim qui blandit prae sent luptatum zzril delenit aigue dous dolore et molestias exceptur sint occaecat cupidiata non simil pro vident tempor sunt in clulpa qui officia deserunt mollit anium ib est abor um et dolor fuga. Et harumd dereud facilis est er expedit distinct. Nam liber tempor cum soluta nobis eligend option congue nihil impediet doming id quod mazim placeat facer possim omnis voluptas assumenda est, omnis repellend.</p>
      <p>Temporibud auteui quinusd et aur office debit aut tum rerum neccessit atib saepe eveniet ut er molestia non <a href="#">recusand</a>. Itaque earud rerum hic ten tury sapient delectus au aut prefer zim endis dolorib asperiore repellat. Hanc ego cum tene senteniam, quid est cur verear ne ad eam non possing accommodare nost ros quos tu paulo ante cum memorite tum eita ergat. Nos amice et nbevol, olestias access potest fier ad augend ascum consci ent to factor tum poen legum odio que civiuda. Et tamen in busdam neque nonor imper ned libliding gen epular reli quard cupiditati quas nul la priad om undat.</p>
    </div>

Step 3. Creating the CSS

The markup is done, but the layout looks pretty dull if viewed in a browser at this stage. In order to make the pages look like the PSD, we need to create the CSS to style the content.

To do this, create a style.css file in your minimal folder. The browser picks up this file due to the link in each page's head element, and styles the page using the style rules in the file.

Now we'll add the style rules to the style.css file. The following sections describe each of the rules in turn.

The reset CSS


/* Meyer's Reset */

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-weight: inherit;
  font-style: inherit;
  font-size: 100%;
  font-family: inherit;
  font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;
  vertical-align: baseline;

/* remember to define focus styles! */
:focus {
  outline: 0;
}

body {
  font-size: 0.8em;
  line-height: 1.2em;
  color: #000;
  background: #fff;
}

ol, ul {
  list-style: none;
}

/* tables still need 'cellspacing="0"' in the markup */

table {
  border-collapse: separate;
  border-spacing: 0;
}

caption, th, td {
  text-align: left;
  font-weight: normal;
}

blockquote:before, blockquote:after, q:before, q:after {
  content: "";
}

blockquote, q {
  quotes: "" "";
}

p {
  margin-top: 1em;
}

}

This CSS comes from Eric Meyer's reset stylesheet. The idea of a CSS reset is to override the quirky default settings of different browsers so that you're working from a common starting point across all browsers.

Headings and links


/* Headings */

h1, h2, h3 {
  font-family: "Georgia", "Times New Roman", serif;
  font-style: italic;
  font-weight: bold;
  margin: 1em 0;
}

h1 {
  font-size: 2.4em;
}

h2 {
  font-size: 1.7em;
}

h3 {
  font-size: 1.3em;
}


/* Links */

a:link, a:active
{
  color: #038ee7;
  text-decoration: none;
}

a:visited {
  color: #999;
  font-size: 1.0em;
  text-decoration: underline;
}

a:hover {
  color: #000;
  font-size: 1.0em;
  text-decoration: underline;
}

These rules style the headings and links in the page. All headings are given a common font (Georgia) and style (italic, bold, and a 1em top and bottom margin). The h1, h2 and h3 headings are then each given a specific font size.

The links are styled using the colour from the PSD (#038ee7). The underlines are turned off with text-decoration: none. Visited links are given a grey underlined style, and hovered links a black underlined style.

The page container


/* Container for page */

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

Now we move onto the CSS that creates the page layout. The first rule styles the outer #container div that is wrapped around the entire page content:

margin: 0 auto;
Centres the container — and therefore the page content — in the middle of the browser window.
padding: 0 10px;
Adds 10 pixels of padding on the left and right sides of the container, so the content doesn't go right to the edge of the browser window.
width: 960px;
Sets the width of the page content. 960 pixels is a good width, since it allows most people to view the site without needing to scroll horizontally.

The page header and logo


/* Header */

#header {
  width: 100%;
  height: 200px;
  position: relative;
  background: transparent url("images/logo.png") no-repeat 10px 60px;
  border-bottom: 1px solid #000;
}

This rule styles the #header div, which contains the logo/title, strapline, and navigation menu. It's given a width of 100% so it stretches across the whole container width, and a height of 200 pixels.

Screenshot of page header
The #header div contains the logo/title, strapline, and navigation menu.

We use position: relative on this div since we want to include absolutely-positioned elements inside the div. By setting position: relative on the div, we ensure that those absolutely-positioned elements are relative to the div, rather than to the entire page.

Finally, we add the logo.png bubble image to the header as a background image, positioned 10 pixels from the left of the div and 60 pixels from the top, and we give the header a thin black border along its bottom edge.

The page title


/* Title */

#header h1 {
  position: absolute;
  left: 88px;
  top: 130px;
  margin: 0;
  line-height: 100%;
}

The "MiniMal" title is created as an h1 heading. It's positioned within the header using absolute positioning, just below and to the right of the bubble. Its margin is set to zero to override any margins on regular h1 headings. Setting the line-height to 100% helps to ensure that the text is positioned consistently across different browsers.

The strapline


/* Strapline */

#header h2 {
  position: absolute;
  left: 89px;
  top: 158px;
  font-size: 0.95em;
  font-weight: bold;
  margin: 0;
}

#header h1, #header h2 {
  font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;
  font-style: normal;
}

The strapline, "Food for thought", is an h2 heading. As with the title, we position this using absolute positioning, and adjust the font size and weight as required. Again, margin: 0 overrides any margin settings on regular h2 headings.

We also set the desired font family and font style on both the h1 and h2 headings in the header, overriding the Georgia Italic style for general h1 and h2 headings that we set earlier in the style sheet.

Making the logo clickable


#header h1 a {
  color: #000;
  text-decoration: none;
  font-weight: normal;
  position: absolute;
  display: block;
  margin-left: -88px;
  margin-top: -100px;
  padding-left: 88px;
  padding-top: 100px;
}

The "MiniMal" text is wrapped in a link that links back to the homepage, but it would be great if this link could stretch to encompass the logo bubble too. This is what the above CSS does.

By setting the link to display: block and adding some padding to the link, it stretches out to the dimensions of the bubble. We then set corresponding negative margins to move the link up and to the left so that it actually covers the bubble.

The navigation menu


/* Navigation menu */

#header ul {
  position: absolute;
  left: 650px;
  top: 134px;
  width: 310px;
  border-top: 1px solid #000;
  padding: 12px 0;
}

#header ul li {
  display: inline;
  margin-right: 12px;
}

#header ul li a {
  color: #000;
  font-weight: bold;
  text-decoration: none;
}

#header ul li a:hover {
  text-decoration: underline;
}

The nav menu is an unordered list (ul) element, with each each list item (li) element containing a link.

We position the ul on the right hand side of the header, and give it a thin black top border. We add 12 pixels of top and bottom padding around the list to create space between the border and the links.

In order to make the list items go across the page rather than down, we set the li elements to display: inline. We give each item a right margin of 12 pixels to separate it from the one next to it.

The links themselves are given a bold, black, non-underlined style, with an underline appearing when they're hovered over.

Subheader with large text, wide photo and page title


/* Subheader with wide photo, large text and (on inner page) the page title */

#subheader {
  width: 100%;
  height: 296px;
  padding: 10px 0;
  margin: 0;
  position: relative;
}

#subheader img {
  width: 630px;
}

#subheader div {
  position: absolute;
  left: 650px;
  bottom: 10px;
  vertical-align: bottom;
  width: 310px;
}

#subheader div * {
  font-family: "Georgia", "Times New Roman", serif;
  font-size: 1.7em;
  line-height: 1.3em;
  font-weight: bold;
  font-style: italic;
}

#subheader h1, #subheader h2 {
  position: absolute;
  font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;
  font-style: normal;
  color: #fff;
  margin: 0;
}

#subheader h1 {
  bottom: 10px;
  width: 610px;
  height: 1.4em;
  padding: 30px 10px 10px 10px;
  background: transparent url("images/photo-overlay-bg.png") repeat 0 0;
  font-size: 2.7em;
}

#subheader h2 {
  bottom: 10px;
  background: transparent;
  font-size: 1.1em;
  padding: 0 10px 10px 10px;
}

The subheader area contains the wide photo on the left (with the overlaid page title/strapline on the inner page) and the large italicised text on the right.

Screenshot of subheader
The inner page #subheader div, showing the large photo with overlaid page title and strapline, along with the large text in italics.

The above rules style each of these elements in turn. Here's how they work:

  • The #subheader div is given a 100% width, a fixed height of 296 pixels, and some top and bottom padding to separate it from the black borders above and below. It's set to position: relative so that we can place absolutely-positioned elements inside it.
  • The wide photo image is given a width of 630 pixels.
  • The div within the subheader — that is, the large italic text — is positioned on the right side of the page. vertical-align: bottom ensures that the text is positioned at the bottom of the subheader.
  • The text itself is given a Georgia font, and a large, bold italic style.
  • The page title and strapline were created in the HTML using h1 and h2 headings respectively. In the CSS they're both set to position: absolute and given a Helvetica Neue font in white.
  • The page title (h1) is positioned at the bottom of the subheader. It's given a width and padding to make it take up a wide strip at the bottom of the photo, and its background is set to the semitransparent PNG image exported earlier to create the overlay effect. The background image is tiled so that it fills the whole h1 area.
  • The strapline (h2) is also positioned at the bottom of the subheader, just below the h1.

The main content and sidebar areas


/* Main content */

#content {
  width: 100%;
  overflow: hidden;
}

#content .main {
  float: left;
  width: 540px;
  padding: 15px 0 0 90px;
  border-top: 1px solid #000;

}

#content .sidebar {
  float: right;
  width: 310px;
  padding: 15px 0 0 0;
  margin: 0 0 0 20px;
  border-top: 1px solid #000;

}

#content .sidebar h2:first-child {
  margin-top: 0.75em;
}

/* Intro paragraphs */

p.intro {
  font-weight: bold;
}

The #content div holds the page content proper: the main content on the left, and the sidebar on the right.

Screenshot of main content area
The #content div contains the main content column on the left and the sidebar on the right.

We give the #content div a width of 100% to fill the container width. Also, since the div will contain floated elements, we use overflow: hidden to clear the floats so that the content after the div appears correctly below the div.

The .main div contains the main left-hand column of text, so it's floated left and given an appropriate width and padding. It's also given a thin black border along its top.

The .sidebar div contains the right-hand sidebar text. It's floated right, and given a fixed with, padding, margin and top border, much like the .main div.

So that the sidebar's h2 heading ("Recent Tweets") aligns nicely with the top of the main content column, it's given its own top margin of 0.75em, overriding the default of 1em.

The :first-child pseudo-class ensures that only the first h2 within the .sidebar div is given the new top margin.

Finally, we style the special .intro paragraph at the top of the main content column using bold text.

The page footer


/* Footer */

#footer {
  height: 60px;
  border-top: 1px solid #000;
  margin: 40px 0 0 0;
  padding: 10px 0 0 90px;
  font-weight: bold;
}

The final section of the page that we need to style is #footer, the page footer area. This is given a fixed height and a thin black top border. It's given a top margin of 40 pixels to separate it from the body content, and a top padding of 10 pixels to separate the border from the footer content. The 90-pixel left padding makes the footer content's left hand edge line up with the body content.

Screenshot of page footer
The page footer area, #footer.

The finished product

Here's the final template. As you can see, the finished layout is pretty darn close to the original PSD design. :)

Screenshot of PSD and final layout
The original PSD (left) and final layout in Firefox (right).

This was a pretty straightforward layout to build, since there aren't that many elements to the design and the page layout isn't too complex. Still, I hope you found the walkthrough useful and learned a couple of tips and tricks along the way.

I'll be adding to this series soon, as I show how we built more of our PageKits. Meanwhile, if you liked this walkthrough or have any other comments, please post below.

Until next time then... have fun! :)

Follow Elated

Related articles

Responses to this article

6 responses (oldest first):

28-Aug-10 14:29
That was fantastic! I've been making sites for a long time, but I realized I only went so far in learning and then just stopped. I got quite a few invaluable tips from this. Hope to see more like this!
29-Aug-10 18:31
@JohnStanowski: Thanks so much! I was really cheered by your comment.

I shall definitely write some more!
01-Dec-10 23:52
Of course, THANK YOU SIMON AND MATT!!! This is awesome! Thank you, really! Not only the fact that it is good, it is very good this stuff!!!

UAU!!!

Thank you!

Cheers from Portugal

Márcio Guerra

P.s.- Starting now I will be a web-dsigner, ehehehe!!!
02-Dec-10 20:09
Thanks Márcio! All these nice comments are motivating me to write another one of these.
03-Dec-10 21:46
If you don't mind me taking your job, go ahead, write another one, we will be waiting, eheheh!

Cheers from Portugal, and now, I guess, we can already start wishing a Merry Xmas, can't we?

Márcio Guerra
06-Dec-10 20:43
Yes indeed! Merry Xmas from sunny (actually pretty rainy right now) Australia.

Post a response

Want to add a comment, or ask a question about this article? Post a response.

To post responses you need to be a member. Not a member yet? Signing up is free, easy and only takes a minute. Sign up now.

Top of Page