Crafting Lightweight Page Templates with CSS

Posted on September 19, 2004   |   Download sample code

25 comments

Giving your web application a consistent look and feel is a task of paramount importance. Yet, templating in ASP.NET has been complicated, to say the least. Learn how you can craft lightweight, efficient page templates with CSS.

Unfortunately, building page templates in ASP.NET has never been easy. There are several solutions to this tricky problem, but they all either involve complex inheritance with some page build-out mechanism (which is what I utilize on this site), or they put to work HttpHandlers and HttpModules and load server controls on the fly. All this is beyond the grasp of a novice developer.

There's an effective approach to building lightweight page templates. This approach requires no advanced ASP.NET skills. I didn't invent it. In fact, I think I first saw Doug Bowman use it, and then read about it in Dan Cederholm's book Web Standards Solutions. I know Mark Pilgrim has used it, and so has Ian Hickson.

By the time we're done you'll be surprised ASP.NET has very little to do with it.

<body> Styling

The idea is quite simple: we can assign the good ol' <body> element an id and a class. Next, we build a generic page template and write CSS rules that cater to each body style individually.

An example will help clarify my point. Let's create a bare-bones web log for a fictional personage, Mr. Hugh Jass. We'll create three simple pages: Home, Contact and About and fill them with Lorem Ipsum text. I've used my own web form template generator to create each one. The "blog" has no artistic value; I've thrown in just enough CSS to back up my point.

The structure of each page is the same (since we're developing a template):

<html>
...
<body>
  <div id="masthead">...</div>
  <div id="leftcol">...</div>
  <div id="rightcol">...</div>
  <div id="content">...</div>
  <div id="footer">...</div>
</body>
</html>

You see a header (masthead), footer and three columns. We'll establish up front this much: some pages will show all three columns, others—two. We'll remember to assign each <body> element a corresponding class.

<body class="twocolumns">
...
</body>

Or

<body class="threecolumns">
...
</body>

On a three-column page I float the left and right columns and squeeze content in between:

#content {
    background: #eee;
    padding: 0 2%;
    margin-left: 25%;
}

#leftcol {
    width: 20%;
    float: left;
    padding: 0 2%;
}

body.threecolumns #rightcol {
    width: 20%;
    float: right;
    padding: 0 2%;
}

body.threecolumns #content {
    margin-right: 25%;
}

The left column will always be there (in our imaginary blog). Both columns are given a 20% width with content taking up the rest. Note the body.threecolumns #content selector. The entire rule is applied to #content within a <body> of class threecolumns:

<body class="threecolumns">
 ...
 <div id="content">...</div>
 ...
</body>

The Home page of our blog has all three columns.

On we go to a two-column page. The About page is built this way. We simply use the CSS display property to hide it and adjust content to stretch and take the rest of the space:

body.twocolumns #content {
   margin-right: 2%;
}

body#contact #footer {
    display: none;
}

The Contact page is a modification of a two-column page. It shows no footer. By this I wanted to demonstrate that in addition to assigning <body> a class you can also take advantage of its id:

<body id="contact" class="twocolumns">
...
</body>

The CSS rule that hides the footer on this page only (!) is shown below.

body#contact #footer {
 display: none;
}

Done and done.

class or id?

If you research this subject on the web you'll see different opinions on whether to assign <body> an id or a class. I'll throw my opinion into the mix.

I give <body> an id only if I want to make a modification that is catered to that page only. If a modification is of a generic kind (such as hiding a column, which is done on a number of pages) a class is more appropriate. You should choose whatever works better for each project and go with it. There's no crime in using only classes or ids.

visibility or display?

Another tricky question. The CSS display: none declaration generates no element box, i.e. the hidden element "disappears" and takes no space. On the other hand, visibility: hidden does generate an element box and takes space, even though you don't see the element itself.

Since we needed to hide the right column completely—and couldn't afford having a gaping hole that visibility produces—I chose display.

Spicing Up the Template

If you download the code you'll see ASP.NET really played no part here! It's all HTML and CSS. You can take it from here and wrap the masthead into a user control, for example. Have it produce a consistent header with a logo and navigation. You can wrap the footer into a user control as well. Finally, you may have other static content or database-driven custom server controls to do heavy lifting. Plug them in where you see fit.

Conclusion

Templating with CSS is an approach that is easy to master even by novice ASP.NET developers. Of course, it has its own shortcomings, but so does every templating solution out there. I hope I taught you a new way to leverage (such a popular term these days) the power of CSS!

25 comments

Ryan Farley
on September 20, 2004

Milan,

Once again you've read my mind and have written an article specific for what I needed. How do you do that?!

I am just started a big web project where I'll need to do just this. Glad to have another expert opinion of an awesome CSS-based approach.

Thanks,
Ryan


SomeNewKid
on September 20, 2004

Fantastic article, Milan. I *really* liked this one.

Even though I am a huge fan of CSS, I had not previously read about the technique of giving the body tag a class that defines its layout.

I've really learned something from this article.

Thanks!!!


Milan Negovan
on September 20, 2004

Stand still, will ya, Ryan? I want to see what else is on your mind. :)


Edgard Durand
on October 22, 2004

I'm very concerned about standards in all my projects, I will use this approach for an asp project. thanks.


Nikhil Kothari
on January 03, 2005

In ASP.NET, templates are typically used to refer to markup that results in content... hence from an ASP.NET perspective, I'd see templates and CSS (or more generically styles whether they are server or client-based) to be two orthogonal things.

For example, in Whidbey we have master pages and themes - one for layout, another for visual appearance.


David
on January 28, 2005

The "class or id?" bit, you could have also used

[body class="twocolumns contact"]

body.contact #footer {
display: none;
}

I'm not sure about any browser problems using 2 CSS classes in a class attribute?


Karl
on January 30, 2005

Milan,

Beautiful article. I do the same thing as a matter of fact, and I have had no problem doing so via ASP.NET.

My problem for validation always arises though with the submit button on my contact page throwing off nasty code. :(

Thanks. Keep up the good work.

Karl


Programmer Or Artist?
on March 03, 2005

Hi,

I'm a programmer since a long time, and coding C# to implement businness logic is quite natural for me... The things becomes less natural when it comes to HTML layout, styles and standard. After all i'm a programmer doing web application, i'm not an artist ;-).

But today is a really good day, your arcticle blow me out... I already know that CSS is poweful to define the styles, but none of the ASP.NET resources I consulted in the last months make usage of CSS like you are doing...

It seems that I will have to left some of my old programmer's friends on the side and start to meet artists!!!

Thanks for the revelation; you are an Artist!!!


Chad
on March 16, 2005

Ok, I might be a giant 'tard. But I fail to see how this solves any of the issues with templating..

Yes you can change the look of the site, but say if you wanted to change some words in the left column, you would have to go in and edit it in *every* file... hence I don't see how this is templating at all.

Templating to me.. = having a fixed design, and loading the content into it..

If i am missing something really simple - please set me back on the path and I will eat humble pie..

But for eg.. say if I wanted to have a nav bar in the left column. I dont want to repeat that code in every page...

Someone please clear this up for me?


Milan Negovan
on March 17, 2005

Well, I was talking about page templating approaches I've seen in ASP.NET so far. They go too heavy on class inheritance and funky code rendering techniques.

I was trying to illustrate that whichever way to templating you choose (there are many of them), your template should be based on sound page structure, and not so much on presentation (which is the mistake of many templates). Once you have that going you can control the structure with CSS. That's what this is about, really.

And, of course, your shouldn't just copy and paste code from page to page.


Sheridan
on April 01, 2005

Thanks Loads - Developers should read this.

Its a shame there just aint enought of this excellent information on the web regarding this subject, as stated above this type of information is hard to come by so thanks.

More please, when u have time


Hugh
on April 05, 2005

Milan,
Killer article! I just finished a site for my company and I killed myself trying to get this kind of artifact. Why didn't you tell me sooner? :-)

I like this so much, I'm going to go back and refit my pages with this suggestion.

Thanks!


Mark
on April 13, 2005

I don't get why this article is so great in people's minds. This doesn't make the task of changing the content or markup of the masthead any easier.

In your sample:
< div id="masthead" >
Hugh Jass Personal Site
Two columns and no footer


If I wish to change EVERY page on my site, then I have to do a mass find/replace which may cause problems if there is more complex markup in the section in question.

I understand that you could (and I do) encapsulate the entire "masthead" into a user control, but then you have to include it in every page anyway.

Wouldn't it be better (if all your pages are truly templated) to derive from a base page class?

Is there something I'm missing here?


Walt
on April 18, 2005

I agree with Mark. What if you wanted to change a menu's content in a navigation bar? Can't do that with CSS.


serjiro
on April 29, 2005

Hello Everything,

I am not good in English but I will try :)

If you want page inheritance you could use peters approach. I guess this approach will erase the cut and paste of menu in every page.

But we could also apply Milans article to this approach in order to have a better display using css.

I therefore conclude that this article is great and it can be applied also using MasterPages (based from System.Web.UI.Page). Apply both thats what I mean.


chris ward
on April 30, 2005

a computer doesnt understand or carewhat leftcolumn, rightcolumn means.

think semantically milan!

you use this web-standards based method to seperate style from content, and you will find your xhtml so much more extensible if you didnt give it a naming scheme such as this.

your left box may not always sit to the left of your page!

instead of calling it leftcolumn, rightcolumn, bluebox, bigbox etc... call it something with meaning.

if your left box is your primary content box, then call it primaryContent, if the right box is secondary content, then call it secondaryContent respectively!

hope that helped

chris


Milan Negovan
on April 30, 2005

Very true, Chris. The left column may become a right column at any time should the design change. Good point.


TimGO
on October 15, 2005

> I don't get why this article is so great in people's minds. This doesn't make the task of changing the content or markup of the masthead any easier.

Correct. It doesn't. However, combined with User Controls this issue is resolved.

We're then left with the issue of inserting the header/left/right controls into every page template. This should not scare us. In a carefully constructed site with dymanic content there should only be a handful of "master" pages. For instance, a "news article" page will be one template populated with dynamic content. The "news search" may be another.

To me page inheritance is be the ideal, but as the cost of having the web "application" completely tied to asp.net. The methods of page inheritance seem far too convoluted to me; the idea of having base classes render html is, IMHO, backwards, and completely against object-oriented philosophy. Maybe ASP.Net 2.0 will improve matters.

For now, I will be using CSS and simple UserControls, across as few base pages as possible. Fast and effective, and reduced maintenance.

There's no perfect solution, but Milan certainly isolates the trees from the forest.

Thanks Milan.


Ezequiel Espíndola
on November 04, 2005

Milan, this is another great contribution from you to the spread of web standards!

As Nikhil Kothari and Chris Ward have said I think the key is thinking your site in a semantical way by applying standard XHTML, and using CSS to create the visual layout. The standard XHTML, the semantical structure of your site that repeats itself on each page like the global navigation of the site, can be centralized by the use of master pages.

I've been investigating the subject in the last few days and I think the
MasterPages Templating Framework at MetaBuilders provides a really simple solution for the problem and one of the most compatibles with the upcoming Master Pages on ASP.NET 2.0.

Are you using something similar on this site for templating?

You'd probably read it already, I'm currently reading designing with web standards and can certainly recommend it to have fun learning about the whole semantical concept of the web. =)


Milan Negovan
on November 06, 2005

Yes, I've already read Zeldman's book. Great read! For templating I use an old technique which is in some ways similar to master pages in 2.0.


Madhu Kampurath
on September 26, 2006

I like this article very much. But, I face a problem when I try to do it actually.

I would like my pages to be 100% wide. All pages has got a fixed width left navigation bar (which I am putting in a div). Then there is a right place holder where the actual content comes. Content has to occupy the full space to the right of left navigation bar. However, this fails.

I have given a fixed width for left div and 100% width for right (content) div. However, this is not working. I gave percentage widths to both - 20% for left navigation and 80% for right place holder (eventhough this is not fully acceptable to me). However, it is not aligning correctly with the header and footer which are 100% wide.

May anybody suggest a solution.


Barry Clark
on December 23, 2006

I agree with your approach. I'm playing at the moment with DBNetLink's suite for ASP.NET. It's expensive but it seems to allow you to embed massive functionality without the hassle of all the low level stuff. I think CSS is the way to go for styling - otherwise you aren't separating content from style. If your template ends up as a DLL - who needs that, when you can simply adjust the CSS to suite.

Best wishes
Barry


Web Hosting Delhi
on February 25, 2007

Thanks for idea about css template. When I have started my website I was looking for the same kind of css template, but not get enough time to dabble with css, but your trick is really appreciable and in my next coming website, I must use your template based css because I was looking for the the template which can render the home page layout diffrent from internal pages and fully controlled under .NET . Thanks a ton :)


jillymon
on March 23, 2007

This method seems a bit too simple. Perhaps .net templating is not as difficult as you think. Please revise


Wilson Perez
on February 04, 2008

Great, useful and easy to understand article...