- Home
- Image Slicing
- Navigation Lists
- Archive
Image Slicing for fluid CSS designs
Optimising the layout
Now we have our basic layout, and some dummy content as well. However, there are a lot of improvements that can be made that will make the page look better and load faster. This is what we will be doing in this step:
- Make the content better fit the layout.
- Optimise and combine our images.
- Clean up the HTML and CSS, organise our files
1. Make the content better fit the layout
If you look at the red border around the content in the illustration, you'll see that there is a lot of space underneath the content, and also some space above it.
So as not to waste too much of the visitor's precious screen real estate, we are going to remove this space.
First we edit the existing #content rule to remove the
space above the content. New CSS is in red:
#content {
color: #b95207;
margin-left: 70px;
margin-right: 70px;
padding-left: 1em;
padding-right: 1em;
position: relative;
top: -30px;
}
Then we bring the bottom part of the layout up to remove the space
below the content. Again, we are editing an existing rule,
.mainB. New CSS in red:
.mainB {
background: url( mainB.png );
margin-top: -168px;
}
So far so good. We've removed the gap above the content, and the gap below it. There's only one problem, and this is why I made the h2 have a lot of text in it, so that you could see the problem in action. Because of the curve in the background image, under some conditions the header overlaps the background:
To fix this, we will use two empty divs that will stop the header text from overlapping the background. We will insert the following HTML into the page:
<div id="content">
<div id="spacerL"></div>
<div id="spacerR"></div>
<h2>
A really long title, this is a level 2 header as it is the 2nd most
important header on the page
<h2>
We insert the following into our CSS:
#spacerL {
float: left;
height: 1em;
width: 60px;
}
#spacerR {
float: right;
height: 1em;
width: 60px;
}
This adds two invisible blocks that stop the header or any other content from reaching the edges of the layout at the top. I have added a red border to these blocks in the illustration so that you can see exactly what they do:
Our content now sits a lot more snugly in our layout.
2. Optimise and combine our images.
The easiest way to explain the concepts involved in slicing our layout image was to cut it into 9 slices. This means 9 seperate HTTP requests that your browser has to make, and depending on how much latency your Internet connection has, this can translate into a noticeable delay. We can actually combine these 9 slices into 5 slices.
How does this work? Maybe the easiest way to explain it is to go back to the exploded perspective view again:
Even though the background images are now 440px high, the
div elements that they are applied to are still only
220px high. Now we can use the same images for both the top and the
bottom parts of our layout, and just offset them differently so that
only the part we are interested in shows through the 220 pixel
high "window".
So, we combine mainTL.png and mainBL.png, saving the resulting image
as mainTLBL.png. We combine
mainTR.png and mainBR.png to form
mainTRBR.png. We combine
mainT.png and mainB.png to form
mainTB.png.
mainL.png and
mainR.png can't be combined, so they
remain as they are, although we have trimmed them down a little.
We've done this because they are going to be sitting on a white
background anyway so they don't need those additional white pixels
on the insides of the images. We can throw mainC.png away
completely, because it's just an image filled with white, we may as
well just use CSS to give the div a white background.
We don't need to make any changes to our HTML to accomodate the new way of slicing the image, but we do need to change our CSS. We make the following changes (marked in red) to our CSS:
.mainT {
background: url( mainTB.png );
}
.mainTR {
background: url( mainTRBR.png ) no-repeat top right;
}
.mainTL {
background: url( mainTLBL.png ) no-repeat bottom left;
height: 220px;
}
.mainC {
background: white;
}
.mainR {
background: url( mainR.png ) repeat-y right;
}
.mainL {
background: url( mainL.png ) repeat-y left;
}
.mainB {
background: url( mainTB.png ) bottom;
margin-top: -168px;
}
.mainBR {
background: url( mainTRBR.png ) no-repeat bottom right;
}
.mainBL {
background: url( mainTLBL.png ) no-repeat bottom left;
height: 220px;
}
Note that apart from the changes in file names, some of the slices
also have a position such as top or bottom
added. Now that the background image is 440px high, we want the
right 220px portion of it to show through the 220px high
div elements, so we tell the browser to start drawing
the background from either top or bottom
depending on which part of the layout it is.
The next thing we can do to optimise our images is reduce the colour depth that some of our images are saved at. mainTLBL.png contains 1301 colours. We can't reduce it to the next bit depth down (256) without it looking bad, so we leave that image as it is, at 24 bit. mainTRBR.png is a special case, so we will leave that for now and come back to it later. mainL.png and mainR.png don't have very many colours at all. In fact, they look just as good using only 16 colors, so we reduce them to this. mainTB.png has too many colours for us to reduce it to 16 colours without it looking bad, but it looks fine at 256 colours, only in fact using 121 of those 256.
The reason we decided to come back to mainTRBR.png is because of the photo of the lemon/lime. The nature of PNG compression means that the other images we used compressed quite nicely, but because PNG doesn't compress photos well, this slice is a lot bigger than the others. While mainTLBL.png is around 11KB, mainTRBR.png weighs in at a hefty 40KB! This is much too big, so we decide to bite the bullet and save it as a jpeg file, which is better suited to compressing the photo part of the image. We don't want to use too much compression though, because jpeg creates noticeable artifacts in the image that will make it look bad, so we save it at only 5% compression, yielding a much more manageable file size of 14KB.
What has all of this achieved? We have managed to get the total file size of the layout images down from around 55KB to about 25KB, a saving of 30KB, or over 50%.
Because we have changed mainTRBR.png to a jpeg file, the filename has changed to mainTRBR.jpg. We need to update our CSS:
.mainTR {
background: url( mainTRBR.jpg ) no-repeat top right;
}
.mainBR {
background: url( mainTRBR.jpg ) no-repeat bottom right;
}
Note that the PNG images would be slightly bigger, but I ran them through a free command line utility (available for Windows, Unix and Linux) called Pngcrush. I used the -brute switch to reduce the file size as much as possible, and I also removed the gAMA chunks from the PNG files using the -rem switch, because otherwise Internet Explorer renders the colours slightly incorrectly (the actual problem is that it is applying gamma correction when it shouldn't be).
3. Clean up the HTML and CSS, organise our files
Finally, we want to optimise our HTML and CSS a little, and organise our files a little better.
Remember how when we created the divider earlier, we didn't
explicitly give the div elements class names like we
have with our layout div elements, instead using
selectors like .hr div and .hr div div?
Now we are going to do this with our layout div
elements as well.
In our HTML, this:
<div class="mainT"><div class="mainTR"><div class="mainTL"></div></div></div>
<div class="mainC"><div class="mainR"><div class="mainL">
Becomes this:
<div class="mainT"><div><div></div></div></div>
<div class="mainC"><div><div>
And this:
<div class="mainB"><div class="mainBR"><div class="mainBL"></div></div></div>
Becomes this:
<div class="mainB"><div><div></div></div></div>
All of our CSS selectors change also (changes in red), and we need
to add a new rule, .mainC div div div (also in red) so
that it doesn't try to apply the new rules to all of the
div elements inside .mainC:
.mainT {
background: url( mainTB.png );
}
.mainT div {
background: url( mainTRBR.jpg ) no-repeat top right;
}
.mainT div div {
background: url( mainTLBL.png ) no-repeat top left;
height: 220px;
}
.mainC {
background: white;
}
.mainC div {
background: url( mainR.png ) repeat-y right;
}
.mainC div div {
background: url( mainL.png ) repeat-y left;
}
.mainC div div div {
background: none;
}
.mainB {
background: url( mainTB.png ) bottom;
margin-top: -168px;
}
.mainB div {
background: url( mainTRBR.jpg ) no-repeat bottom right;
}
.mainB div div {
background: url( mainTLBL.png ) no-repeat bottom left;
height: 220px;
}
We also have to make the .hr
selectors more specific by prefixing them with #content
so that they don't get overridden by our new rules:
#content .hr hr {
display: none;
}
#content .hr {
background: url( hrC.png );
margin: 1em 0;
}
#content .hr div {
background: url( hrR.png ) no-repeat right;
}
#content .hr div div {
background: url( hrL.png ) no-repeat left;
height: 14px;
}
And some changes to our body rule to make the page
look a little nicer, and to stop it collapsing below a point where
the layout breaks:
body {
background: #eee;
color: black;
font-family: sans-serif;
font-size: 100%;
line-height: 1.5em;
min-width: 440px;
}
Next, we create a new folder called "layout", in the same location as our index.html. Then we create a new file in the layout folder called "layout.css". We cut the CSS out of our HTML file and move it to the "layout.css" file. We also move all of our layout images (but not nrkn.png! this is a content image) into the layout folder.
Now we need to add a reference to our CSS file to the HTML. There are a couple of ways to do this, but I prefer to do it like this, because it hides our CSS from old browsers that won't render it properly:
<style type="text/css">
@import url( layout/layout.css );
</style>
Finally, we create another folder called "content" and move our content images into it. At the moment our only content image is nrkn.png. We have to update our HTML to reflect the new location:
<h1><img src="content/nrkn.png" alt="nrkn"></h1>
That's it! You're all done. Our HTML and CSS is shown below, or you can view the optimised page, or you can download a zip file containing all of the files that make up the optimised layout (ZIP, 31KB).
Contents of index.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Basic Fluid CSS Layout with Dummy Content</title>
<script type="text/javascript"></script>
<style type="text/css">
@import url( layout/layout.css );
</style>
</head>
<body>
<h1><img src="content/nrkn.png" alt="nrkn"></h1>
<div class="mainT"><div><div></div></div></div>
<div class="mainC"><div><div>
<div id="content">
<div id="spacerL"></div>
<div id="spacerR"></div>
<h2>
A really long title, this is a level 2 header as it is the 2nd most
important header on the page
</h2>
<div class="hr"><div><div><hr></div></div></div>
<h3>
This is our level 3 header, as it is the 3rd most important header on
the page
</h3>
<p>
If we had more than one section on this page, each of them would get
a level 3 header, as each section is of equal importance. If we had
some sub-sections inside these sections that needed a header, they
would get a level 4 header, and so on and so forth.
</p>
<ol>
<li><span>This is the first item in the list</span></li>
<li><span>This is the second item in the list</span></li>
<li><span>This is the third item in the list</span></li>
</ol>
</div>
</div></div></div>
<div class="mainB"><div><div></div></div></div>
</body>
</html>
Contents of layout/layout.css:
* {
margin: 0;
padding: 0;
}
body {
background: #eee;
color: black;
font-family: sans-serif;
font-size: 100%;
line-height: 1.5em;
min-width: 440px;
}
.mainT {
background: url( mainTB.png );
}
.mainT div {
background: url( mainTRBR.jpg ) no-repeat top right;
}
.mainT div div {
background: url( mainTLBL.png ) no-repeat top left;
height: 220px;
}
.mainC {
background: white;
}
.mainC div {
background: url( mainR.png ) repeat-y right;
}
.mainC div div {
background: url( mainL.png ) repeat-y left;
}
.mainC div div div {
background: none;
}
.mainB {
background: url( mainTB.png ) bottom;
margin-top: -168px;
}
.mainB div {
background: url( mainTRBR.jpg ) no-repeat bottom right;
}
.mainB div div {
background: url( mainTLBL.png ) no-repeat bottom left;
height: 220px;
}
#content {
color: #b95207;
margin-left: 70px;
margin-right: 70px;
padding-left: 1em;
padding-right: 1em;
position: relative;
top: -30px;
}
h1 {
position: absolute;
top: 75px;
left: 75px;
}
#content .hr hr {
display: none;
}
#content .hr {
background: url( hrC.png );
margin: 1em 0;
}
#content .hr div {
background: url( hrR.png ) no-repeat right;
}
#content .hr div div {
background: url( hrL.png ) no-repeat left;
height: 14px;
}
ol {
color: #5ac90f;
font-weight: bold;
margin-left: 1.5em;
}
ol span {
color: #b95207;
font-weight: normal;
}
li {
margin-top: 0.5em;
}
h1, h2, h3, h4, h5, h6 {
color: #5ac90f;
font-family: "Arial Rounded MT Bold", sans-serif;
font-weight: normal;
margin-bottom: 1em;
}
h2 {
text-align: center;
}
p {
margin: 1em 0;
}
#spacerL {
float: left;
height: 1em;
width: 60px;
}
#spacerR {
float: right;
height: 1em;
width: 60px;
}

Step
3, Adding and styling dummy content