CSS Positioning with Flex 2

Among the countless new features offered by Flex 2 is constraints-based layout. If you haven’t had a chance to explore the use of constraints I encourage you to spend some time with the approach. I was a skeptic at first myself, but have since come to really enjoy the lightweight results (as compared to flow-based layout which generally involves deep nesting of boxes to achieve complex layouts). At the core of constraints-based layout is a series of properties that allow you to specify positioning and anchoring of your controls and containers.

To be clear, flow-based layout and constraints-based layout aren’t mutually exclusive. Combining the two for their strengths lends itself to rapid development using Flex Builder’s design view.

I was curious about these constraints properties, so one day I looked them up in the language reference. What I found is that they weren’t properties at all! The constraints I had been putting inline were actually styles. This meant that I could externalize them and leverage an external CSS to control the appearance of my user interface. Take the following code and screenshot as a starting point.

<mx:Application layout=”absolute” xmlns:mx=”http://www.adobe.com/2006/mxml”>

  <mx:Panel
    x=”10″
    y=”10″
    width=”274″
    height=”148″
    layout=”absolute”
    title=”Login”>

    <mx:Label x=”10″ y=”12″ text=”Username:” />
    <mx:TextInput x=”85″ y=”10″ />

    <mx:Label x=”10″ y=”42″ text=”Password:” />
    <mx:TextInput x=”85″ y=”40″ displayAsPassword=”true” />

    <mx:ControlBar>
      <mx:Button label=”Login” />
    </mx:ControlBar>

  </mx:Panel>

</mx:Application>

constraints1.jpg

At first pass, when you look at the screen and code nothing seems obviously wrong or lacking. When you take a closer look however, you start to see some shortcomings of how this UI has been put together. You might notice for example, that the login dialog is always going to be at the upper-left of the application. We’d probably like that to be centered in the application based on screen resolution.

The login dialog has also been made specifically to fit the size of the TextInput controls. There’s no width information on the TextInput controls, so they will default to 150 pixels. What would happen if I needed to add another field to the login and the preceding label was longer than the existing username and password labels?

This would force me to put the TextInput further to the right. To maintain alignment, I’d then have to revisit the other TextInput controls and align them further to the right as well. All this pushing to the right would mean that the Panel would need to be wider. Wouldn’t it be easier if the contents of the Panel would just automatically align themselves within the confines of that container?

Constraints let me solve these types of problems very easily. They also let me do so entirely through Flex Builder’s design view. Let’s revisit the code and screenshot with constraints added.

<mx:Application layout=”absolute” xmlns:mx=”http://www.adobe.com/2006/mxml”>

  <mx:Panel
    width=”275″
    height=”150″
    horizontalCenter=”0″
    verticalCenter=”0″
    layout=”absolute”
    title=”Login”>

    <mx:Label left=”10″ top=”12″ text=”Username:” />
    <mx:TextInput left=”85″ right=”10″ top=”10″ />

    <mx:Label left=”10″ top=”42″ text=”Password:” />
    <mx:TextInput left=”85″ right=”10″ top=”40″ displayAsPassword=”true” />

    <mx:ControlBar>
      <mx:Button label=”Login” />
    </mx:ControlBar>

  </mx:Panel>

</mx:Application>

constraints2.jpg

Now my dialog will stay centered in the application regardless of screen resolution. Additionally, the username and password Label and TextInput controls will also now stay where they are relative to the Panel regardless of the size of the Panel itself. As a side effect, this has also allowed me to round the numbers for the width and height of the Panel (used to be 274×148, and is now 275×150). Because the controls will now resize themselves appropriately these subtle changes become much easier to make.

Notice that all the X and Y properties are also no longer present, as the UI is now relative to other parts of the application.

There’s still one thing that bugging me about the UI though, and that’s the “Login” button itself which is aligned (by default) to the left in the ControlBar. Most operating systems align control buttons to the bottom right of a dialog. This is easy enough to change though, right? The ControlBar defaults to an HBox layout. While we could tell it to use constraints, this layout is working great for us as-is, save that pesky alignment.

Luckily for us, there’s a “horizontalAlign” style on the ControlBar container. I can flip that style inline, right on the tag, or I can put it in a Style block elsewhere in the source code. Most of the times we’ll pull our styles to a Style block, but then we’ll go one step further as well. We don’t like embedding all those styles inside the application itself, so we’ll externalize it to a CSS file. Now all our changes can be made in one centralized place.

What about those constraints though? Didn’t I mention that those were styles too? They are, and can be externalized in the same CSS. Let’s take a look at the application source code and screenshot one more time.

<mx:Application layout=”absolute” xmlns:mx=”http://www.adobe.com/2006/mxml”>

  <mx:Style source=”constraints3.css” />

  <mx:Panel
    width=”275″
    height=”150″
    layout=”absolute”
    title=”Login”>

    <mx:Label text=”Username:” styleName=”userlabel” />
    <mx:TextInput styleName=”userinput” />

    <mx:Label text=”Password:” styleName=”passlabel” />
    <mx:TextInput displayAsPassword=”true” styleName=”passinput” />

    <mx:ControlBar>
      <mx:Button label=”Login” />
    </mx:ControlBar>

  </mx:Panel>

</mx:Application>

constraints3.jpg

The screenshot is almost identical to the previous examples save that our “Login” button is now aligned to the right - whew! The code has changed only a little as well, and in a good way. In place of exact constraints there’s now style names given to the controls where appropriate. All those pesky constraints that were tied directly to their specific control are now gone. Actually they are still there and it’s obvious that they are still being applied, but they’re now externalized into the CSS file. It’s in that CSS file where the magic really takes place, so let’s get a closer look.

ControlBar {
  horizontal-align: right;
}

Label {
  left: 10;
}

Panel {
  horizontal-center: 0;
  vertical-center: 0;
}

TextInput {
  left: 85;
  right: 10;
}

.userlabel {
  top: 12;
}

.userinput {
  top: 10;
}

.passlabel {
  top: 42;
}

.passinput {
  top: 40;
}

The first thing you should notice is that I’ve used CSS selectors where appropriate to specify styles for those controls en masse. When you get to the TextInput block, you’ll see that I’ve defined not fonts or colors, but left and right constraints. Since I want all my TextInput controls to be aligned vertically, and to maintain the same width (relation to the edges of the container), it makes sense to apply that styling at the block level. Managing the constraints for the TextInput’s relation to the top of the container is done in a CSS class statement.

The best part of all of this is the cascading nature of CSS. The “left” and “right” constraints on the TextInput block are also inherited with the class statements used to specify the “top”. We’ve been looking at the TextInput, but the same is also done with the Label selector and class statements. These are applied back in the MXML by using a “styleName” property on the controls.

The CSS selectors and class statements can also include font, color and other styling information.

Using the stylistic approach to constraints provides me with some pretty impressive capabilities. Let’s say that for whatever reason we decided that the Panel should actually be in the upper-left of the application. I can go into the CSS, exchange “vertical-center” and “horizontal-center” for “left” and “top” values and be done. An even better example might be if we want to rearrange the order of the Label and TextInput controls.

Simply by modifying the CSS I can completely change the order in which these controls appear. It could be as simple as vertical arrangement where I wanted “Password” to come before “Username”, but I could also put the Label controls on the right side of the TextInput controls. No hunting and pecking for inline properties, just simple CSS changes. A quick couple of double-clicks in the Flex Builder design view to change the labels to reflect their new positioning, and the rest is up to your imagination!

All the source code for these iterations is attached.

ControlBar {
  horizontal-align: right;
}

Label {
  right: 10;
}

Panel {
  left: 10;
  top: 10;
}

TextInput {
  left: 10;
  right: 85;
}

.userlabel {
  top: 42;
}

.userinput {
  top: 40;
}

.passlabel {
  top: 12;
}

.passinput {
  top: 10;
}

constraints4.jpg

13 Responses to “CSS Positioning with Flex 2”

  1. Dominick Says:

    just a note that recompilation is needed which is a small difference about html stylesheets and flex stylesheets.

  2. Nobody in Particular Says:

    What “built-in” functionality am I loosing by not wrapping labels in fields within Form layout components? Validation? Required attributes?

  3. Maksys Says:

    Its Rox.. :D
    A Flex can supporting full specification css2 or css3 from w3c?

  4. Dreamer Says:

    wonderful post!

    Can I translate it into Chinese and publish on the web? Of course, with links to the original post.

    Thanks

  5. The Doctor Says:

    Why don’t use HTML and CSS?

  6. Sanjay Sharm Says:

    Hi,

    I want to pick piechart color from CSS. but I am not able to do it. pls help me

    Sanjay

  7. judah Says:

    Nice article. I just found this article after posting the PropertyBag class last night. Basically it lets you mix in properties into your stylesheets.

    http://www.judahfrangipane.com/blog/?p=56

    @The Doctor - you have so much more control and compatibility in Flex. I worked in HTML and CSS for 8 years as a professional web developer. I have switched to using Flex and I *enjoy* developing again and sleep peaceful at night. ;)

  8. Claudia Says:

    Hi Kevin,
    I found you via Computer Edge listings of Users Groups while actually looking for the Macromedia Group to get some CSS learning. Their website doesn’t come up. Might you know if they’re still functioning?
    And is this Cold Fusion group?
    If so, when is your next gathering, and where, please?
    Thanks.

  9. Kevin Hoyt Says:

    Claudia,

    You might try taking a look at the user group information on the Adobe web site.

    http://www.adobe.com/communities/usergroups/

    Thanks for reading,
    Kevin

  10. racheal Says:

    Hi.

    Need a flex person.

    racheal

  11. racheal Says:

    Need a Flex developer.
    are you open?

    In San Franciscio.

    racheal bailey
    RGA Consulting
    415 951 8051 ext. 1404

  12. Hi Says:

    if I have several TextInputs and Buttons, then how can I relate their position in a css in flex? should I define some different class for each of them?
    thank u

  13. Ivan Says:

    Nice.
    Thanks

Leave a Reply