July 30, 2008

Advanced CSS Techniques and Programmatic Skinning

At the start of this month I attended the Boston Flex User Group Meeting where TR Coffey, Design Lead at Allurent (where I also work) gave a talk about Advanced CSS Techniques and Programmatic Skinning. Below are some rough notes I took during his talk.


TR comes to Flex from a visual design background, not coding. Has approached design as a picture to code process. Not only has he created the visual design but has also been involved in coding the styling to make it work.

Flex provides a great framework to start off from using Halo and CSS. Try to use it before going into any of the more labor intense methods. If CSS doesn't work the other options are: graphic skins, states, and programmatic skins.

Using graphic skins in a program like Flash (also available in Photoshop and Illistrator) lets you use scale 9, nested movie clips to provide global control, and work with percentage sized components.

State based skinning can be done with MXML components or on the Flash timeline. State skinning allows transitions between states (color fading, resizing, animations, etc.). For Flash the timeline has labels for each state. Component utility plug-in for Flash exists to help with the creation and exporting for use in Flex. Work to maintain timelines skins is very high.

When creating custom programmatic skins look at Halo border. It does a lot of heavy lifting.Are required to do things like set the border style to solid to get it to show up. Makes heavy use of theme color but doesn't provide that much subtle control over how colors get used.

If creating a custom border skin extend RectangularBorder, Border, or as a last resort ProgrammaticSkin. RectangularBorder gives edge metrics and other utility functions that shorten the development time. All of the border skin drawing will take place in updateDisplayList(). If style properties change call invalidateDisplayList() to trigger a redraw.

He demonstrated an issue with the default Halo border with thick borders and rounded corners. Should be logging a bug about that.

Have your skin pickup custom CSS properties from the style manager to offer control not found in the standard Halo skins. Always use hyphens in the CSS file for property names and camel case in code. The utility function drawRoundRect() gives you control to make almost any kind of border you want.

When creating a CSS file, define type selectors for defaults then cascade down to class selectors for overrides. Handy to make a CSS skin reference ClassReference(null) to turn it off for something like an up-down button. Components should have default values baked in that can then be overridden by CSS.

When to use inline MXML vs. style sheets: Designers don't really want to muck with MXML to style the application so providing style sheet properties that the skin picks up makes life easier.

Trade off between making a single mega-skin like Halo border, versus multiple smaller skins each with a single purpose. Mega skins allow more layers of effects but are harder to maintain.

Allurent tends to push more skin configuration to the style sheet since we are making products and having a single configuration point makes it easier. Having it in a style sheet instead of inline MXML also allows for external style sheet loading, compiled independent of the rest of the application. Since styling is cross component having everything in one place is best.

Tags: css flex styling

November 30, 2007

Styles, Fonts, and Compile Time

There has been some recent conversation about the impact of styles and fonts on compilation time in Flex Builder 3. I figured I'd take the project I'm currently working on and see what the numbers came out as.

Some more details about the test: About 700KB of raw .as and .mxml code. 2 separate CSS files are imported. 120KB of TTF fonts. 650KB of SWF fonts. Compiling using Flex 2.0.1 Hotfix 3 SDK. Each tests was run 3 times with the average time reported. Each test was run by changing text in the top level MXML component, saving it, and timing a manual build. Timing was from time of click until the progress view reported the build was finished. Copy non-embedded and generate HTML template were disabled.

As with all measurements these should be taken with a grain of salt and are meant to be representative. Your project will vary, yadda, yadda, yadda.

Compile State Compile Time (in seconds)
All styles, 11 SWF fonts, and 2 TTF fonts 11.3
No styles or fonts 4.8
All styles and no fonts 6.9
All styles and 8 SWF fonts 9.1
All styles and 2 TTF fonts 9.1
All styles and 3 SWF fonts 8.1

Clearly using TTF encoded fonts has a higher overhead than SWF encoded fonts. More fonts take more time. The next item to explore is using Flex Builder 3's compile CSS to SWF option. Doing that would require looking at application startup time since the styles would no longer be compiled in but instead loaded during startup.

Tags: as3 css flex

September 26, 2007

Flashforward Boston: Stylizing Flex Applications

Rough Draft of Notes

Joey Lott The Morphic Group

Main application to be styled is just using standard components. VBox, List,

Inline attribute on List: backgroundColor
This isn't preferred since you have no centralized location of what your style information is.

Adding . Type selector and Class selector.

<mx:Style>
List {
    backgroundColor: #0000FF;
}
</mx:Style>

Applies to all components. Another List in the program would also get it. To have more control you can use a style selector. Need to set it via styleName on a target component.

.exampleStyleSelector {
    backgroundColor: #0000FF;
}

Why do this. Can reuse selector on any other component while keeping the style information centralized. Camel case for style names or hyphenation. Inline styles must use camel case but CSS information can use either.

Moving selector into external styles.css file via:

<mx:Style source="styles.css"/>

Application {
    background-color: #000000;
}

Precedence of style application: Type selector applied first, then class selector, lastly inline style attribute.

What to style items in the List. Going to use an item renderer. Like Cell renderer in Flash. Using another MXML component to show the list item. Gets passed a data property which contains the list item.

<mx:HBox>
<mx:Image source="{data.image}"/>
<mx:Text text="{data.title}"/>
</mx:HBox>

Add itemRenderer="com.example.DataRenderer" to List we want to render items of. Always need to use full class name can't use class name only even if imported.

Style scrollbars with a type selector. It is using custom images for arrows.

ScrollBar {
    up-arrow-up-skin: Embed('images/scrollArrowUp.png');
}

Embedding fonts can use url or local directive can be used to reference font file.

@font-face {
    src: url("Verdana.ttf");
    font-family: Morphic;
}

Styling some of the other components. Some type selectors can reference other class selector names.

TabNavigator {
    tab-style-name: tabButtons
}
.tabButtons {}

VBox with nested image. Using scale 9 to control embedded image.

.framedImage {
    background-image: Embed('image.png', scaleGridTop=30, scaleGridBottom=59, scaleGridLeft=30, scaleGridRight=59);
}

Programmatic skinning. Consider a general style that you want to have many variations of. Graphic assets would require unique file for each variation and increase file size. A programmatic skin let's you do it in code instead.

public class ButtonSkin extends ProgrammaticSkin {
    // key method to override
    override protected function updateDisplayList(...);
    if (getStyle("backgroundColor") != null) {
        //pikcup value
    }
    // name property of programmatic skin
    if (name == "upSkin") {
        //skin specific style
    }
}

// in css
Button {
    upSkin: ClassReference("com.example.ButtonSkin");
}

Customizing the preloader. Make sure you only use ActionScript stuff, nothing from Flex framework since they won't be available yet.

public class CustomDownloadProgress extends DownloadProgressBar {
    override public function set preloader(value:Sprite):void {
        // progress and init_complete events
    }
    // dispatch complete event when done and application should start
}

<mx:Application preloader="com.example.CustomDownloadProgress"/>

scale9.com for premade styles

Tags: css flashforward2007boston flex styling

August 31, 2006

CSS and Runtime Modules

Another strange problem has popped up with the use of runtime modules. CSS type selectors don't work correctly. The compiler optimizes the CSS such that it only includes information for types that are actually used, based on the class dependency hierarchy. Since with a runtime module you are indirectly using classes, the dependency isn't found and the CSS information is excluded. Consider the following type selector:

SampleClass {
    backgroundColor: #FFFFFF;
    backgroundAlpha: .5;
    borderColor: #000000;
    borderThickness: 2;
    borderStyle: solid;
    paddingTop: 4;
    paddingBottom: 4;
    paddingLeft: 4;
    paddingRight: 4;
}

If you don't have a dependency on SampleClass in the main application you will end up with the following compiler warning:

"The type selector 'SampleClass' was not processed, because the type was not used in the application."

Right now I don't have a good solution for this. The simple work around is to not use a type selector but instead just make it a style selector (i.e. .sampleClass instead of SampleClass), but that requires you to set the styleName attribute on every instance you create. I'm open to other ideas.

Update
There are a couple of compiler options that help with this issue. If you are getting the warnings and don't care about them you can turn them off like this:

-show-unused-type-selector-warnings=false

This can be either a command line parameter, stuffed into a flex-config.xml file, or setup as an additional compiler argument in Flex Builder. If instead you want to include every CSS type selector, without having to do the static reference nonsense, you can do this:

-keep-all-type-selectors=true

Again that can be setup as either a command line parameter, part of a config, or enabled in Flex Builder. For additional information on the two options see LiveDocs.

Tags: css flex