Introduction

This tutorial describes how to make a skin for the JSF library Richfaces. It involves writing a skin.properties file and explains how to write and use a Richfaces xcss file that skins non-Richfaces components as well. It assumes the reader is familiar with Richfaces.

What is a Richfaces Skin?

In many web applications, the same color often reoccurs in the css style file(s) associated with the app. The same color might be used for the panel header color, for the background color of the menu and as a general background color in a certain part of the page. Css has no way to define a particular color in an abstract way. So if you want to change a particular color, you have to change this color in all these different places, otherwise your interface might appear clumsy. The more interface elements there are, the more of this incredibly happy copy-paste activity needs to be done.

The Richfaces framework solves this problem by providing developers with a skinnability system. Every skin defines a collection of properties which together define an application palette. By changing one of these properties, you can alter the appearance of interrelated components at once and keep user interface consistency at max.

These skins are still all css under the hood. What happens is that Richfaces adds dynamic css stylesheet references to the head part of your webpage, that are generated by the server when the browser resolves those references, obviously taking the properties of the chosen skin into account. The skins do not completely replace standard css. They just provide a high-level extension of css that can be used with regular css declarations.

*.skin.properties files

Richfaces ships with quite a few built-in skins, like classic, emeraldTown and blueSky.
To define which skin you want to use for a particular application/module, you define it in your web.xml like this:

<context-param>
	<param-name>org.richfaces.SKIN</param-name>
	<param-value>emeraldTown</param-value>
</context-param>

There are other, more dynamic options, for if you want to change the skin at runtime, but these are outside the scope of this article.

All these built-in skins are defined in the richfaces-impl-x.x.x.jar, in its META-INF/skins directory. When taking a look there, you will find files like classic.skin.properties, emeraldTown.skin.properties and blueSky.skin.properties. Richfaces skins are defined in these simple property files.

Adding a skin is as simple as adding a new file like this to one of the two locations on the classpath that are scanned for skins: META-INF/skins or WEB-INF/classes.
When developing a skin for future use in your/some company, you should probably package it in a jar, but for testing purposes, you can just add a META-INF/skins folder to one of the source folders of your project(in Maven projects, the typical location would be src/main/resources/META-INF/skins) and add the following forest.skin.properties file there:

headerBackgroundColor=#858d6e
headerGradientColor=#858d6e
headerTextColor=#edeeea
headerWeightFont=bold
generalBackgroundColor=#edeeea
generalTextColor=#2f3122
generalSizeFont=12px
generalFamilyFont=arial, Arial, Helvetica, sans-serif
controlTextColor=#edeeea
controlBackgroundColor=#858d6e
additionalBackgroundColor=#b9beac
shadowBackgroundColor=#ffffff
shadowOpacity=1
panelBorderColor=#858d6e
subBorderColor=#2f3122
tabBackgroundColor=#b9beac
tabDisabledTextColor=#edeeea
trimColor=#edeeea
tipBackgroundColor=#b9beac
tipBorderColor=#edeeea
selectControlColor=#b9beac
generalLinkColor=#edeeea
hoverLinkColor=#edeeea
visitedLinkColor=#2f3122
headerSizeFont=12px
headerFamilyFont=arial, Arial, Helvetica, sans-serif
tabSizeFont=12
tabFamilyFont=arial, Arial, Helvetica, sans-serif
buttonSizeFont=12
buttonFamilyFont=arial, Arial, Helvetica, sans-serif
tableBackgroundColor=#b9beac
tableFooterBackgroundColor=#cccccc
tableSubfooterBackgroundColor=#f1f1f1
tableBorderColor=#C0C0C0
tableBorderWidth=1px
calendarWeekBackgroundColor=#F5F5F5
calendarHolidaysBackgroundColor=#FFEBDA
calendarHolidaysTextColor=#FF7800
calendarCurrentBackgroundColor=#FF7800
calendarCurrentTextColor=#FFEBDA
calendarSpecBackgroundColor=#E4F5E2
calendarSpecTextColor=#000000
warningColor=#FFE6E6
warningBackgroundColor=#FF0000
editorBackgroundColor=#F1F1F1
editBackgroundColor=#FEFFDA
gradientType=plain

That’s it. You can now define

<context-param>
	<param-name>org.richfaces.SKIN</param-name>
	<param-value>forest</param-value>
</context-param>

in your web.xml and your new forest skin will be immediately applied to all your richfaces components.

If you take a look at the above skin.properties file, these properties dont ring a bell for most of us. Some of them are more or less obvious. generalBackgroundColor is the background that will be used in the body of most components, in a panel for example, while generalTextColor is the color of the text there. All of these properties are used by different components too. headerBackgroundColor for example is used by panel headers, datatable headers and even for menu items.
Which components are affected by which skin property, can be looked up in the Richfaces Developer Guide. All skin bindings are mentioned in that document.

Using xcss files

Richfaces skins are applied to your Richfaces components, like rich:panel, rich:dataTable and rich:toolBar. The skin will not be applied to other parts of your page. For example, plain xhtml parts like a div with id header(<div id=”header”>), a seam div(s:div), standard jsf components(h:commandButton) or components from some other jsf component library such as Primefaces, will all be unaffected by the given Richfaces skin.

To apply our skin properties to these elements as well, you will need to use the exact same system Richfaces uses internally: xcss.

Imagine that the first element in the body part of our webpage is a div with id “header”. Imagine that we always want to skin this div the same way we skin panel and table headers. What we need is to be able to make use of the headerBackgroundColor of our skin. With xcss we can easily do that:

<?xml version="1.0" encoding="UTF-8"?>
<f:template xmlns:f="http:/jsf.exadel.com/template" xmlns:u="http://jsf.exadel.com/template/util" xmlns="http://www.w3.org/1999/xhtml" >
<u:selector name="#header">
	<u:style name="background-color" skin="headerBackgroundColor"/>
</u:selector>
</f:template>

This xcss file sets the background-color css property of the #header css selector to the value of headerBackgroundColor of our skin, which is exactly what we want. If we switch from classic to emeraldTown to blueSky to our own skin forest, the background of the header div will always change together with the color of all the Richfaces components, all according to the chosen skin.

To apply the xcss to a page though, we first have to add the following ajax4jsf tag to our xhtml (template) file(s):

<a4j:loadStyle src="resource://xcss/test.xcss"/>

Ofcourse, in the above example, xcss/test.xcss has to be on the classpath.

This will make sure an additional dynamicly generated css link is added to the head part of your page, which in this case will contain something like:

#header{background-color: --value-of-headerBackgroundColor-property-of-your-skin--}

Note that you are free to define new, previously unknown properties in your skin.properties file and use them in your xcss files.

Note: It is not true that to apply a Richfaces skin to non-Richfaces components, you need to use xcss. I think xcss is the most flexible and cleanest option, but there are other options as well. Some of these are quite limited, like applying the css class rich-container to a particular html element(the skin will be applied in a general way to all of its subelements), while others do not cleanly seperate style and content. For example, the properties of the skin are accessible through the “richSkin” bean. You could skin our header the same way we did with xcss by changing

<div id="header">

into

<div id="header" style="#{richSkin.headerBackgroundColor}">

Which puts style information right where you dont want it.