Page layout using CSS: a very simple example
Rather often people ask how one could use CSS positioning instead of tables for layout. I had been looking for a simple example, but with no luck, so I decided to try and design one. (You are now viewing the styled version. See the unstyled version for comparison.)
So you want nav links on the left?
Suppose you would like to have a set of site navigation links on the left. A very simple idea, which could be implemented using a two-cell table. But the CSS approach has several benefits, including the fact that it can be made to degrade gracefully to purely linear presentation when CSS support is switched off. And it could be done so that then the nav links are after the content proper, which is often desirable. For example, blind users don't like to hear all the links first every time they move from a page to another within a site.
Note that this means assigning some width on the left to the navigational links, across the page vertically, even if this means wasted space below the actual links. It might be more appropriate to make the content take full width after the link section, but this would be a different issue. That approach will be briefly discussed below, though.
Use two div
elements and absolute positioning
The simple idea is to make the document body consist of two
div
elements, one of which contains the content proper and the other
contains the nav links. Then I use CSS to make latter div
take some specific width, using font size as unit, and using a suitable
value corresponding to the widths of the links. And the
div
that
has the content proper is absolutely positioned so that it will
appear to the right of the nav links.
The simple example
This means something like the following:
#nav { width:5em; padding:0.3em;
background:#fff; color:#000;}
#content { position: absolute; top: 1em; left: 8em;
padding-bottom:0.5em; }
#nav hr { display: none; }
#nav ul { margin: 0 0 0 1em; padding: 0; }
#nav li { margin: 0; padding: 0; }
<div id="content">
Content proper goes here
</div>
<div id="nav">
<hr>
<ul>
<li>
a link goes here</li>
<li>
another link goes here</li>
...
</ul>
</div>
In this example, I just position the content part absolutely about 8 em units from the left. This leaves sufficient space for the small navigational part, which is positioned by the browser appears there as if there were no content part. The idea of absolute positioning is that you specify the position and other elements get positioned there as if the absolutely positioned element were not present at all.
Information about the constructs used
Please see my collection of essential CSS links for information about the properties and techniques used. For positioning in particular, see CSS Positioning, Part I and CSS Positioning, Part II as well as other informative and readable tutorials by by Stephanos Piperoglou.
In particular, note that padding
is used to
prevent the text inside the navigation box from hitting the box border.
Also note that display:none
causes the hr
element between the content proper and the navigation links
to be ignored in presentation, i.e. a horizontal rule
will appear only when
the style sheet is not applied. The rules for #nav ul
and #nav li
make the presentation of a list more
compact than in typical default rendering. This lets us use the
logical construct and still tune the presentation into a small box.
Discussion
I posted an article presenting the idea above to the comp.infosystems.www.authoring.stylesheets newsgroup. It raised an interesting discussion, from which I have picked up a few comments that I found especially interesting.
But everything besides the navigation bar has to go in the 'content' div. If you want to put a separate footer beneath the content over the full length of the page, you're in trouble with this approach.- -It doesn't 'work' properly in browsers that support only CSS1 and no CSS positioning (aka Opera 3.5-3.62) The fall back is readable enough.- -In Netscape 4.7, the left margin for the UL element gets added to the default margins.
I like the use of ems. It shows that CSS layout can be based on (and thus, can adapt to) the size of the user's font. It isn't that complex a concept that it should cause problems for those migrating from table-based layout to CSS-based layout.
Sander Tekelenburg mentioned the site
http://henkhaverhoek.nl
,
which uses float
to position things. And float
indeed is another interesting
possibility
of creating layout in simple CSS. The reason why I chose absolute
positioning is mainly that it looked more natural from the
perspective of people who have used tables for layout.
He also wrote that the simple positioning approach
helps to keep the HTML
simple, and easy to maintain.
"You can just quickly mark up your content and be done with it.
The only 'ugliness' is the odd DIV
that you really only need for the
CSS."
Stan Brown wrote about problems with Netscape 4.x. Actually,
my original idea didn't work at all on Netscape 4.5 in some
tests: the navigation block just didn't appear at all!
It's up to you to decide what position to take to Netscape 4.x,
which is a nest of bugs as regards to CSS support. But for the
purposes of my demonstration, I replaced the use of a border, as in
#nav { border: solid 0.1em #060; }
by the setting of background and text color. There might be ways
to circumvent the Netscape 4.x bugs so that you can specify a border,
instead of or in addition to background, but I'm satisfied with the
observation that the navigational area can be made visually distinctive
in some manner.
Suppressing the navigation on print
Site navigation links are hardly useful in printed copies. Besides, since they eat up horizontal space when positioned on the left, part of the content proper often get chopped off. It's frustrating to print a long page just to see that the last few characters of each line have been lost.
In the approach described above, it's easy to add a style sheet rule that suggests that the navigation links be omitted in print:
@media print { #nav { display:none; } }
This, however, is not sufficient, since the content would still
be positioned, leaving an unnecessary left margin. But since
the idea of positioning the nav links on the left probably makes
sense on computer screen only, we could simply put our original style
sheet inside a
@media screen {
...}
wrapper. This means that the style sheet as a whole would be the following:
@media screen {
#nav { width:5em; padding:0.3em;
background:#fff; color:#000;}
#content { position: absolute; top: 1em; left: 8em;
padding-bottom:0.5em; }
#nav hr { display: none; }
#nav ul { margin: 0 0 0 1em; padding: 0; }
#nav li { margin: 0; padding: 0; } }
@media print {
#nav { display: none; } }