Data-Driven CSS Style Sheets Using ColdFusion

I was talking to someone earlier about applications that have dynamic, data-driven style sheets so I thought I would just touch on one of the ways that I have accomplished this in the past. Normally, when we have a data-driven style sheet, the data-driven aspect is not the entirety of the style sheet, but rather the look-and-feel portions of it. This often includes things like font family, font size, link color, logo image, background color, etc. - generally, things that let a given application have a "branded" look based on client or subscription or some other variable.

Because the data-driven aspects only contain look-and-feel information, I create my page layout and default styles in some sort of generic style sheet (or collection of style sheets). Then, I link to the dynamic style sheet afterwards so that it can override the default styles of the site. There's a number of ways to do this; you could link to a static style sheet that was previously generated:

<link href="./css/vendor-#vendorID#.css" ... />

... or, you can write the overriding styles directly to the current page request:

<style type="text/css">

<cfoutput>#GetCSSTheme( vendorID )#</cfoutput>

</style>

... or, you can link directly to a ColdFusion file that generates the style sheet at run time:

<link href="./css/theme.cfm?vendor_id=#vendorID#" ... />

Notice that we can pass in meta data to the ColdFusion style sheet URL to help it determine which theme to render. This is the methodology that I am going to demo below:

First, let's take a look at the demo page. As you will see in the following code, the demo page links to two style sheets: my generic one and my themed one (which is a ColdFusion file):

For demonstration purposes, I am passing a Theme ID through the URL so that we can easily switch between the themes. Normally, this would be some sort of SESSION-based variable that gets set when a user logs into an application. You can either pass this variable through the LINK HREF, or you can simply reference it in the target CFM page.

On the server side, this ColdFusion page then takes the given Theme ID and generates a styles sheet to stream back to the client:

<!---

Param the URL theme. This will determine the look and

feel of the style sheet to generate.

--->

<cfparam name="URL.theme" type="numeric" default="1" />

<!--- Tell the client (browser) that this a style sheet. --->

<cfcontent type="text/css" />

<!--- Figure out which style sheet to generate. --->

<cfswitch expression="#URL.theme#">

<cfcase value="1">

<!--- The default theme. No override. --->

</cfcase>

<cfcase value="2">

body {

font-family: arial ;

}

strong {

background-color: gold ;

}

em {

color: #FF0000 ;

}

ul {

list-style-type: circle ;

}

ol {

list-style-type: upper-roman ;

}

</cfcase>

<cfcase value="3">

body {

background-color: #000033 ;

color: #FFFFFF ;

font-family: monospace ;

font-size: 100% ;

}

strong {

background-color: #FFFFFF ;

color: #333333 ;

}

em {

border-bottom: 1px dotted #FFFFFF ;

}

a {

color: gold ;

}

</cfcase>

</cfswitch>

In this demonstration, I am conditionally display CSS rules; this ColdFusion page could, however, be pulling data from a database or even other static files. The method of CSS generation depends on your needs, the traffic of the site, and other performance concerns.

So anyway, that is the basic outline of how I create data-driven style sheets in my applications that require themeing (usually vendor-based). The hardest part is coming up with the right set of CSS rules that will make up the themeing style sheet; you want to allow for good themeing, but not so much that you have to worry about customizing a million different CSS rules.

Reader Comments

It's worth noting that using either the 2md or 3rd methods listed above will prevent the browser from caching your CSS. This means that ColdFusion will be required to generated the CSS each time a page containing that code is requested.

In the 2nd example, this reduces SEO to some degree as the style block is inline on the page.

At Dealerskins, we used to take the 3rd approach, but finally moved away from that, instead generating unique CSS files for each of our websites, each time changes are made in our admin.

We created a method in a CFC which contained the full CSS block, along with any conditionals. When the styles for a site are changed, we save the changes to the database, call the method, and rewrite the CSS.

Those are some really good points. CSS caching can be great and a curse at the same time, depending on what you are trying to do :)

As far as performance goes, obviously, generating a static style sheet is going to be the best as we are just going to be serving up non-ColdFusion files at that point. However, an additional CFM execution can still be quite efficient if you are working off of in-memory data rather than hitting the database each time.

The larger the "theme" CSS, the more likely I am to go with a flat CSS file generated at "update time" as you are referring to with your CFC.

@Adam,

Yeah, definitely, the same technique can be applied to dynamic JS file compilations.

I'd probably do a session var which points to the appropriate style sheet, that way it can be cached (as mentioned above).

This technique is still very useful though - especially for accessibility - being able to have a high contrast style sheet, or a large print version style sheet it a great thing to be able to give users!

@Andy - can you provide some facts to back up your "this reduces SEO to some degree as the style block is inline on the page" claim?

I've heard this said before, but have always chalked it up to urban legend (just like using tables reduce SEO value) because while everyone seems to say it, no one can seem to provide evidence to back it up.

What I think Andy is referring to is simply the fact that you have more "non-content" stuff at the top of the page. If you consider that part of SEO is putting your most relevant information towards the top of the markup, the more inline CSS you have in your HEAD tag, the farther down your "relevant" content is pushed.

Whether or not this actually matters (ie. does the search engine automatically ignore things in the HEAD tag?), I am not sure.

And this method can be good for those quick buttons that say, change this site from red to blue to yellow, etc.

The same problem remains, that your re-writing the css structure-per instance of a theme/profile/site. What happens when you have more then 3 small themes? maybe 2000 full website themes, and you're forced to change or update you mark-up.

That won or can't scale when you're the one managing all of the css themes, for each new site created with the app. When I add or change the mark-up, I don't wanna be forced, or force my users to modify what they have going. (I'm trying to think both users that are and aren't css designers)

For you to have a really strong mark-up that allows for updating and adding to the mark-up as the app grows. I can't go and add #newCssID to everyone's css file, it would take for ever. I've done it a few times, and I'm only at 4 or 5 sites right now, lol.

There has to be a way to create one main Css structure. Think Object-Oriented, Polymorphic, Normalized Css.

Just a thought, maybe you should consider putting the elements that change in a separate style so that you're swapping out only the changes during the different times of the day. I'm not a css expert by any means, but on a project that we worked on a couple years ago we did something different with the times of the day the theme would change. Our css/html guy created a separate file for the changes and we swapped it out dynamically, we also did cache the files so that they are not recreated.

I worked on a site several years ago that was basically a single code base with hundreds of "clients" that had their own CSS / images for the site. From what I remember, the way they did it was that the CSS look and feel attributes (color, font, border colors) were stored in a database - one record per client. This was administered via some admin where you could organize client branding. Every time branding was updated, a CSS file was generated and saved to file in the given client directory.

It scaled quite nicely because you only work with look / feel which means the primary style sheet can be updated, no problems. The trick was to generate a CSS file each time you update a given client.

@Leigh,

I second Hatem's suggestions. If you had like:

styles_morning.cssstyles_night.css

You could simply but some logic in the HEAD to include one based on time.

Also, sometimes, if the CSS changes are small enough for the different overrides, I simply compress them (remote white space) and include them directly in the HEAD tag in a new STYLE tag. If its small enough, it will load faster than a subsequent call to the browser (in my experience).

I've only done this with PHP but I assume it's possible with CF... why not set up a dynamic page for the stylesheet... this can go get all the other stylesheets (reset, layout, typography etc) then append them with styles from a database, compress them (eg remove unneeded white space, shorted colours from #aabbcc to #abc etc), even gzip them and then output them to the browser after sending appropriate caching headers.

If you really wanted you could process all the styles and remove any that were overridden.

You can even use the link '/dynamicstyles.cfm?3456788987'... eg a 'last modified' timestamp on the end or something which will prevent it from being cached by the browser or ISP.

A similar php version here... http://rakaz.nl/item/make_your_pages_load_faster_by_combining_and_compressing_javascript_and_css_files

By the way, as I type, this box keeps getting longer... every character makes it grow, it's now easily 50x the height of all the text I've typed.

What browser are you using? I've been told that happens with really old versions of FireFox, but even when I download portable versions of FireFox, I cannot duplicate the box growing issue?

Yeah, we can definitely combine the styles sheets. My only concern with appending the "custom" CSS to that is that if you have a bunch of clients with customized CSS, you would have to burn a copy of each compiled version for them. That's not a real problem, so long as you have the architecture for it.

A search engine usually only checks a page up to a certain number of bytes. Therefore, if you have a lot going on at the top of your page that isn't actually important content, then it could be blocking real content from getting looked at.

This being said however, I think that the number of bytes is still very large and will be able to satisfy most of your needs.

I like this post, and will read it more in-depth later. This is something I have been looking for for awhile...something similar to this. Thanks, @Evik James, for commenting on it and bringing it to the top of the recently commented list. I appreciate that. I'm busy writing some code now for our site that needs to go live soon, but once I get the chance, I'll be able to search for this and read over it in a little more detail. Thanks!!! (I have so much trouble sometimes with css...this might help)

I had included CSS file in my cfml code as:<head><link rel="stylesheet" type="text/css" href="test.css" /></head>but the effect of this test.css is not getting reflected in WebPage when i call it from different section in the same program..

I am the co-founder and lead engineer at InVision App, Inc — the world's leading prototyping,
collaboration & workflow platform. I also rock out in JavaScript and ColdFusion 24x7 and I dream about
promise resolving asynchronously.