Since the beginning, vBulletin has had some way of inserting style-related variables into its templates.

In vBulletin 1 and 2, replacement variables were used, and simple html-esque tags could be inserted in order to re-style text etc. For example:
<smallfont>Here is some small text</smallfont>
would be replaced with
<font size="1" family="verdana, arial, helvetica, sans-serif">Here is some small text</font>
The content of the replacement could be altered, so if you really wanted to, <smallfont> could be replaced with <span title="Something Useless"><font color="skyblue" size="7" face="arial"><b> or something like that...

This system was necessarily simplistic and its scope for dramatically altering the appearance of the templates was strictly limited.

For vBulletin 3 we wanted to make use of CSS, if only for reasons of bandwidth. After all, it requires a lot less text to be delivered to a client to have <span class="smallfont"> than to have <smallfont> being translated into <font family="verdana, arial, helvetica, sans-serif" size="1">. Yes, those considerations seem largely irrelevant now, but it was important back then...

The use of CSS in vBulletin 3 is relatively light. Its primary purpose was to handle the specification of font sizes and families, and to manage the colours and backgrounds of commonly-used elements.

It achieved this through the use of a relatively small number of CSS classes, such as .tborder, .tcat, .thead and .tfoot, each of which had predefined properties for which values could be specified, together with a free-form field in which extra CSS properties could be entered. All of these values were then automagically baked into a single CSS stylesheet, the precise content of which could not be (easily) altered.

This system started to show its limitations when vBulletin 3.7 called for a CSS-driven layout for the user profile page (member.php). For the tab controller, I needed access to the colours and background attributes of the .tcat predefined vBulletin 3 class, and also the border attribute from the .tborder class, without all of their extra baggage. Unfortunately, this is not possible in vBulletin 3, so a kludge class had to be made that combined .tborder and .tcat, then undid various styling rules that were set up by those two. It was not pleasant to work with.

For vBulletin 4, I wanted a system that was based on CSS and semantic XHTML, but it had to retain the simplicity of changing colours, backgrounds and fonts etc. that existed in previous versions. I also wanted to be able to access individual components of CSS classes in order to re-use them elsewhere, in a way that can not be done using vBulletin 3.

The system I devised builds on another feature that appeared in vBulletin 3, namely the Style Variable or Stylevar. For vBulletin 3, used these for storing simple strings of data, such as the path to an image directory, or the amount of cell padding to apply to tables. These variables would then be available for use anywhere in the templates, so you could see things like <table cellpadding="$stylevar[cellpadding]"> or <img src="$stylevar[imgdir_buttons]/newreply.gif" />. These values could be customized and had the same system of inheritance as the templates themselves.

Therefore, the basis of the vBulletin 4 style system is freeform, editable CSS templates with the ability to call values from style variables.

Basic Style Variable Use

Consider the following example:
this is not code from vB4
.tcat {
color: #FFFFFF;
font-size: 10pt;
font-weight: bold;
font-family: verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
background-color: #869BBF;
background-image: url(../../images/gradients/gradient_tcat.gif);
background-repeat: repeat-x;
padding: 6px;
}
In vBulletin 3, it would have been impossible to extract that #869BBF background colour for use in a different CSS class. Now let's have a look at how the same CSS could be written in vBulletin 4:
.tcat {
color: {vb:stylevar tcat_color};
font-size: {vb:stylevar tcat_fontSize};
font-weight: {vb:stylevar tcat_fontWeight};
font-family: {vb:stylevar tcat_fontFamily};
background-color: {vb:stylevar tcat_backgroundColor}
background-image: {vb:stylevar tcat_backgroundImage}
background-repeat: {vb:stylevar tcat_backgroundRepeat};
padding: {vb:stylevar tcat_padding};
}
Using this new system, the various instances of {vb:stylevar stylevarname} will be replaced with the value of the corresponding style variable. Therefore, if we want to create an entirely new class that just happens to have the same background colour as the .tcat class but the text styling from .thead, we can do so very easily:
.whatever {
font-family: {vb:stylevar thead_fontFamily};
background-color: {vb:stylevar tcat_backgroundColor};
}
Style variables can be defined and edited through the new style variable editor, which is a little rough around the edges right now, but it's functional so I'll provide a screenshot of some simple style variable values being edited:

Here you can see three different colour variables being edited, together with a simple 'size' type, which will accept a value and a unit specification.

Compound Style Variables

Further, one can have what we have called compound style variables.

Those familiar with CSS will know that some CSS properties also have shorthand equivalents. Font and Background are two examples. Instead of writing the names and values of each CSS property, like this...
.foo {
font-size: 10pt;
font-weight: bold;
font-family: verdana;
background-color: red;
background-image: url(image.png);
background-repeat: repeat-x;
}
One can instead write it like this:
.foo {
font: 10pt bold verdana;
background: red url(image.png) repeat-x;
}
Compound style variables take advantage of this ability in CSS, allowing specific shorthand properties to be employed. For example, one may define all background properties into a single compound style variable, or access the individual elements. Some code will illustrate this better than me trying to describe it...
.foo {
font: {vb:stylevar foo_font.fontSize} {vb:stylevar foo_font.fontWeight} {vb:stylevar foo_font.fontFamily};
background: {vb:stylevar foo_background.backgroundColor} {vb:stylevar foo_background.backgroundImage} {vb:stylevar foo_background.backgroundRepeat};
}
Can also be written as...
.foo {
font: {vb:stylevar foo_font};
background: {vb:stylevar foo_background};
}
As can be seen from this example, when a compound style variable is called without specifying one of its component properties, it will return all of its component properties, in a fashion that is usable for shorthand CSS properties.

This screenshot shows compound style variables being edited - each set of values is saved into a single style variable that can be accessed either with the shorthand method (foo_font), or specified as individual properties (foo_font.fontSize, foo_font.fontFamily etc.).

Style Variable Mathematics

When using CSS, there are often times when an exact dimension is required for an element in order to fit into a particular place within a layout. Unfortunately however, CSS does not provide a method to specify an absolute size for elements. Consider the following example:
<style type="text/css">
#mydiv {
width: 600px;
height: 400px;
}
</style>
...
<div id="mydiv">My 600 x 400 div</div>
This will produce a box of exactly 600 x 400 pixels. However, if we now add a little extra CSS...
<style type="text/css">
#mydiv {
width: 600px;
height: 400px;
padding: 10px;
border: solid 1px black;

}
</style>
...
<div id="mydiv">My 622 x 422 div</div>
... we end up with a box measuring 622 x 422 pixels, because the border width and padding size are added to the dimensions of the box.

When dealing with static pages, one can deal with this by manually subtracting the border width and padding size from the dimensions, in order to restore the intended 600 x 400 pixel size:
<style type="text/css">
#mydiv {
width: 578px;
height: 378px;
padding: 10px;
border: solid 1px black;
}
</style>
...
<div id="mydiv">My 600 x 400 div</div>
However, in a dynamic page, where the border width and padding size are not fixed, this becomes impossible.
<style type="text/css">
#mydiv {
width: 578px;
height: 378px;
padding: {vb:stylevar mydiv_padding}; /* set to 30px */
border: solid {vb:stylevar mydiv_border.borderWidth} black; /* set to 3px */
}
</style>
...
<div id="mydiv">Oh dear, a 644 x 444 div</div>
In the previous example, the result will not be the intended 600 x 400 box, as the padding size and border widths have been trebled from their original values.

The solution? Style Variable Maths! We can now enter mathematical expressions into our templates in order to resolve this issue and provide precise element dimensions (or positioning, or anything else that might involve numbers) while still respecting the values entered for style variables.
<style type="text/css">
#mydiv {
width: {vb:math 600 - {vb:stylevar mydiv_padding} * 2 - {vb:stylevar mydiv_border.borderWidth} * 2}px;
/* assuming padding = 10, border = 1 -> 600 - 10 * 2 - 1 * 2 = 578 */

height: {vb:math 400 - {vb:stylevar mydiv_padding} * 2 - {vb:stylevar mydiv_border.borderWidth} * 2}px;
/* assuming padding = 10, border = 1 -> 400 - 10 * 2 - 1 * 2 = 378 */

padding: {vb:stylevar mydiv_padding};
border: solid {vb:stylevar mydiv_border.borderWidth} black;
}
</style>
...
<div id="mydiv">My 600 x 400 div</div>
So What Does All This Get Me?

All this wrangling means that there are now three distinct methods to edit the style of a vBulletin 4 installation, depending upon the expertise of the administrator and the degree of customization required.

1) Editing Style Variables

The majority of administrators will not need to venture outside of the safe confines of the style variable editor to customize their sites. Access to colours, fonts, backgrounds, padding etc. can all be found within the style variable editor, and the use of Style Variable Maths in the templates means that (for the most part) administrators are free to change the variables' values as they choose without breaking the layout.

2) Editing CSS Templates

Those administrators with a greater knowledge of CSS may want to delve into the CSS templates in order to make more extreme customization to their style.

One may do this safe in the knowledge that at the worst they could break their layout by editing CSS, but they will not prevent content from being delivered to the browser - all of that is controlled by the HTML, not the CSS.

Further, the administrator no longer has CSS classes force-fed to them by the system. Under vBulletin 3, the .tborder, .thead, .tcat, .alt1 (etc.) classes were hard-coded to exist, and removing them involved code modifications and an abandonment of all style variables. This is no longer the case in vBulletin 4, where administrators may completely rewrite their CSS if they choose to do so, and in the process they may choose to employ all the default style variables in their CSS, ignore a few, or abandon their use completely. It's your choice.

A bonus of this approach is that there should be very few occasions where as CSS template is flagged by an upgrade as 'revert required', because critical data is not stored in these tempates, so there should be no reason to require them to be updated.

3) Editing XHTML Templates

The final method, and the one that will be most familiar to existing customers. Maybe you don't like or don't understand CSS. Maybe you want massive changes to your layout that CSS alone can't deliver. Either way, there is nothing to stop you editing the raw XHTML of the vBulletin templates, just as there has always been.

Except that now there is the three-way-diff template upgrade method, which will attempt to compare your customized templates with their original version from when you customized them and the new version of the default template, and then apply your customizations to the new version...

...which was the subject of a previous blog entry by Mike.

Over And Out

I think most people now know that I am working my last few days here at vBulletin. It's been almost nine years since I was brought into the vBulletin development team and eight since I took over John's role as lead developer and product manager. In that time I've made some great friends both of staff and customers and the decision to leave all of you, and the product to which I have dedicated so many years of my life, was one of the hardest I have ever made.

I will miss vBulletin, its staff and its customers greatly.

Thanks everyone.
- Kier