Westciv Logo

These materials are copyright Western Civilisation Pty Ltd.

www.westciv.com

They are brought to you courtesy of Style Master CSS Editor and Westciv's standards based web development courses.

Please see our website for detailed copyright information or contact us [email protected].

quick tutorials

A floated page layout

A question which was a great opportunity to create a simple little tutorial about using float and clear in a CSS based page layout was recently posted to our forum. As a bonus, I've also thrown in some information about how to work out the width of elements in a fixed width layout.

This tutorial shows you how to create a page layout like this, using web standards and CSS. Such a layout could have any number of uses, of which a photo gallery is only the most obvious. The page I've linked to there clearly isn't finished, I've just tried to keep it simple so we can focus on the layout of the images and the text.

The question asked whether it was possible to recreate this page, which at the time of writing uses tables for layout, with pure web standards and CSS.

Not too hard to do with a table, but the resulting markup is pretty heavy, only HTML 4.01 transitional, and not too good semantically. Without too much trouble it's pretty easy to improve this page on all three of these fronts. Let's see how.

The HTML

I'm not going to work through the whole page here, just the main content section, which in terms of the markup I'm going to put inside a <div> with the id content. I'd create the following, within a document which had a Strict XHTML 1.1 DTD.

<div id="content">

<img src="photo01.jpg" />

<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.</p>

<img src="photo02.jpg" />

<p>Sed diam voluptua at vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren.</p>

<div class="separator"></div>

<!-- repeat the above a number of times -->

</div>

Lighter, XHTML 1.0 Strict, and "not bad" semantically. I say "not bad" because that <div> of class separator clearly has no semantic value. In fact the only reason it's there is to make the layout work in Internet Explorer. If you were in the luxurious position of needing to create a layout that only needed to work in browsers such as Firefox, Safari and Opera both the markup and the CSS could be a little different. But I'm not going to go into that here. What I'm going to create here is a layout which works in all those browsers as well as Internet Explorer. This should be a familiar compromise.

The selectors

First we need to select all the <img> and <p> elements and make them float to the left. We'll select the using descendent selectors.

If you're not familiar with the float property, for the purposes of this tutorial you need to know that it turns any element it is applied to into a block box, takes it out of the flow and shifts it as far as possible to the left or right. You'll find a more comprehensive explanation on this page here, which is part of Russ Weakley's excellent Floatutorial.

Be sure to take a look at a page which includes the above HTML before you apply any properties. What's happening with the content? You should see it all just flowing down the page, one element after another, in the same order as it appears in the HTML code.

#content img {

float: left;

}

#content p {

float: left;

}

Floated elements need to be given a width, except if they are <img> elements, which have an implied width. So, we need to give all the <p> elements a width. I'm going to use 263px, as this is the figure you need for the text area to make a fixed width layout where everything can be seen even at 800x600. See below for how I work this out.

#content p {

float: left;

width: 263px;

}

Do this and then have a look in the browser. It might not look so amazing at this stage, but in fact the most important aspect of the whole design is now already in place. Notice how the <p> elements and the <img> elements aren't just flowing down the page anymore? Instead they are acting as block boxes and each floating to the left of each other. If you can, change the width of the window and see what happens. The elements should move around as more and less room becomes available on any given line. But, this isn't how you want the finished page to behave. Instead we want only two <img>s and two <p>s on each line. That's where the separator comes in.

Keep them separated

As we said above, any element which follows on from a floated element will wrap around it, unless you tell it to "clear" the floated element. You can tell an element to clear: left, clear: right or clear: both.

If we set clear: left on an element this means the element will drop below any elements floating on its left. And the same with clear: right. And of course clear: both will make the element drop below other elements floating on either its left or its right. That's what we're going to do here.

Remember that empty <div> element of class separator I pointed out in the HTML above? If we tell it to clear: both this will make it drop below the set of two <p>s and two <img>s floating before it. This isn't such an important thing in itself, but what it means is that that next set of two <p>s and two <img>s get separated out from the previous set, and can start a new row, so to speak.

.separator {

clear: both;

}

As long as you're not using a Mozilla based browser, the sets of images and text should now have separated out.

If you're looking at this layout with a Mozilla based browser like Firefox, you might in fact still be seeing a bit of a mess. That's because these browsers have a bit of a bug with the clear property: it only works on an element which has some sort of "actual presence". Of course, in many situations you won't even see this bug because the element will have content. Luckily enough for what we're trying to do here though, you can give the element actual presence even by giving it a 1px height.

.separator {

clear: both;

height: 1px;

}

Tweaking

Now, you probably won't want the text to be flush up against the images like that. The easiest way to fix this is to apply a bit of padding to the <img> and the <p> elements.

#content img {

float: left;

padding-right: 8px;

}

#content p {

...

padding-right: 8px;

}

Likewise, you may want to play with the amount of space between the "rows". To do this you'll need to put margin-bottom on both the <img> and the <p>, because either one of those could be longer than the other, depending on the amount of content in the <p>, and also the user's default font size in the browser.

#content img {

...

margin-bottom: 25px;

}

#content p {

...

margin-bottom: 25px;

}

While we're on the subject of margins, you've probably noticed that the top of the text, inside the <p> element, is sitting a little lower than the top of the image. This is because of a default margin, applied by the browser to all <p> elements. Set the margin-top on the <p> element to 0 and it will go away.

Centering the main content area

Now we just need to center <div id="content">. The best way to do this is to give it a width of 779px, and a left and right margin of auto. Again, I've worked out this as the right width so the layout will still work at 800x600.

#content {

width: 779px;

margin-left: auto;

margin-right: auto;

}

You'll need to put a margin of 0 on the <body> to get rid of its default browser values, but apart from this that's all there is to it. Hopefully you've added a robust new layout technique to your toolbox, and learned a bit about float and clear in the process.

How did I work out that width?

In case you're wondering this is how I worked out how wide the various elements need to be.

As I said, you want to make sure the content is viewable, without a horizontal scrollbar, even at the smaller screen size of 800px wide. I use Internet Explorer 6 as the baseline browser I aim to please here, because in fact it gives you the smallest viewing area width-wise, so if you don't see a horizontal scrollbar here, you won't see it in any browser.

The screen is 800 pixels wide, but you only end up with 779px actual viewing area once you allow for a 19px scrollbar on the right side and a 2 pixel frame on the left. So, I'll always give the content a width of 779px. And the rest kind of writes itself.

There's two images in every row, and they're each 110px wide, so that's 220px taken up by them. Then you need to add on two lots of 8px padding for each of the images, and another two lots of 8px padding for each of the paragraphs, which is 32px.

220 + 32 = 252px

If you take this away from your total width of 779px, that leaves you with 527 pixels for the two <p> elements. Divide that by two and you get 263px (you can't have a half pixel), thus this was the width I gave to the <p> elements.

The finished CSS

body {

margin: 0;

}

#content {

width: 779px;

margin-left: auto;

margin-right: auto;

}

#content img {

float: left;

padding-right: 8px;

margin-bottom: 25px;

}

#content p {

float: left;

width: 263px;

margin-bottom: 25px;

margin-top: 0;

padding-right: 8px;

}

.separator {

clear: both;

height: 1px;

}

Disagree with the method I've used to solve this problem? Feel free to let me know how you'd do it by posting a comment at my blog.