Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

JVM Languages

Cascading Style Sheets & JavaServer Faces


July, 2005: Cascading Style Sheets & JavaServer Faces

Tor is a senior staff engineer at Sun Microsystems responsible for writing the visual web page designer for Sun Java Studio Creator. Previously, he worked on Sun's C/C++ debugger and emacs integration. He can be contacted at http://blogs.sun .com/tor/.


JavaServer Faces (JSF) technology is a Java standard web technology that makes it easy to create web applications. Cascading Style Sheets (CSS) is a W3C technology that has been around for some time, but has recently gained momentum because modern browsers now support it.

JSF has support for CSS, which provides synergy between the two technologies (http://java.sun.com/j2ee/javaserverfaces/). In this article, I describe the hooks for CSS built into JSF, which lets you easily control the visual appearance of your JSF web applications.

Style Sheets

In the Bad Old Days, HTML pages contained both the actual text content of the page, as well as all kinds of formatting, color, and font settings, using the <font> tag, bgcolor attribute, and so on. This made it really hard to maintain the pages if the visual style of the site needed to change. It also made it hard for users to override the font and color choices to display a larger font size, and so on.

CSS lets you move all style information out from the page and into a separate style sheet. In addition to removing the maintenance burden, it offers faster page downloads (because style sheets can be cached by browsers and are typically shared for a number of pages), and the style-sheet language makes it easier to express global style preferences. For example, rather than having to add a <font size="+2"> tag around every heading in your document to make headings larger, you can write a single style rule that applies this change globally.

Style sheets are made up of sets of rules, where each rule has a selector and a set of style definitions. The selectors identify elements in the document that the corresponding style definitions should be applied to.

For example, say you have this style sheet:

li { background-color: red }
#loginButton { width: 45px }
.number { text-align: right }

which has three rules, each with different types of selectors. The first rule selects any elements where the element name is li, so the rule will assign a red background color to all <li> elements, or in other words, HTML list items.

The second selector matches any elements that have an id attribute matching the text following the #, so if you have:

<input id="loginButton" type=
"submit" value="Login"/>

it will be assigned a width of 30px.

Class Selectors

The third selector is a style class selector. This type of selector is used heavily by JSF. The style class selector matches any elements where the class attribute in the element contains the string following the dot. The aforementioned rule means that any elements associated with the number class will have their text right-justified.

There are many other types of selectors, such as selectors that apply when the user moves the pointer over a visited hyperlink and so on, and these are described in the CSS documentation (http://www.w3 .org/TR/CSS21/). But style class selectors play a special role in JSF.

The essential concept with style classes is that you get to identify style groups and associate your components with these groups. For example, you may want to style all negative numbers in red, or all recently changed fields in a boldface font, or as just shown, all numbers in text fields aligned to the right. You define these style classes in the style sheet along with the colors, fonts, alignments, and so on to be applied for each class. In documents using these style sheets, you only identify which style class to associate with the different elements, not what the actual styles are.

All the standard JSF components have a styleClass property. This styleClass property lets you set the name of a style class you want applied to your component. The styleClass property value will end up as a class attribute in the HTML page rendered for the JSF page. Thus, if you create a JSF InputText component (a text field), and set its styleClass property to number, the text in the text field will be right-justified. Note that there is no dot in the style class name here, but there is one in the selector in the style sheet. The dot in the style sheet tells CSS that the following identifier is a style class selector, instead of matching an element name like the first rule. JSF components can belong to multiple style classes. The styleClass property of a JSF component is not limited to just identifying one style class; it can reference many by listing them all separated by spaces.

For example, if you set the styleClass property of your InputText component to "number alert changed," this will apply the merged styles "number," "negative," and "changed." The text will be red, bold, and right-justified.

If multiple style classes set the same style properties, such as the background color, then the last one generally wins. However, the rules are much more complicated than that. Recall that the first "C" in "CSS" stands for "Cascading." The cascade defines the selection of style values by taking into consideration rule specificity, rule order, importance requests, the element hierarchy, and other factors.

Style Class Lists

To this point, everything I have discussed is standard CSS and HTML behavior, since the styleClass attribute in JSF just renders to the HTML class attribute, which behaves as previously described. However, JSF adds a new concept, which makes CSS even more useful—style class lists.

Some JSF components have special properties that can take a "style class list." A style class list property has a comma-separated list of style classes. When the JSF component is rendered, it will assign one style after another from the style class list to the content being rendered. For example, the PanelGrid component, a layout component that renders its children on successive rows, has a rowClasses property, which is a style class list. When it renders the first row, it assigns the first style in the class list to the row. The second row will then use the second style, and so on. This makes it easy to create a "striped table background." You create two CSS styles as follows:

.odd { background-color: gray }
.even { background-color: white }

Then set the rowClasses property to "odd, even." Now the first row will have style class odd applied to it and turn gray, while the second row will have style class even with a white background. The third row will force the component to cycle around to the beginning of the style class list and use odd again, and so on.

Multiple Style Properties

Some JSF components have multiple style properties, each one for a different portion of the component. The JSF Data Table, for example, has a headerClass style property, which lets you set style classes that apply only to the header row. A footerClass style property applies to the table footer. Then there is a rowClasses property, which behaves the same way as the rowClasses property for the PanelGrid discussed earlier. It also has a columnClasses property, which lets you assign style classes to successive columns in the table. In this way you can, for example, set up a three-column data table to have varying width and text alignments with columnClasses="col1,col2,col3" and this style sheet:

.col1 { width: 30%; text-align: right }
.col2 { width: 50%; text-align: center }
.col3 { width: 20%; text-align: left }

Note also that style class lists can contain multiple style classes per list item; for example, "number changed, number number, number alert, number changed."

As another example of the principle of multiple style properties, a calendar component can have a currentDayStyle, which specifies a CSS style to be used to render the calendar cell for the current day; it can have a selectedDayStyle for the currently selected date, it can have a nextMonthButtonStyle for the month iterator button, and so on. This lets the developer using the calendar component map the component to specific styles in the style sheet that work well with the rest of the color scheme used for the web application. This makes it possible to avoid hard coding colors in the JSF markup of JSF components.

Value-Bound Style Classes

JSF has a concept of "value binding," where you can use Expression Language statements in your property values. These are evaluated on the server at runtime and the result substituted into the generated HTML. These expressions can perform method calls as well. Combining this with style classes and style class lists allows some simple, but powerful, "dynamic" styles.

For example, say you want to show a different background color in your grid panel component depending on the current season—light blue for winter, light green for spring, and so on.

First create the seasonal styles in your style sheet:

.winter { background-color:
#9999ff; color: #ffffff }
.spring { background-color:
#99ff99; color: #ffffff }
.summer { background-color:
#77cc77; color: #000000 }
.fall { background-color:
#eeee77; color: #000000 }

Next, create a method in one of your JSF-managed beans to return the right style class to use (see Listing One). Note that the method needs to be a standard JavaBeans property: It needs to be public, take no arguments, and follow the "get" name pattern.

Now you just need to bind the styleClass property for the component to the aforementioned method. You can do this by setting the styleClass property to "#{Page1.seasonStyle}":

<h:panelGrid styleClass="#{Page1.seasonStyle}">
...

Instead of an actual style class name, you are now using a method-binding expression that will be evaluated by the server. The result ending up in the HTML page will be the return value from our method assigned to the HTML class attribute.

In the method-binding expression, Page1 is the managed JSF bean you added the method to, and seasonStyle is the property added to the page. Note that you are not using the method name (getSeasonStyle)—you are using the JavaBeans property name. The expression language resolver in JSF will use reflection to find the right method from the property name by searching for a public, no-argument method named "get"-property or "is"-property.

Advanced Value-Bound Style Classes

The style property methods in the managed beans can be coupled even more tightly to the components. Whereas the season style just described does not depend on anything in the JSF page, imagine that we have a JSF Data Table, with an Output Text component showing names in a database. If you want to highlight any names beginning with the letter "A," you can bind the styleClass property to a method like Listing Two. Here, the trick is that the Java code can also perform expression language evaluations, and you can examine the rowset being rendered in the data table. In particular, you can look at other columns and decide which style you want to generate based on the current row's values.

In summary, while CSS provides clean separation of styles from content and JSF provides a solid web application programming model, the combination of the two technologies creates a synergy where Hard Things are Simple. With the expression language binding to style classes and lists, you essentially get to attach Java code to your style sheets to create conditional and iterative style effects.

DDJ



Listing One

public String getSeasonStyle() {
// For instructional purposes only -- my hometown has winter WAY longer than 
// this... and this won't work for the southern hemisphere
int month = calendar.get(Calendar.MONTH);
if (month <= Calendar.FEBRUARY || month >= Calendar.DECEMBER) {
   return "winter";
      } else if (month < Calendar.JUNE) {
   return "spring";
      } else if (month < Calendar.SEPTEMBER) {
   return "summer";
}  else {
      return "fall";
   }
}
private static Calendar calendar = Calendar.getInstance();
Back to article


Listing Two
public String getNameStyle() {
String s = String.valueOf(getValue("#{currentRow['NAME']}"));
if (s != null && s.startsWith("A")) {
   return "highlighted";
      } else {
   return "normal";
   }
}
protected Object getValue(String expr) {
FacesContext context = FacesContext.getCurrentInstance();
Application app = context.getApplication();
ValueBinding vb = app.createValueBinding(expr);
   return (vb.getValue(context));
}
Back to article


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.