About style inheritance

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:
<!-- From HSliderSkin.mxml --> 
<s:Label id="labelDisplay" text="{data}" 
    horizontalCenter="0" verticalCenter="1" 
    left="5" right="5" top="5" bottom="5" 
    textAlign="center" verticalAlign="middle" 
    fontWeight="normal" color="white" fontSize="11"> 
</s:Label>

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 supported by the control. For information about which controls support which styles, see the control’s description in the ActionScript 3.0 Reference for the Adobe Flash Platform.

  • 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.

For more information, About themes.

About the themeColor property

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.