In this tutorial we are going to create a very basic “blank canvas” webpage which has a central white cut-out with a drop shadow effect. Our “page” will be 960px wide, floated in the center of the browser window:

Tutorial end product

aBlankCanvas
Click to enlarge

Real-world example

a non-blank Canvas
Click to enlarge

The following is a list of steps needed to create the drop-shadow page edge images using the freely available GNU Imagine Manipulation Program (v2.6.6):

  1. Create a new image: File > New. Image size: 960 x 60, Fill with Transparency.
  2. Using the “Rectangle select tool” R, draw a random rectangle, it doesn’t matter where you draw it or how big you draw it because once you have a arbitrary selection, specify the following attributes in the Toolbox: Position: 10, 10. Size: 940, 40 px. The result should be a central rectanglar selection with a 10px margin on each side.
  3. Select the “Bucket fill tool” Shift+b, make sure the current foreground colour is black (d) and click inside the selection to create a black rectangle.
  4. Shrink the selection by a pixel: Select > Shrink, 1 pixel.
  5. Switch the foreground/background colours (x) so it’s now white and bucket fill the new selection to create a white rectangle with a black border.
  6. Add the shadow: Filters > Light and Shadow > Drop Shadow. Offset X: 0, Offset Y: 0, Blur radius 10, Colour: black, Opacity: 50, Allow resizing: unticked. The shadow is quite faint so it might be difficult to see until we have a white background.
  7. Add two horizonal guides. Image > Guides > New Guide. Horizontal, Position: 20 and Image > Guides >New Guide. Horizontal, Position: 40.
  8. The guides make is so we can slice the image into three: Image > Transform > Guillotine. Three new gimp windows will pop up. Save them as topShadow.png, edgeShadow.png and bottomShadow.png and we’re done.

Here is the smallest amount of HTML (that I can think of) that uses these drop-shadow images to create a valid webpage:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Mockup</title>
    <link rel="stylesheet" href="http://yui.yahooapis.com/2.8.0r4/build/reset/reset-min.css" />
    <style>
    .row {width: 960px;margin: 0 auto}
    .topShadow {background: transparent url('topShadow.png') 0 0 no-repeat;padding-top:20px;margin-top:40px}
    .edgeShadow {background: transparent url('edgeShadow.png') 0 0 repeat-y}
    .bottomShadow {background: transparent url('bottomShadow.png') bottom left no-repeat;padding-bottom:20px}
    </style>
</head>
<body>
<div class="row topShadow"></div>
<div class="row edgeShadow"><p style="height:400px;text-align:center">Hello world!</p></div>
<div class="row bottomShadow"></div>
</body>
</html>

Notes:

  • Inline CSS is bad – The only reason I used it was to condense the example into a single file.
  • I used the Yahoo reset – amongst other things, it strips all margin and padding from divs.
  • The page is centered using margin: 0 auto; on the row class.
  • The padding on the topShadow and bottomShadow divs is the same height as the background drop-shadow images.
  • The edgeShadow div background is repeated vertically so the page can be any height.

There’s a few problems with what we’ve done so far:

  • We shouldn’t use a empty div elements for the top and bottom shadows.
  • The transparency used in the shadow images won’t work in IE6 because it doesn’t support 24bit png images. If you want to support IE6, here is one solution.
  • We use 3 images for the page outline – we could save two HTTP requests if we could use a single image.
  • The process we used to build the shadow images didn’t involve any creativity. The programmer inside me says that if a robot could do a task, a robot should do the task – I have written a script that generates these images automatically.

Let’s convert the toy example into something that is actually usable.

The first thing to do is to concatenate the 3 shadow images into a single image, tiled horizontally. e.g.

montage -mode concatenate topShadow.png edgeShadow.png bottomShadow.png pageShadow_horzSprite.png

Good info about sprites can be found at alistapart. We use the sprite image as follows:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Mockup</title>
    <link rel="stylesheet" href="http://yui.yahooapis.com/2.8.0r4/build/reset/reset-min.css" />
<style>
<!--
/* 1KB Grid */
.grid_1 { width:60px}
.grid_2 { width:140px}
.grid_3 { width:220px}
.grid_4 { width:300px}
.grid_5 { width:380px}
.grid_6 { width:460px}
.grid_7 { width:540px}
.grid_8 { width:620px}
.grid_9 { width:700px}
.grid_10 { width:780px}
.grid_11 { width:860px}
.grid_12 { width:940px}
.column { margin: 0 10px;overflow: hidden;float: left;display: inline}
.row { width: 960px;margin: 0 auto;overflow: hidden}
.row .row { margin: 0 -10px;width: auto;display: inline-block}

/* Theme */

body {padding-top:40px;}

.topShadow {
  background: transparent url('pageShadow_horzSprite.png') 0 0 no-repeat;
  padding-top:20px;
}
.edgeShadow {
  background: transparent url('pageShadow_horzSprite.png') -960px 0 repeat-y;
}
.bottomShadow {
  background: transparent url('pageShadow_horzSprite.png') bottom right no-repeat;
  padding-bottom:20px;
}
.topShadow .grid_12, .bottomShadow .grid_12 {
  background: transparent url('pageShadow_horzSprite.png') -960px 0 repeat-y;
  margin:0;
  padding:0 10px;
}

/* Base - used just for demo*/
ul li {list-style-type:disc;margin: 0 20px;}
h2 {font-weight:bold;font-size:1.2em;margin:0.5em 0}
p {font:40px/55px Helvetica;text-align: center;border: 1px dashed #000;}
-->
</style>
</head>
<body>

<div class="row topShadow">
    <div class="column grid_12"><p>header goes here (12)</p></div>
</div>

<div class="row edgeShadow">
    <div class="column grid_8"><p>8</p>
        <div class="row">
            <div class="column grid_4"><p>4</p></div>
            <div class="column grid_4"><p>4</p></div>
        </div>
        <div class="row">
            <div class="column grid_2"><p>2</p></div>
            <div class="column grid_2"><p>2</p></div>
            <div class="column grid_2"><p>2</p></div>
            <div class="column grid_2"><p>2</p></div>
        </div>
    </div>
    <div class="column grid_4"><p style="line-height: 222px;">4</p></div>
</div>

<div class="row bottomShadow">
    <div class="column grid_12"><p>footer goes here (12)</p></div>
</div>

</body>
</html>

This is what the resulting page looks like:

Click to see full size version

How does it work?

  • The 1KB grid is used to allow for a flexible layout structure.
  • A single image (pageShadow_horzSprite.png) with varying offsets is used for the page shadow. To tile images vertically we need to use a horizontal sprite and set the horizontal offset. This is how we access the sprite image to get the 3 background page shadows:
    • background: transparent url('pageShadow_horzSprite.png') 0 0 no-repeat;
    • background: transparent url('pageShadow_horzSprite.png') -960px 0 repeat-y;
    • background: transparent url('pageShadow_horzSprite.png') bottom right no-repeat;

I have done a related post which describes how to automatically generate page shadow images.

Leave a Reply