Leverage the powerful capabilities of CSS that are already built into the Adobe® Flex™ framework. This article provides the information you need to start using CSS in Flex, and then provides tips and techniques to speed up your workflow when designing and developing user interfaces with Flex.

Dan Orlando, Software Architect, Vision Media Group

Photo of Dan OrlandoDan Orlando is a software architect specializing in rich client-server applications that involve Flex, AIR, and ActionScript on the client. He works with a variety of Web service protocols and server-side languages. Dan is co-founder of Vision Media Group, the makers of Avijax, and also serves as a senior UI developer on the (RED)WIRE team. You can reach Dan at dan@vizmarketing.com.



07 July 2009

Also available in Chinese Japanese

One of the most powerful features of Flex is the vast amount of design flexibility it contains. This flexibility is largely the result of Adobe's implementation of CSS with Flex. For instance, while recently serving as senior UI developer for a new Adobe AIR™ application, I received a number of design change requests days before officially launching the first public release to 160,000 people worldwide. Although many developers might have considered these last-minute requests an atrocity, I had the changes completed and checked into version control in less than 20 minutes, thanks to the power of Flex and CSS.

Frequently used acronyms

  • UI: User interface
  • W3C: World Wide Web Consortium

I look at the use of CSS with Flex as a form of leverage in UI development. There are certain inevitabilities I've learned to expect and prepare for through my experience in UI development. One such inevitability is that regardless of how much planning you do beforehand, both the design and the functional requirements of the project will change and will change often throughout the development life cycle. It's a rule of the game when developing large-scale applications in a team-based environment, and the best way to play a winning game is to anticipate the moves of all the players involved, and then position yourself accordingly in advance. When you learn how to master this development technique, you're always in the lead, and hitting a moving target becomes a lot easier. For this reason, I enjoy developing with Flex, because Flex features like CSS integration give you the power to do exactly that.

My goal is that by the time you finish reading this article, you too will be able to leverage the powerful capabilities of CSS with Flex and play a winning game as a master Flex UI developer. If you're already an avid user of Flex, then my hope is that you will learn new techniques for utilizing CSS with Flex—particularly with enterprise-level applications.

Why use CSS?

Most object-oriented design patterns keep the design logic separate from behavioral functionality. Because Adobe ActionScript™ is an object-oriented language, it only makes sense to remain consistent with these object-oriented programming (OOP) conventions. The benefits of doing so include flexibility, keeping maintenance of the application easy as it grows, code reuse, and better performance.

In the world of Web design, CSS is a standard for encapsulating the code that makes up the design of a Web site. Given the power and maturity of CSS, most experienced Web designers strive to implement as much of the design and layout properties of a Web site in CSS as possible. The result is much greater control and flexibility over the look and feel of the site. CSS gained most of its popularity three or four years ago when Web developers began to realize that when the design of a Web site is independent of the site's behavioral functionalities, the design can be easily modified without the risk of breaking or otherwise negatively affecting the site's behavioral code. This is what propelled the rapid growth of templates, skinning, and re-skinning the same code base. For example, I'm an avid user of WordPress for my blog Web site. There are tens of thousands of people who use this same open source code base to power their blog site, and yet many times, you will stumble upon a site built on WordPress and you wouldn't even know it thanks to its impressive separation of code from design through the use of CSS.


CSS in Flex

First and foremost, for those of you coming from a Web design background, it's important to understand that Flex CSS does not follow the same conventions as the W3C CSS spec. The hyphen (-) used to separate words in the W3C CSS Version 2.0 specification isn't used as part of the code convention in the Flex implementation. Instead, the Flex implementation of CSS uses camel case. For example, vertical-center in the W3C CSS2 spec is equivalent to verticalCenter in Flex CSS. If you're already programming in a language that uses camel case, however, this is pretty easy to get used to. The good news is that most of what's available in the CSS 2.0 specification is also available with the Flex CSS implementation. Furthermore, the Flex implementation of CSS expands significantly on the CSS 2.0 W3C standard, offering additional style properties that are unique to the Flex components.


Maintaining styles: Component versus style properties

Before you begin creating Flex CSS style sheets, I recommend that you first consider how you want your styles implemented. For the sake of simplicity, I show you four basic methods of declaring a style:

  • Through a component's class name. You can set a style on a component by using the component's class name as the style name:
    TitleWindow {
       borderColor: #f7f7f7;
       borderAlpha: 1;
       borderThicknessLeft: 0;
       borderThicknessTop: 0;
       borderThicknessBottom: 0;
       borderThicknessRight: 0;
       cornerRadius: 0;
       headerHeight: 0;
       highlightAlphas: 1, 1;
       headerColors: #f7f7f7, #f7f7f7;
       footerColors: #f7f7f7, #f7f7f7;
       backgroundColor: #f7f7f7;
       dropShadowEnabled: true;
    }
  • Through a unique style name. You can declare styles using a unique style name. Just be sure to put a dot in front of the name and use the camel case convention:
    .altText
    {
    	fontFamily: TVNordEFCEOP-RegularCon;
    	fontSize: 18;
    	color: #FFFFFF;
    }
  • Through a component plus a style name. You can also set a style name on a component when you need to have multiple designs for the same component, which is common for applications that have multiple view states. This method also ensures that only the specified component can have that particular style assigned to it:
    Text.bigYellowText
    {
    	color:#EFB526;
    	fontSize:36;
    	fontWeight:Bold;
    }
  • Through the global selector. The global selector is a special kind of selector that affects every component within the application that contains the properties set inside it. For example, I could set the cornerRadius style property of all of my display object components that contain a cornerRadius style property to a setting of 4, like so:
    global
    {
    	cornerRadius: 4;	
    }

Style precedence

Although the global selector basically sets a default value of a property, that value is easily overridden. For instance, if I set the cornerRadius property of the Button component to 0 either inline or in my CSS file, it will take precedence over the global default setting of 4 that I have also specified; thus, all my Button components will contain a cornerRadius value of 0. Furthermore, I can override both the global setting of 4and the Button setting of 0 by creating an additional style:

Button.altCornersButton
{
	cornerRadius: 8;	
}

Applying styles in Flex

The method of CSS implementation with Flex you choose must be based on the situation and the environment. It's important to look at the application you're designing from the conceptual 50,000-foot view when considering your options for design implementation. The following methods are the most common for using CSS with Flex.

Setting styles on an instance (inline)

Flex components that extend the Flex UIComponent base class allow you to set common styles as properties inline—in other words, within the MXML component declaration tag (see Listing 1). The layout properties of a display object are often unique to that object, so it's common to see any one of the following properties set explicitly on a component: x, y, height, width, top, right, left, bottom, horizontalCenter, verticalCenter, horizontalAlign, and verticalAlign.

Listing 1. Setting styles as properties of a component instance with MXML
<mx:Button id="volumeIcon" cornerRadius="0" alpha="0.9"
	verticalCenter="0" enabled="true" toolTip="Volume Control"
	click="toggleVolumeControl();" />

Listing 1 exhibits a functional example of setting style properties that are unique to the specific instance of the Button component with an id value of volumeIcon. Because I know that this is the only button that will require these particular style values, I have explicitly set the cornerRadius, alpha, and verticalCenter of this particular button.

As a good rule of thumb when setting style properties on an MXML component tag, only set the property this way when you know that the particular property value you're setting is specific to that component. For instance, say your application requires a container that vertically stacks display objects but without any gap in between. At the same time, you know that other VBox containers in the application do need to have some spacing between the display objects. In this type of situation, you should explicitly set the verticalGap property on that instance of the VBox component, as shown in Listing 2.

Listing 2. The verticalGap is explicitly set to 0 on this instance of the VBox container component
<mx:VBox id="myVBox" verticalGap="0" 
	x="15" y="15" width="100%" height="100%">
		
(...)
		
</mx:VBox>

Embedding CSS in MXML

This method involves embedding styles or assets directly into an MXML file with the <mx:Style/> tag. For all practical purposes, there are few instances in which directly embedding style information into an MXML file makes sense. It's important to recognize that as the application grows, the design will become increasingly difficult to maintain if the application contains a lot of embedded CSS. With that in mind, be conservative with this method, and only use it when necessary. Listing 3 provides an example of an embedded style declaration that really should be held within an external CSS file for greater code maintainability.

Listing 3. Embedding styles directly within the MXML application file
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication 
	xmlns:mx="http://www.adobe.com/2006/mxml"
	layout="absolute"
	showFlexChrome="false"
	borderStyle="none" 
	keyUp="{this.onKeyStrokeEvent(event);}">
	
	
	<mx:Style>
		.bGroup {
			borderSides:"left,bottom,right";
			borderStyle:"solid";
			borderColor:#6d6f71;
			borderLeftThickness:3;
			borderRightThickness:3;
			borderBottomThickness:1;
			dividerColor:#6d6f71;
			dividerThickness:3;
		}
	</mx:Style>
	
	<mx:Script>
		<![CDATA[ 
			
			(...)

However, that's not to say that it will never happen. Listing 4 is a scaled-down component I built for one of my applications that's based on the Flex AplicationControlBar. In the design provided, each button in the control bar was actually just a single word of text and looked more like a link than a button. Additionally, all the one-word links had a small bullet separator between them. Because I had the design for the full application already, I knew this bullet separator was unique to the application's main control bar and did not appear anywhere else. Most importantly, because the bullet appeared several times within the same component, it made perfect sense to embed the image as its own private class within the MXML file so that I could bind to it from each image control I placed between the links. Otherwise, I would have ended up with multiple instances of the same image being created, which is nothing more than a waste of system resources.

Listing 4. Embed an image directly
<?xml version="1.0" encoding="utf-8"?>
<mx:ApplicationControlBar xmlns:mx="http://www.adobe.com/2006/mxml">

 <mx:Script>
        <![CDATA[
        	
            [Embed(source="assets/bullet_black.png")]
            [Bindable]
            private var bullet:Class;            
            
        ]]>
    </mx:Script>

	<mx:HBox x="10" y="10" id="hbox" horizontalGap="10" width="350">
		<mx:LinkButton label="Help" styleName="appBarButton"/>
		<mx:Image source="{bullet}" />
		<mx:LinkButton label="About" styleName="appBarButton"/>
		<mx:Image source="{bullet}" />
		<mx:LinkButton label="Minimize" styleName="appBarButton" />
		<mx:Image source="{bullet}" />
		<mx:LinkButton label="Quit" styleName="appBarButton"/>
	</mx:HBox>
</mx:ApplicationControlBar>

External style sheets

A Flex or AIR application has a single MXML file at the root of the source code directory that is based on either the Application class (Flex) or the WindowedApplication class (AIR). This is the default MXML application file that starts with either the <mx:Application/> or <mx:WindowedApplication/>. The application's style sheet source should immediately follow the declaration of the application's base class (see Listing 5).

Listing 5. Declaring style sheets in any other file except your main application MXML file results in errors
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication 
	xmlns:mx="http://www.adobe.com/2006/mxml"
	layout="absolute"
	showFlexChrome="false"
	dropShadowEnabled="false" 
	borderStyle="none" 
	applicationComplete="{this.appInit(event);}"
	>
	
	<mx:Style source="com/passalong/assets/RED_SKIN_MAIN.css"/>
	
	<mx:Script>
		<![CDATA[
			...

The easiest and safest way to maintain an application's style settings is by using external style sheets. In fact, you could reasonably maintain all the styles of a large application from a single CSS file. I choose to use only one CSS file for two reasons: First, I always know where to find my style settings; second, it makes finding styles easy for other developers when working in a team environment. Additionally, it's good practice to keep this file well organized, because as the application grows, your CSS file will inevitably grow, as well.

When building your main application CSS file, it's generally good practice to place your default component style declarations first. For instance, if you want all your tooltips to look the same throughout your application, use ToolTip as the name of the style and place it toward the beginning of the file. I tend to place a tooltip on just about anything I can in my applications to make the application as user friendly as possible. Therefore, the tooltip component shows up in my applications more than probably any other component. Because your default component styles have the greatest impact on the overall look and feel of your application, you need to have quick and easy access to them. This is why it's usually a good idea to place those styles first.

Keep in mind that in most applications, you won't be able to get away with just creating a default style for each component and calling it a day. The Button component is a good example of this. Similarly, to keep your CSS code tidy, consider grouping component style subsets. For instance, a design with three alternate button styles called Button.musicPlayerPlay, Button.pageDown, and Button.backToMenu would be placed one after the other in the style sheet and separated by comments from other style groupings.


Using getStyle() and setStyle()

All components derived from the UIComponent base class inherit two methods: getStyle() and setStyle(). These two methods provide an incredible amount of flexibility to the developer, especially for programmatic skinning. Although covering all the possible uses of this functionality is beyond the scope of this article, I show you a couple of very different uses to demonstrate the power behind the functionality. When using this functionality in ActionScript code, a call to getStyle is needed for each call to setStyle and vice-versa.

Listing 6 shows how to use the two methods to skin the task bar buttons when a window enters a minimized state.

Listing 6. Skin the task bar buttons when the window is minimized
private function toMinimized():void {
	   TaskBarManager.addToTaskBar(this);
	   pushStateProperties(stateMin, x, y, 200, titleBar.height, NaN, NaN);
	        
	   minimizeButton.setStyle("upSkin", getStyle("restoreButtonUpSkin"));
	   minimizeButton.setStyle("disabledSkin", getStyle("restoreButtonDisabledSkin"));
	   minimizeButton.setStyle("downSkin", getStyle("restoreButtonDownSkin"));
	   minimizeButton.setStyle("OverSkin", getStyle("restoreButtonOverSkin"));
	        
	   maximizeButton.setStyle("upSkin", getStyle("maximizeButtonUpSkin"));
	   maximizeButton.setStyle("disabledSkin", 
	        getStyle("maximizeButtonDisabledSkin"));
	   maximizeButton.setStyle("downSkin", getStyle("maximizeButtonDownSkin"));
	   maximizeButton.setStyle("OverSkin", getStyle("maximizeButtonOverSkin"));
	        
	   dispatchEvent(new Event("minimize"));
}

The toMinimized method in Listing 6 is taken from a custom component that extends the Flex Panel class. This component gives the appearance of a new window within the application that a user can minimize so that only the title bar shows (in case the user has to access something behind it). The cool thing about it is that when the window is in the minimized state, the Minimize button is re-skinned on the fly using the getStyle and setStyle methods, which turn the button into a Restore button and set the new state for the maximize button skin. Essentially, I'm reusing the same instance of a class by creating a sort of toggle switch, which conserves system resources.

The setStyle method is also conveniently available through MXML using the syntax:

<mx:SetStyle name=”styleNameAsString” value=”newStyleValue” />

When setStyle is called through MXML, it automatically makes the getStyle call for you, so you don't have to worry about getting that style's current property to reset it. As you can see in Listing 7, where I'm setting a new background image when the state of the application is changed, this method is especially handy for applications that use a stateful design pattern.

Listing 7. Calling setStyle in MXML
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
	layout="absolute"
	creationComplete="init()">
	
	<mx:states>
		<mx:State name="MyLibraryState">
			<mx:AddChild position="firstChild">
				<comp:CollectionsLibrary height="100%" width="100%" 
					horizontalCenter="0" verticalCenter="0">
				</comp:CollectionsLibrary>
			</mx:AddChild>
			<mx:SetStyle name="backgroundImage"
				value="@Embed(source='com/passalong/assets/
				          my_collections_background.png')" />
			<mx:SetProperty target="{vbox1}" name="y" value="442.95"/>
		</mx:State>
	</mx:states>
	(…)

Run time CSS

An interesting feature in Flex Version 3 is that you can compile a CSS file as an SWF file and load it at run time. Using this feature, you could allow users to change the look and feel of your application based on their personal preferences. You may have seen this type of functionality used on social media Web sites, where JavaScript™ code is used to swap CSS files when users select a new design view.Compile style sheet to load at run time.

Not surprisingly, accomplishing this task is easy in Flex. Simply create a new CSS file, place your CSS style selectors in it, and save the file. Then, in the Flex navigator panel (the upper left pane when in Flex Development mode), right-click the CSS file you just created, and then click Compile CSS to SWF.

The StyleManager class

After you have created and compiled all the style sheets you want to use in your application to separate SWF files, use the Flex StyleManager class to easily switch between style sheets, as shown in Listing 8.

Listing 8. Use the StyleManager class to load precompiled style sheets at run time
private function loadFirstStyleSheet():void {
	StyleManager.loadStyleDeclarations("CSS1.swf");
}
		
private function loadSecondStyleSheet():void {
	StyleManager.loadStyleDeclarations("CSS2.swf");
}

Computational expense

One important element to take into consideration when loading precompiled style sheets at run time is the load that you're putting on the user's system as a result. You should use this method of design implementation conservatively and with extreme caution, as doing a lot of it will quickly degrade the performance of your application because of a lack of available system resources.

Themes and skinning

One thing I have always appreciated about Adobe is its focus on bridging the gap between the tools it offers in an effort to streamline and speed up the design and development workflow. As a matter of fact, my favorite part about designing Flex UIs is being able to jump back and forth between the Adobe applications Flex, Illustrator®, Flash®, Photoshop®, and Fireworks®—depending on what I'm trying to accomplish. The ability to do this effectively results in a "regular designer" quickly becoming a "power designer." The Adobe Developer Connection has several great articles that expand on this topic (see Resources).


Conclusion

This article has shown you quite a few methods and techniques for implementing CSS with Flex applications. Yet, I haven't even begun to tap into the design capabilities built into Flex and AIR—particularly with regard to creating and implementing skins, which also involves extensive use of CSS. Additionally, although this article should do a fine job of getting you started, I strongly recommend you continue your research on using CSS with Flex when developing custom components. That said, when you have completed your research on Flex and CSS and feel like you have a solid understanding of the topic, I challenge you to develop a custom component that extends the UIComponent class and make it completely scalable and customizable so that others can use your component.

Resources

Learn

Get products and technologies

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Web development on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=406964
ArticleTitle=Discover the power of Flex and CSS
publish-date=07072009