First, I would suggest using Flex 4 if you haven't started already. Flex 4 is just about to be released.
With Flex 4, they have a whole new skinning architecture. This means you'll never use Programmatic Skins again. Plus they have Advanced CSS Selectors, so you can do way more with CSS in Flex 4. Programmatic Skins are very hard to make dynamic anyways. In the end, you'll end up creating an architecture like Flex 4 Spark Skins if you try to abstract out the logic for Programmatic Skins.
Customization
What we're doing to make Flex 4 Skins and Styling as dynamic as possible is the following:
- Style Palletes: Either static classes, or XML files
- Custom Skins
- CSS
Style Palletes: These are static classes that hold all of the variables you use in either CSS or Skins. For example, you can have a ColorPalette
that has all of your colors: public static const ColorPalette.BRIGHT_RED:uint = 0xff0000;
, etc. You can then use these in Flex 4 Skins via binding, such as <mx:Button color="{ColorPalette.RED}"/>
. The only problem with static classes is they they're not dynamic (you couldn't define an arbitrary number of colors for them). Same with XML: you'd have to hard-code (eventually) a certain XML structure in order to use them in Skins. You could even have the XML define ColorPalette values (so ColorPalette.ACCENT_COLOR
could be set to anything from XML (gold, bright blue, or any accent). Fun stuff.
Custom Skins: Flex 4 allows you to easily skin all the Flex 4 and Flex 3 (datagrid, accordion, etc.). So if you don't like how Panels only have 1 drop shadow and no gradients, you can add a background with 4 gradients and 2 dropshadows (for 2 angles of light), and maybe some rollover effect. And then you could apply your ColorPalette.BRIGHT_RED
to the shadow (or a glow :)). And you could have XML configure the ColorPalette settings. Here's a cool custom Flex 4 Skin
CSS: Then in CSS, you could write a very simple Palette parser that applied your ColorPalette values (for example) to CSS. Check out the Degrafa CSS Skin for some code examples.
Performance
The only problem with Palettes and CSS is performance. By definition, static class and binding decrease performance. Binding causes lots of event dispatching in the background, so things like <mx:Button color="{ColorPalette.RED}"/>
decrease performance (not noticeable of course, since there are much worse applications, such as using built in Adobe Tweens), but it does to some degree.
Same with CSS. In Flex, every CSS Selector (Panel { properties:values... }
is converted into an Object. So if you have 100 selectors, you get not only 100 extra object, but 100 extra classes in your application, at least! And that definitely adds to your swf size. And all of their properties are dynamic, and by definition, dynamic classes are slower than non-dynamic classes. Plus, setting a style (with setStyle(property, value)
in Flex is very slow because you have to loop through all the children. If you're setting styles via an admin system (or something like Flex Style Explorer like you suggested), then you don't really care. But because they use setStyle()
, you can see a decent performance hit when changing styles.
So if performance was a super big issue, the best option would be to hard code every style value, and not change styles at runtime (who needs to do that anyway (unless your in the admin section)?). How do you hard code styles while still remaining agile? Use Palletes (ColorPalette.BRIGHT_RED
) and the like, and convert the binding expressions (<mx:Button color="{ColorPalette.RED}"/>
) to static declarations via some preprocessor (I use ruby to compile my swfs, so I just match patterns and replace). So it'd convert <mx:Button color="{ColorPalette.RED}"/>
to <mx:Button color="0xff0000"/>
, and you get a performance boost.
In the end though, it's best to create custom skins and define the styles there, either through:
- static declarations
<mx:Button color="0xff0000"/>
- palette declarations
<mx:Button color="{ColorPalette.RED}"/>
- xml declarations
<mx:Button color="{myxml.@button_color}"/>
Then you can define some really cool and advanced skins and have them wired up to a palette or xml file and have the user edit that. Trying to build a very cool and modular skin/styling system with Flash or Flex using their built in stuff is not easy (nor desirable). So it's best to
- create a set of skins (and package them up as a theme)
- wire skins to xml
- let user modify xml
Avoid CSS, it's too processor intensive, unless you need advanced selectors like you'd use in HTML because it does make life easy. But for modularity and customizability (and performance), create Skins and wire them to XML.
I myself create a basic theme that I can use in all of my client projects, something that defines my style. That consists of 3 packages (myskins, mx, spark). In there, I copy/paste all the default Flex 3/4 skins and start customizing. You can download a Scale 9 Skin Project for free to have most components ready to skin and test. Then I just merge my design (photoshop or whatever) into Flex however you choose. For all the colors I reuse, I add them to a palette and eventually to XML. Then if I need a slightly different skin and I use that multiple times, I use CSS to define a new style for a skin (maybe a list with no background color or border). My CSS is very lean. Then I can just copy/paste my theme/palettes/css to new projects, modify it as needed, allow the user to edit the colors and positions via xml (or an admin interface) and I'm ready to go.
You can't do that much with just CSS.
Hope that helps.
Lance