Creating a Richfaces skin
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.
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):
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:
Note that you are free to define new, previously unknown properties in your skin.properties file and use them in your xcss files.