Flex 4 Spark Skinning
In Flex 3 the way you styled your applications was through css, style properties, importing images, and finally using flash via swf files to style the look of your application. The problem with this situation was css and styles allowed for a limited styling and images and swf files would increase the size of the compiled application really quickly. In the end, we didn’t have enough options and enough options that could be highly optimized. As you could already guess, this has all changed with Flex 4 and the new Spark components.
Before I can say how Spark components are different, let me define a specific term halo components. Halo components are Flex 3 components, specifically components that have the look and feel of the component directly connected to the logic and methods of the component. Spark components are different, the look and feel have been pulled away from the logic and methods. This make it so that one component and another component can look COMPLETELY different while still maintaining the same base logic, properties, and methods.
In Flex 3 we could easily style multiple different buttons, such as:
Having a hard time viewing this example? Click here to view.
Due to each button containing the same style properties, there are only so many combinations of properties and therefore each button still looks and feels similar – similarly to how brothers and sisters look the same.
Now, with Flex 4 we can make custom Spark skins to continue making our buttons look even more foreign from each other. The Flash plugin is required to view this object.
Having a hard time viewing this example? Click here to view.
The first button is just a plain button with no skinning, the other three are very different, all due to the skin that is added on them. And yes, I do know that the buttons look horrible – I wasn’t going to pretty.
Skins Basics
As you first get into Spark skinning your immediately going to think “this takes forever!” Once you get over that feeling you will realize that by skinning your spark components you have the ability to literally make anything component you want with ease.
To start your skinning, first determine if you are basing this skin off of a component, specifically a spark component. Yes? Then just like my examples, you need to set the host component meta tag, and the defined states in your component. The reason you set your states is so that your skin works just like every other flex 4 mxml components states array. No? Then I guess you better go make the component core that you are planning to make and then later start making your skin.
The Host Component
The host component meta tag states what component this skin defines, also giving you access to the styles and properities inherit to the specific component.
1 2 3 | <fx:Metadata> [HostComponent("spark.components.Button")] </fx:Metadata> |
Skin States
The skin states act just like states within mxml components. You can see this states feature from a previous blog post of mine: Flash Builder Feature: States.
Your initial button skin should look similar to this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?xml version="1.0" encoding="utf-8"?> <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo""> <fx:Metadata> [HostComponent("spark.components.Button")] </fx:Metadata> <s:states> <mx:State name="up"/> <mx:State name="down"/> <mx:State name="over"/> <mx:State name="disabled"/> </s:states> </s:SparkSkin> |
From this point on the look of the component is up to you. Typically you will start with a shape, set it’s fill and stroke and draw out your component, for some examples view the source of the different skin examples I have provided for you. After your initial or base component state, feel free to keep playing with the different states of your spark skin. At this point your imagination (and time) is your only limitation to the look, feel, transitions, and interaction of your new spark component skin.
The Circle Button
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <?xml version="1.0" encoding="utf-8"?> <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minHeight="80" minWidth="80"> <fx:Metadata> [HostComponent("spark.components.Button")] </fx:Metadata> <s:states> <mx:State name="up"/> <mx:State name="down"/> <mx:State name="over"/> <mx:State name="disabled"/> </s:states> <s:Ellipse left="0" top="0" right="0" bottom="0"> <s:fill> <mx:RadialGradient> <mx:GradientEntry color="0xFF0000" ratio=".33"/> <mx:GradientEntry color="0x000000" ratio=".9"/> </mx:RadialGradient> </s:fill> </s:Ellipse> <s:Ellipse left="0" top="0" right="0" bottom="0" includeIn="over"> <s:fill> <mx:RadialGradient> <mx:GradientEntry color="0xFFFFFF" ratio="0"/> <mx:GradientEntry color="0xFF0000" ratio=".33"/> <mx:GradientEntry color="0x0000FF" ratio=".66"/> </mx:RadialGradient> </s:fill> </s:Ellipse> <s:Label id="labelDisplay" horizontalCenter="0" verticalCenter="0" textAlign="center"/> </s:SparkSkin> |
The Diamond Button
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | <?xml version="1.0" encoding="utf-8"?> <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minHeight="80" minWidth="80"> <fx:Metadata> [HostComponent("spark.components.Button")] </fx:Metadata> <s:states> <mx:State name="up"/> <mx:State name="down"/> <mx:State name="over"/> <mx:State name="disabled"/> </s:states> <s:Rect rotation="45" y="0" x="50" minHeight="80" minWidth="80"> <s:stroke> <mx:SolidColorStroke color="0x000000" weight="1"/> </s:stroke> <s:fill> <mx:LinearGradient> <mx:GradientEntry color="0x00FF00"/> <mx:GradientEntry color="0x000000" ratio="0.1"/> <mx:GradientEntry color="0x0000FF"/> </mx:LinearGradient> </s:fill> </s:Rect> <s:Rect rotation="45" y="0" x="50" minHeight="80" minWidth="80" includeIn="over"> <s:stroke> <mx:SolidColorStroke color="0x000000" weight="1"/> </s:stroke> <s:fill> <mx:LinearGradient> <mx:GradientEntry color="0x00FF00"/> <mx:GradientEntry color="0x000000" ratio="0.9"/> <mx:GradientEntry color="0x0000FF"/> </mx:LinearGradient> </s:fill> </s:Rect> <s:Label id="labelDisplay" horizontalCenter="0" verticalCenter="0" color="0xFFFFFF"/> </s:SparkSkin> |
The Link Button
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <?xml version="1.0" encoding="utf-8"?> <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo"> <fx:Metadata> [HostComponent("spark.components.Button")] </fx:Metadata> <s:states> <mx:State name="up"/> <mx:State name="down"/> <mx:State name="over"/> <mx:State name="disabled"/> </s:states> <s:Rect left="0" right="0" top="0" bottom="0"> </s:Rect> <s:Rect left="0" right="0" top="0" bottom="0" includeIn="over" radiusX="15" radiusY="15"> <s:stroke> <mx:SolidColorStroke weight="2" color="0x0000FF"/> </s:stroke> <s:fill> <mx:SolidColor color="0x0000FF"/> </s:fill> </s:Rect> <s:Label id="labelDisplay" left="10" right="10" top="10" bottom="10" color.over="0xFFFFFF"/> </s:SparkSkin> |
The Triangle Button
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | <?xml version="1.0" encoding="utf-8"?> <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="40" minHeight="40"> <fx:Metadata> [HostComponent("spark.components.Button")] </fx:Metadata> <s:states> <mx:State name="up"/> <mx:State name="down"/> <mx:State name="over"/> <mx:State name="disabled"/> </s:states> <s:Path data="H 100 L 50 75 L 0 0"> <s:filters> <s:DropShadowFilter blurX="20" blurY="20" alpha="0.5" distance="11" angle="90"/> </s:filters> <s:stroke> <mx:LinearGradientStroke weight="1"> <mx:GradientEntry color="0x0000FF" ratio=".25"/> <mx:GradientEntry color="0xFFFFFF"/> </mx:LinearGradientStroke> </s:stroke> <s:fill> <mx:LinearGradient rotation="90"> <mx:GradientEntry color="0xFFFFFF"/> <mx:GradientEntry color="0x0000FF"/> </mx:LinearGradient> </s:fill> </s:Path> <s:Path data="H 100 L 50 75 L 0 0" includeIn="over"> <s:stroke> <mx:LinearGradientStroke weight="1"> <mx:GradientEntry color="0x0000FF" ratio=".25"/> <mx:GradientEntry color="0xFFFFFF"/> </mx:LinearGradientStroke> </s:stroke> <s:fill> <mx:LinearGradient rotation="90"> <mx:GradientEntry color="0xFFFFFF"/> <mx:GradientEntry color="0x0000FF" ratio=".25"/> </mx:LinearGradient> </s:fill> </s:Path> <s:Label id="labelDisplay" horizontalCenter="0" verticalCenter="-10"/> </s:SparkSkin> |
Packaging Skins
Since skins are basically just mxml components, you can asdoc your skin like any other mxml component and also package the skin within your application or library project.
CSS with Skin Files
Finally, you can directly assign you spark component’s skin class as such..
1 | <s:Button label="Button" skinClass="com.unitedmindset.skins.button.LinkButtonSkin"/> |
… or you can put the skin information into your css sheets as such…
1 2 3 4 | s|Button.diamond { skinClass: ClassReference("com.unitedmindset.skins.button.DiamondSkin"); } |
… and reference your skin via the component’s styleName properties.
1 | <s:Button label="Button" styleName="diamond"/> |
Update: I’ve created a future post on how to do this with Flash Catalyst.
Updated the blog text to reflect the Flex 4 Beta 2 release. The view source is still the old code, please be aware. Because of that I’ve removed the view source files. Will update them shortly.
I’ve created another post detailing some new skinning workflows for Flash Builder 4
I’ve created a newer post that goes over creating your own Spark Component and how to package your custom Spark Skin with your own custom Spark Component.





I have been interested in learning how to skin both spark and halo components.
I’m still trying to understand the whole the actual elements themselves have to all be together towards the bottom of the page and the action script and other non visual tags have to be located towards the top.
Technically the actual elements and the script COULD switch, but it is seen as best practice to place them in that order. And, one thing to remember about mxml, is the lower the visual element is in the mxml document, the higher the index order. So with…
2
<s:Group id="b"/>
b is in front of a visually.
A+++ Would go to again. Great presentation, guys.
Glad you liked it!
[...] Flex 4 Spark Skinning Post [...]
This is super. I am still at Flex 3 and will not be able to upgrade for a few more months and in my project, I need a triangle button. Any thoughts on how I can achieve that without excessive graphics rogramming? Thanks
You can, it just is a different process.
In Fx3 you have the ability to set the component’s skin with an image. Use the skin (skin, upSkin, downSkin, overSkin, disabledSkin, etc) property on your button and set whatever image you want… done! Use Flash SWF files for the most optimized results. In Fx4 you don’t even have to worry about Flash and you get the optimization.
Hi Jonathan, unfortunately that does not work as the button is rectangular in shape, even if I have a triangle image skin on it.
May be my photo shop skill is bad, but I don’t know how to create a GIF or JPG Image that has only a triangle and no background color or matte. If I attach my triangle image skin on the button, the background color of the image shows up along with my colored triangle.
I hope I am explaining my problem to you well enough to be understood. Thanks, Ramesh
No, that makes sense. The problem is that you are using jpg and gifs. Try using a swf or png with a transparent background. That will give you your desired effect.
Thank you. PNG worked great.
Thank you for your clear explanation of how to properly skin spark buttons. It has to be the best I’ve found online. There is one thing I wanted to point out though.
Due to a change in how text will be represented in buttons, as I found out from here:
http://opensource.adobe.com/wiki/display/flexsdk/Spark+Text+Primitives+Decision
I believe your examples will need to replace:
with:
At least this is what I had to do in my skins when upgrading from Flash Builder Beta 1 to Beta 2.
Thank you Nick, and you are right. I need to update the examples to reflect the newest SDKs.
Jonathan,
thanks for the post.
SimpleText throws an error on my build.
workaround: just use Label , with the id as discussed above.
Updated the examples to be up with the newest Fx4 build.
thanks for the explanation. can i have some inputs on how to apply background attachment/background image to certain control.
regards.
Check out what dev girl did, it should explain background images well.
Thanks for the simple breakdown. How would these look separated out to a css file? Do you leave the host component meta tag declaration in the mxml file, and simply define the style properties for the various states in the css? Also, whats the best way to match styles in an application that is being developed in Flex 3 and flash builder 4? My biggest hurdle as a non-programmer/designer, is trying to make the two look and act the same while being constrained to only halo components in one application and the changing nature of a beta development tool in the other. Do you have any resource suggestions for a novice in this situation?
Thanks in advance!
@dave What do you mean “how would these look separated out to a css file?”. My example shows how to include skins in css. The whole skin file would not go into a css file.
Yes, the host component would stay in the proper skin file.
The best ways to match styles of halo components in a Fx4 project would be to use the “halo” default theme. This simple theme will make your Fx4 spark components look like halo components… or use halo components
Let me know what other resource suggestions you are looking for and I’d be happy to point you in a direction, what is it you are trying to learn?
[...] few months ago I put together a blog entry on Spark Skinning. This entry was based off of Flash Builder Beta 1 and there have been many improvements to Flex 4 [...]
[...] Flex 4 Spark Skinning Post [...]
[...] Flex 4 Spark Skinning Post [...]
[...] Aquí encontrarás mayor información de Spark: http://unitedmindset.com/jonbcampos/2009/07/02/flex-4-spark-skinning/ [...]
[...] gives me an opportunity to throw some props to local Flex developer and guru, Jonathan Campos. Take some time to review his Spark skinning tutorial. I created a ‘minimal’ [...]
[...] of my posts on Spark Skinning… Flex 4 Spark Skinning Flash Catalyst – The Missing Visual Editor The New Spark Skinning [...]
[...] of my posts on Spark Skinning… Flex 4 Spark Skinning Flash Catalyst – The Missing Visual Editor The New Spark Skinning [...]
[...] in Flex 3. If you want more information on Spark Skinning check out some of my other posts: Flex 4 Spark Skinning New Spark Skinning Workflow Spark Skinning with Flash Catalyst var a2a_config = a2a_config || [...]
Awesome ! Many thanks for that !