If you
define a style in only one place in a document, Flex uses that definition
to set a property’s value. However, an application can have several
style sheets, local style definitions, external style properties,
and style properties set directly on component instances. In such
a situation, Flex determines the value of a property by looking
for its definition in all these places in a specific order.
Lower-level styles take precedence over higher-level or external
styles. If you set a style on an instance, and then set the style
globally, the global style does not override the local style, even
if you set it after you set the local style.
Style inheritance order
The order in which Flex looks for styles is important to
understand so that you know which style properties apply to which
controls.
Flex looks for a style property that was set inline on the component
instance. If no style was set on the instance using an inline style,
Flex checks if a style was set using an instance’s setStyle() method.
If it did not directly set the style on the instance, Flex examines
the styleName property of the instance to see if
a style declaration is assigned to it.
If you did not assign the styleName property
to a style declaration, Flex looks for the property on type selector
style declarations. If there are no type selector declarations,
Flex checks the global selector. If all of these
checks fail, the property is undefined, and Flex applies the default
style.
In the early stages of checking for a style, Flex also examines
the control’s parent container for style settings. If the style
property is not defined and the property is inheritable, Flex looks
for the property on the instance’s parent container. If the property
isn’t defined on the parent container, Flex checks the parent’s
parent, and so on. If the property is not inheritable, Flex ignores
parent container style settings.
The order of precedence for style properties, from first to last,
is as follows:
Inline
Class selector
Type selectors (most immediate class takes precedence when
multiple selectors apply the same style property)
Ancestor class’s type selector
Parent chain (inheriting styles only)
Theme defaults.css file
global selector
If you later call the setStyle() method on a
component instance, that method takes precedence over all style
settings, including inline.
Style definitions in <fx:Style> tags,
external style sheets, and the defaults.css style sheet follow an
order of precedence. The same style definition in defaults.css is
overridden by an external style sheet that is specified by an <fx:Style source="stylesheet"/> tag,
which is overridden by a style definition within an <fx:Style> tag.
The following example defines a type selector for Panel that
sets the fontFamily property to Times and
the fontSize property to 24. As a result, all controls
inside the Panel container, as well as all subclasses such as Button
and TextArea, inherit those styles. However, button2 overrides the
inherited styles by defining them inline. When the application renders,
button2 uses Arial for the font and 12 for the font size.
<?xml version="1.0"?>
<!-- skins/MoreContainerInheritance.mxml -->
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
s|Panel {
fontFamily: Times, "_serif";
fontSize: 24;
}
</fx:Style>
<s:Panel title="My Panel">
<s:Button id="button1" label="Button 1"/>
<s:Button id="button2" label="Button 2" fontFamily="Arial" fontSize="12"/>
<s:TextArea text="Flex has is own set of style properties which are
extensible so you can add to that list when you create a custom
component." width="425" height="400"/>
</s:Panel>
</s:Application>
The executing SWF file for the previous example is shown below:
Subcomponent styles
Some Flex controls are made up of other components. For
example, the DateField control includes a DateChooser subcomponent,
the calendar that pops up when you click on the DateField’s icon.
The DateChooser subcomponent itself contains Button subcomponents
for navigation and TextField subcomponents for labels.
The following table lists some of the most commonly used Spark
components and their subcomponents:
Spark component
Subcomponents
Button
Label
ComboBox
Button, Label
HScrollBar/VScrollBar
Button
HSlider/VSlider
Button, Label
NumericStepper
Button, TextInput
RadioButton
Label
TextArea
RichEditableText
TextInput
RichEditableText
TitleWindow
Button, Label
VideoPlayer
Button, Label
Inheritable styles are passed from the parent control to the
subcomponent. These include text styles like color and textDecoration.
If you set the color style property on a DateField
control, Flex applies that color to the text in
the DateChooser subcomponent, too.
If a style property is explicitly set on the subcomponent (such
as in its skin class), then you cannot override it by setting it
in CSS. You must edit the skin class or override the style property
value in some other way. For example, the Spark HSlider control
has a Label subcomponent that defines the appearance of the slider’s
labels. The color style property is set on this
Label control explicitly in the HSliderSkin class:
If you define a Label type selector and specify the color, your
CSS setting does not override the explicit setting in the HSlider
control’s skin class. In this case, you must create a custom skin
class for the HSlider control to change the color of the label’s
text.
If you do not want an inheritable style property to be applied
to the subcontrol, you can override the parent’s style by defining
a custom class selector. For example, to apply styles to the subcomponents
of a ComboBox control, you can use the dropdownStyleName or textInputStyleName style
properties to define custom selectors.
Most controls that have subcomponents have custom class selectors
that apply styles to their subcomponents. In some cases, controls
have multiple custom class selectors so that you can set style properties
on more than one subcomponent.
The following example sets the color style property
on the DateField control. To prevent this color from being applied
to the DateChooser subcomponent, the DCStyle custom class selector
overrides the value of the color style property. This
custom class selector is applied to the DateField control with the dateChooserStyleName property.
<?xml version="1.0" encoding="utf-8"?>
<!-- styles/SubComponentStylesSelector.mxml -->
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Style>
.DCStyle {
color:blue;
}
</fx:Style>
<s:VGroup>
<s:Label text="Overrides the color property of the subcontrol:"/>
<mx:DateField
id="dateField1"
yearNavigationEnabled="true"
color="red"
dateChooserStyleName="DCStyle"/>
</s:VGroup>
<mx:HRule width="200" height="1"/>
<s:VGroup>
<s:Label text="Applies the color property to the subcontrol:"/>
<mx:DateField
id="dateField2"
yearNavigationEnabled="true"
color="red"/>
</s:VGroup>
</s:Application>
The executing SWF file for the previous example is shown below:
Noninheritable style properties are not passed from the parent
component to the subcomponent. In some cases, the parent control
provides a property that lets you access the subcomponent. For example,
to access the RichEditableText control that is a subcontrol of the
Spark TextArea and TextInput controls, you use the textDisplay property.
There are some exceptions to noninheritable styles. For example,
the verticalAlign, lineBreak,
and paddingBottom/Left/Right/Top style properties
are noninheritable. You can set these properties, which are defined
on the RichEditableText control, directly on the TextArea control
because the TextAreaSkin class passes them through to the subcomponent.
The following example sets styles on the RichEditableText subcomponent
with the textDisplay property, and also sets the
values of some noninheriting style properties that are not normally
accessible:
<?xml version="1.0"?>
<!-- styles/TextAreaStyles.mxml -->
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="initApp()">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
/*
Non-inheriting styles you must set on textDisplay:
columnCount
columnGap
columnWidth
Non-inheriting styles that you can set on TextArea because
they are passed to the subcomponent through the TextAreaSkin class:
lineBreak
paddingTop/Bottom/Left/Right
verticalAlign
*/
import spark.components.RichEditableText;
private function initApp():void {
RichEditableText(ta1.textDisplay).setStyle("columnCount", 3);
RichEditableText(ta1.textDisplay).setStyle("columnWidth", 100);
RichEditableText(ta1.textDisplay).setStyle("columnGap", 15);
}
]]>
</fx:Script>
<s:TextArea id="ta1" height="100" width="400" verticalAlign="bottom" paddingBottom="20">
This is a text area control. Because the text rendering is done by a RichEditableText subcontrol,
you have to use the textDisplay property to set the values of some non-inheriting styles.
Other non-inheriting styles are defined in the skin class and are passed through to the
subcomponent.
For inheriting styles, they are inherited by the RichEditableText subcontrol.
</s:TextArea>
</s:Application>
The executing SWF file for the previous example is shown below:
Some controls use filters to determine which style properties
are passed to subcontrols. For example, if you customize the value
of the cornerRadius property on a MX DateChooser
control, the property does not affect the buttons that are subcomponents
of the calendar. To pass that value to the subcomponent in MX components,
you can modify the control’s filter. Filters specify which style properties
to pass to their subcomponents. A filter is an Array of objects
that define the style properties that the parent control passes
through to the subcomponent. Inheritable style properties are always
passed; they cannot be filtered.
Most MX components with subcomponents have at least one filter.
For example, the ComboBox subcontrol has a dropDownStyleFilters property
that defines which style properties the ComboBox passes through
to the drop down List subcomponent.
Some MX controls with subcomponents have multiple filters. For
example, the DateChooser control has separate filters for each of
the buttons on the calendar: the previous month button (prevMonthStyleFilters),
the next month button (nextMonthStyleFilters),
the previous year button (prevYearStyleFilters),
and the next year button (nextYearStyleFilters).
The filters properties are read-only, but you can customize them
by subclassing the control and adding or removing objects in the
filter Array.
The following example includes two DateField controls. The first
DateField control does not use a custom filter. The second DateField
control is a custom class that uses two custom filters (one for
the properties of the next month button and one for the properties
of the previous month button).
<?xml version="1.0" encoding="utf-8"?>
<!-- versioning/StyleFilterOverride.mxml -->
<!-- Compile this example by setting the theme argument to use the Halo theme. -->
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:comps="*">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<s:VGroup>
<s:Label width="200"
text="Standard DateChooser control. Does not pass the cornerRadius property to the button subcomponents:"/>
<mx:DateChooser cornerRadius="10"/>
</s:VGroup>
<s:VGroup>
<s:Label width="200"
text="Custom DateChooser control. Passes the cornerRadius property to the button subcomponents:"/>
<comps:MyDateChooser cornerRadius="10"/>
</s:VGroup>
</s:Application>
The executing SWF file for the previous example is shown below:
To compile this example, you cannot use the Spark theme. You
must set theme compiler option to the Halo theme
file. To use a background image on a container with the Spark theme,
you must create a custom skin class.
The following class extends the DateChooser class and defines
custom filters Arrays for two of the button subcomponents:
// styles/MyDateChooser.as
package {
import mx.controls.DateChooser;
public class MyDateChooser extends DateChooser {
private static var myNextMonthStyleFilters:Object = {
"highlightAlphas" : "highlightAlphas",
"nextMonthUpSkin" : "nextMonthUpSkin",
"nextMonthOverSkin" : "nextMonthOverSkin",
"nextMonthDownSkin" : "nextMonthDownSkin",
"nextMonthDisabledSkin" : "nextMonthDisabledSkin",
"nextMonthSkin" : "nextMonthSkin",
"repeatDelay" : "repeatDelay",
"repeatInterval" : "repeatInterval",
"cornerRadius" : "cornerRadius" // This property is not normally included.
}
override protected function get nextMonthStyleFilters():Object {
return myNextMonthStyleFilters;
}
private static var myPrevMonthStyleFilters:Object = {
"highlightAlphas" : "highlightAlphas",
"prevMonthUpSkin" : "prevMonthUpSkin",
"prevMonthOverSkin" : "prevMonthOverSkin",
"prevMonthDownSkin" : "prevMonthDownSkin",
"prevMonthDisabledSkin" : "prevMonthDisabledSkin",
"prevMonthSkin" : "prevMonthSkin",
"repeatDelay" : "repeatDelay",
"repeatInterval" : "repeatInterval",
"cornerRadius" : "cornerRadius"
}
override protected function get prevMonthStyleFilters():Object {
return myPrevMonthStyleFilters;
}
}
}
The custom filters each include the following additional entry
in the Array:
"cornerRadius" : "cornerRadius"
The cornerRadius property is not normally listed
in the nextMonthStyleFilters and myPrevMonthStyleFilters Arrays.
By adding it to these filter Arrays, you ensure that the property
is passed from the parent control to the subcontrol, and is applied
to the previous month and next month buttons.
You can also use filters to exclude properties that are normally
passed through the subcomponent. You do this by removing those properties
from the filter Array in the subclass.
Inheritance exceptions for styles
Not all styles are inheritable, and not all styles are
supported by all components and themes. In general, color and text
styles are inheritable, regardless of how they are set (using CSS
or style properties). All other styles are not inheritable unless
otherwise noted.
A style is inherited only if it meets the following conditions:
The style is inheritable. You can see a list of inherited
style for each control by viewing that control’s entry in the ActionScript 3.0 Reference for the Adobe
Flash Platform. You can programmatically determine if
a style is inheritable using the static isInheritingStyle() or isInheritingTextFormatStyle() methods
on the StyleManager class. You can access the top-level StyleManager
by using the styleManager property of the Application
object.
The style is supported by the theme. To determine if a style
property is supported by the theme you are using, view the style’s
entry in the ActionScript 3.0 Reference for the Adobe
Flash Platform. If the style property is limited to a theme,
the Theme property will appear in the style’s description,
with the name of the supported theme next to it. If the style requires
a different theme, you can use the theme compiler
option to change the theme. If the ActionScript 3.0 Reference for the Adobe
Flash Platform does not specify a theme for a particular
style property, then that property should work with all themes.
The style is set on the control’s parent container or the
container’s parent. A style is not inherited from another class,
unless that class is a parent container of the control, or a parent
container of the control’s parent container. (The exception to this
condition is if you use type selectors to apply the style property.
In that case, Flex applies properties of the class’s type selector,
as well as any properties set in the base class’s type selector.)
The style is not overridden at a lower level. For example,
if you define a style type selector (such as Button { color:red }),
but then set an instance property on a control (such as <mx:Button color="blue"/>),
the type selector style will not override the style instance property
even if the style is inheritable.
You can apply noninheritable styles to all controls by using
the global selector. For more information, see Using the global selector.
About supported styles
All themes
support the inheritable and noninheritable text styles, but not
all styles are supported by all themes. If you try to set a style
property on a control but the current theme does not support that
style, Flex does not apply the style.
To determine if a style property is supported by the theme you
are using, view the style’s entry in the ActionScript 3.0 Reference for the Adobe
Flash Platform. If the style property is limited to a
theme, the Theme property will appear in the style’s description,
with the name of the supported theme next to it. If there is no
theme specified for a particular style property, then the style
property should be supported by all themes.
Some styles are only used by skins in the theme, while others
are used by the component code itself.
The display text of components is not skinnable, so support for
text styles is theme‑independent.
Many assets in the Halo theme support a property called themeColor.
You can set this property on the MX Application tag,
and the color is applied throughout the application on component
assets, such as the MX Button control’s
border, the headers of an Accordion control, and the default shading
of a ToolTip control’s background.
In addition to color values such as 0xCCCCCC (for silver) or
0x0066FF (for blue), the following values for the themeColor property
are valid:
haloOrange
haloBlue
haloSilver
haloGreen
The default value is haloBlue. The following
example sets the value of themeColor to haloOrange:
<?xml version="1.0"?>
<!-- styles/ThemeColorExample.mxml -->
<!-- Compile this example by setting the theme compiler argument to Halo.swc. -->
<mx:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
themeColor="haloOrange">
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
import mx.collections.ArrayCollection;
[Bindable]
public var themes:ArrayCollection = new ArrayCollection(
[ "haloOrange", "haloBlue", "haloSilver", "haloGreen"]);
private function closeHandler(e:Event):void {
FlexGlobals.topLevelApplication.setStyle("themeColor", ComboBox(e.target).selectedItem);
}
]]>
</fx:Script>
<mx:ComboBox dataProvider="{themes}" width="150" close="closeHandler(event);"/>
<mx:Button id="myButton" label="Click Me" toolTip="Click me"/>
</mx:Application>
The executing SWF file for the previous example is shown below:
To compile this example, you must use the Halo theme. For information
on using themes, see Using themes.
To achieve functionality similar to the themeColor property in
a Spark application, you can use the chromeColor style
property. This property is supported only by the Spark theme.