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

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