Putting Style in the Hand of the User
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:
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.
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:
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.
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.
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.
nice article
As always, worth the wait...
thanks Jake !
Reply
Cool Article
Jake,
Cool article. Thanks.
I have a question. You are using the Domino feature of setting your default Stylesheet as a Shared Resource. Cool, but you are using what I consider a more accepted way I bring in the stylesheet. Using the $$HTMLHead field and coding the path to the stylesheet.
Have you tried inserting a stylesheet the way the Notes help describes? If yes, do you like either way of bring a stysheet into a form, page or subform?
Reply
Re: Cool Article
Glad you like it Erskine.
You want to know what I think of the way Lotus expect you to use Domino? :o)
Well, I appreciate them trying to make it easy for us. But I don't like easy if it means I lose some control.
Here's the code Domino generates. Which, incidentally, appears AFTER any other CSS you might insert in the head yourself using HTML (which would break any cascading as discussed in this article).
<link rel="stylesheet" type="text/css" href="/apps/validation.nsf/codestore.css?OpenCssResource">
If you didn;t know the HTML required to insert the resource then the approach of having Designer do the work could save the day. For the rest of us we're going to need more control. For instance, we couldn't insert a CSS resource this way and specify it as a style sheet to be used for printing only.
Notice of the code generated that it's yet another part of Domino's HTML that's not XHTML compliant. To make it so, it would have to end with a " />".
A nice idea but not for me I'm afraid.
Jake
Reply
Show the rest of this thread
question...
Was definately worth the wait, and hopefully more people will take this approach in their development.
One question however (didn't think you'd get away with nothing but fluff right?!?): Why not name the view "styles.css", then "$$ViewTemplate for styles.css" and make you links simply "styles.css"?
I know I've never run into an issue where a call to "styles.css" didn't open the view as intended... and it would make for a smoother and more standards-based look and feel (would also validate etc). Am I seriously missing something, as I've done this in my own dev without an event (yet?)?!?
Also, thanks for the nod Jake! :-D
-Chris
Reply
Re: question...
In theory you can call the view whatever you like and still omit the ?OpenView command. I left it in so that readers could easily see that one was a Resource and one was a View.
Also, in theory, omitting the ?OpenView will slow you application down. If you don't tell Domino it's a view it's looking for it has to work out that "styles.css" is a view before it can render it...
Jake
Reply
Show the rest of this thread
CSS storage
I prefer to keep my CSS in real life documents. Therefore, I don't need designer access to modify my CSS if I want to. All CSS files are in a view, CSS, and I can call them by using /CSS/myCSS.css
Just my 2 Canadian cents
Reply
Thorough - good!
Thanks Jake,
You did some of the leg-work on this I hadn't even thought neccessary. Nice bit of trail-blazing. I'm seriously rethinking that single form approach I mentioned.
Jerry
Reply
some improvements
Great article.
Some things that can be done, and you have probably done yourself, but may be out of the scope of this article:
- upload images people can use as logo's / background - create drop down menu's for choices, so you can select for H1 bold/normal/italic, and verdana/arial/.. and underline/no underline. This way the users don't have to understand the syntax of css - give them the ability to choose between a left and right menu lay-out
Nice thing of this, especially if you use it for teamroom like applications, that users feel like it is "their" website. Instead of having something forced upon from head office, they consider it as a tool they can use for their own good. Knowledge sharing at least triples because of this.
Reply
text/css not passing through
Jake,
I'm implementing your design having abandoned mine in favor of it. I've noticed that the content type isn't right for the view (shows as text/html in the sniffer and doesn't get applied to forms). I set it up per the article... curious.
It may be because I'm running on the local httpstack. I'll have to put it up on my test server later this week and have another go at it.
If you have any ideas, let me know, chum!
Jerry
Reply
View Template
The problem I was having with this... I was spaced out.
$$ViewTemplate != $$View Template
:-i
Reply
Problem with lots of style definition docs
This article is a cool idea for handling CSS.
One problem though, if you create lots of style definitions, your server may not send all of the style documents through the form "$$ViewTemplate for vwCSS"
Currently on that form, you have the field $$ViewBody. on my d/l copy, I removed the field, and replaced it with an embedded view, so that I could change the "Lines to display".
For me, it broked when I had >30 Style definitions, it only sent the first 30. Probably there is a server setting you could change to make it work indefinitely, but I'm not the greatest admin in the world, and I can't find that setting.
Reply
Re: Problem with lots of style definition docs
Paul,
You can fix this by appending the count argument to the css url.
/vwCSS?Openview&count=100
I'm not sure what the upper limit is, but this solved the immediate issue with the example provided, which I ran into also.
Cheers,
Jerry http://datatribesoftwerks.com
Reply
Putting HTML in the hands of the developer
I know the answer to this must be already someware in codestore... but sorry I did not find it. how do you avoid Domino putting his own HTML tags at the beginning of your pages? the extra <HEAD> and <BODY> tags are giving the gratest problems with accessibility validation
i have a form with pass-through HTML that begins like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="it" lang="it"> <head>
but the HTML of the web generated page is
<HTML> <HEAD> ***eventually the <SCRIPT tag*** </HEAD> <BODY TEXT="000000" BGCOLOR="FFFFFF"> <FORM METHOD=post ACTION="/portale/nuovo/home.nsf/formlaura?OpenForm&Seq=1" NAME="_formlaura"> <INPUT TYPE=hidden NAME="__Click" VALUE="0"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="it" lang="it"> <head>
how can I get rid of the extra HTML? grazie mille!
Reply
Suggestion article: using CSS in the Notes Client?
After reading the article 'Notes Applications with Style' (http://lotusadvisor.com/doc/15115) maybe a good suggestion for a coming article would be exploring the possibilities on using CSS within the Notes Clients?
Reply
Re: Suggestion article: using CSS in the Notes Cli
Notes Client? You're having a laugh. Wouldn't touch it with a barge-pole.
Reply
Show the rest of this thread
Demo login
How can I log into the demo? I don't have any login and password.
Reply
Re: Demo login
You can't login. You'll have to download the Lotus Notes database file if you want to play with creating new styles.
Reply
Great but why...
Hi Jake,
I Think this is great! I have been searching for how to do this before but never found it until now.
Just one !Why! Why do I need the "Default.css" file? Why not just use the one I create in my css view. It's so much easier to update the css in the view than update the css-file.
/RT
Reply
Re: Great but why...
Good question. So long ago now I can't remember why I did that. I guess one good reason why is that there are some things you don't want your users to have control of or don't want them to be able to remove. Naturally you can just remove the file. It's up to you.
Reply
Thanks Jake - all the way from 2018 . Your Domino legacy lives on :-)
Reply