Putting Style in the Hand of the User

Jake Howlett, 7 December 2003

Category: Miscellaneous; Keywords: CSS Cascading Style Sheets

Introduction:

Cascading Style Sheets (CSS) shouldn't really need an introduction. We're all web developers here and we should all know why using CSS is such a good thing. Right?

Talk of CSS is everywhere at the moment. Don't worry though, this article is not about what you can do with CSS and why you should be using it. Instead it offers an approach to implementing CSS that you might not have considered before. One with many benefits.

Do we need CSS with Domino?

We've all heard the mantra - "Separating design from content". The idea being that you can then change the whole design of a site from a single file. Amazing as this is, it's not such a big deal for us Domino developers. Sure, if you've got 300 html files stored on your hard drive, with the style contained in the markup, you've got your work cut out to change the presentation in all of them. However, as Domino developers, we don't need to worry so much. Changing the presentation of every document in a database can be as simple as editing one subform.

So why should we care about CSS? Good question! And one with lots of answers. Consider, for one, that removing all presentation from your page's design makes the HTML a lot "lighter" and saves workload on the server.

There's lots of other reasons but, for now, I will assume you don't need persuading and just want me to get to the point.

What I want to talk about in this article is a way to give power-users, without developer access, the ability to edit the CSS. To do this we are going to have to make the CSS code part of the database's content, adding it to documents.

Why store CSS in documents?

Imagine you have a template used as the intranet for every department within your company. Now imagine each department has their own logo and is very particular about the way their site looks. Obviously CSS is the thing to use. But how would you tailor this CSS for each department? The idea that springs to mind for me is using documents to store personalised CSS definitions. Then we can use a view to present this content to the browser as CSS.

How do we do this?

First thing to do is to simply design your site as you would normally. Start with the layout and create an HTML file as a dummy document. Use CSS to position all the elements and set their colour/size. Once you're happy, save this CSS in a file called default.css and add it to the design of a new database as a Style Sheet Resource, like below:

Default Style Sheet

Now start creating the Forms and attach this stylesheet to all of them. You should end up with them looking like the HTML "comp" file you started out with.

Note: Most of this article and the sample database is heavily based on features of Domino 6. However, the principles involved are just as useful in any version of Domino. If you don't use Domino 6 yet, don't worry.

The idea of this default style-sheet is that it acts as the basic styling for the whole site. Think of it as the "vanilla" style. It contains just enough code to make the site presentable. Anything else is configured by the designer (or trained power-user) whenever a new implementation of the template is needed.

This stylesheet is fixed. It's part of the design of the database and can only be changed by a design update. We now need an additional method of supplying style definitions. This is where the idea of "Style documents" comes in.

Adding Style Documents:

To add style documents we first need a form that will hold the CSS definitions. It's a simple form - all we need is a text field for the name of the class and a multi-value field for holding each of the definitions.

Style Document in design mode

Notice already that we are giving elements on the Form classes so as to use as much CSS as possible!
In the browser, this form would look like the one below:

Style Document in browser mode

Obviously, there are a few more fields on the form but we only need to worry about these two. Using them, we can create a fairly simple Notes View that will display all our Style Documents as one CSS "file".

Consider this simple section of a CSS page:

body {
background : #6cf url(logo.png) no-repeat fixed top left;
margin : 0px;
padding : 0px;
}

h1 {
font-size : 2em;
}


It's a very simple format - name of the class, followed by all the definitions, separated by semicolons and then enclosed within curly brackets {}. We can easily mimic this using a view. All you need is one column. In it you reference the field cssClassName, followed by the imploded list of definitions from the multi-value field. The following formula should do the trick:

cssClassName + "{" + @Implode(cssClassDefinition;";") + "}"

You can imagine what this view would look like. Just a load of CSS. All we need to do now is get the browser to load the view as a CSS resource and we're laughing.

To add CSS files to my Domino sites I like to have a field called "$$HTMLHead" in my common fields subform. In it I have a formula similar to this:

"<base href=\"http://" + Server_Name + "/" + @WebDbName + "/\" />" + @NewLine +
"<style type=\"text/css\">@import url(Default.css?OpenCSSResource);</style>"+
"<style type=\"text/css\">@import url(Styles?OpenView);</style>"+ @NewLine

Using a field with this reserved name on a form adds its value to the page's HTML <head> element. This makes sure that both the default CSS file and all the rules from the view get included in every page on the site.

Note: It's important that the view is listed after the Style Sheet Resource in the page's header. I'll tell you why later...

All that's left to do now is make sure the browser knows that the view we are asking it to treat as CSS, really is CSS. Some browsers, in particular the standards-compliant ones, like Mozilla, don't like being sent HTML if they are expecting CSS. This property is governed by the content-type header of the resource being requested. By default, when you request a view from Domino, it will have the content-type of "text/html". We need to change this to "text/css". To do this we take advantage of a new Domino 6 feature that let's us set the content type of a form. In our case we create a form called "$$ViewTemplate for Styles" (where Styles is the name of the view we store Style Documents in) and make sure we make the following change to its properties tab.

Style Form's properties box

The view template form itself only needs to contain a field called $$ViewBody (or you can embed the Styles view if you prefer). Now, when the view is requested, this form is returned and it has the correct content type for the browser.

We can make sure we have the right content type by watching the traffic between the browser and the server as the page loads. Notice in the shot below the "type" of the view. We wouldn't have been able to do this prior to Domino 6 and it's an essential part of getting this approach to work across all browsers.

Traffic sniffing the view

With all this in place we can start adding Style Documents to the database. Each time you add one the CSS definitions in the view will change and hence, so will the appearance of the page. Magic.

Using these document, you can either add new CSS styles or you can over-ride those already present in the default Style Sheet. If the default Style Sheet set the body's background colour to blue, you can easily chage it to red.

But how does this work?

As I mentioned earlier, it's essential that the view of Style Documents is referenced after the default Style Sheet resource in the <head> element. This allows us to over-ride any styles in the default stylesheet because the style sheets "cascade".

If you set the same property twice in the CSS of any page, it's the definition which appears last that takes effect.

In our case, if the default Style Sheet resource contains this class:

.aClass {
font-weight:bold;
color: red;
text-decoration:underline;
}

And you add a custom Style Document that defines the same class but with different properties, like so:
.aClass {
color:yellow;
text-decoration:none;
background-color:black;
}

Then the resulting style will look like this.

Notice how the colour and underlining attributes have been over-ridden by the definition that appeared afterward. Also notice that the original bold attribute remains and that a new background colour setting has been added.

Want to see it in action?

You've had enough listening to me going on about it haven't you? You want to see it in action don't you? Oh, ok then. There's an online demo of the sample database which you can also download here.

It would have been nice to have let you guys add and edit styles in the online demo. But it would only have been a matter of time before one of you would have worked out how powerful this can be. Imagine you add a new Style Document that produces this style definition:

* {
display:none;
}

Can you see what would happen? The "*" indicates that this style is universal and applies to everything on the page. Hence this one line of CSS can blank out the whole page. Once this is submitted the only way back is to edit the document in the Notes client. You've been warned. Only give this power to people who know what they're doing.

Summary:

Not every site you work on will require this level of control over its appearance. However, even if you can't see a use for this method in the final design of your applications, it can still be useful while you're still working on designing the database. With this view in place, there's no need to keep editing CSS resources until you get it just right. You can simply edit/add documents until you're happy and then submit the changes to the Style Sheet resource once you're done.

Fancy some further reading?

Selectutorial - All about CSS selectors.
CSS Best Practices - Learn some dos and don'ts before you go any further.
CSS Vault - Oodles of CSS stuff to feast on.
Some nice CSS Site - A list of sites that may act as inspiration.


Addendum:

When I was implementing this for the first time and while I was writing this article, I had a sneaky suspicion it wasn't all my own inspiration and that I had seen it somewhere before. I was right. Chris Toohey of DominoGuru.com has written an article describing almost exactly the same method. It's likely this is where I first got the idea from and it's been lurking in my sub-conscience ever since.

Luckily, Chris said he didn't mind me writing this article and I thank him for that. Hopefully it now has a wider audience and will benefit from a few of the other ideas I've thrown in on top.