Hack 42 Keep Text Legible

figs/beginner.gif figs/hack42.gif

Text legibility varies depending on the font, the point size, and the screen dimensions. Change the font metric on the fly to make the site legible on a variety of screen sizes.

Flash sites tend to use small graphics and text. That's cool, except that text legible on one machine may be illegible on another. For example 8-point text may be illegible on a Macintosh iBook. Likewise, text that looks good at a monitor resolution of 1024 768 may become unreadable at 1600 1200 resolution (the pixels are smaller at higher resolutions). And if I designed a site on my 1600 1200 desktop, the text may well look like the oversized font they use in early-reader books when viewed on a monitor set to 800 600. You could create a different site for each user, but we prefer a way of reading the user's screen size and changing the Flash presentation's text on the fly to suit the Stage dimensions.

Read the Screen Dimensions

Reading the user's screen resolution is simply a matter of reading the appropriate System.capabilities properties. The following code gives you the (x, y) screen resolution:

trace(System.capabilities.screenResolutionX);

trace(System.capabilities.screenResolutionY);

On my computer, I get 1600 and 1200 returned from this code, and, unsurprisingly, my screen resolution is set to 1600 1200. So what can we do with these values? One thing we can do is vary the size of our text based on the values. But first, we have to create our text.

The following code (available as varyText.fla on this book's web site) dynamically creates a text field containing some text:

var txtFmt:TextFormat = new TextFormat( );

var myStr:String = "Hello and welcome to Flash Hacks, " +

   "by Sham Bhangal and a host of co-contributors";

// Set up a font and font size for the text

txtFmt.font = "_sans"; 

txtFmt.size = 12;

var metrics:Object = txtFmt.getTextExtent(myStr, 200);

// Add text field

this.createTextField("my_txt", 1, 100, 100, 

       metrics.textFieldWidth, metrics.textFieldHeight);

my_txt.wordWrap = true;

my_txt.border = true;

my_txt.text = myStr;

my_txt.setTextFormat(txtFmt);

Lines 1 and 2 set up a TextFormat instance, txtFmt, that we use to display a string value, myStr. Line 4 sets the font to "_sans," one of three default fonts that Flash supports.

The Object instance metrics is then created (on line 7) using TextFormat.getTextExtent( ). This method returns an object with two properties?textFieldWidth and textFieldHeight?which define the width and height that a text field needs to display our string, myStr, given a text break after 200 pixels.

The second part of the code listing dynamically creates a text field named my_txt at depth 1 and position (100, 100) with width and height equal to the two properties of metrics discussed earlier.

The last four lines simply set up the text field's properties after it is created, including setting its value to our text, myStr, and applying the TextFormat object, txtFmt, which sets the point size and font.

The critical line is line 6:

txtFmt.size = 12;

Setting txtFmt.size to any other value (and applying it with setTextFormat( )) gives you a different size of text, plus a text field sized to fit (shown in Figure 6-1 for txtFmt.size equal to 8, 12, and 16 points, respectively).

Figure 6-1. Text fields scaled for three different point sizes of text
figs/flhk_0601.gif


You're probably getting the game plan by now: if we set the size property based on the user's display resolution, we've cracked the legibility issue. Try replacing line 6 with:

if (System.capabilities.screenResolutionX > 800) {

  txtFmt.size = 12;

} else {

  txtFmt.size = 10;

}

Note that you don't have to check both the screen's X and Y resolution; you can usually get a good idea of the screen resolution by just looking at one dimension because screens usually have an aspect ratio of around 4:3.

A few designers are probably looking at this and thinking, "Um, okay, but won't all this resizing alter my carefully designed layouts?" Yep, but remember that you will usually make fairly small changes to the font size (+/- about 2 points, as we have done here), and that won't drastically change your layouts. In extreme cases, you can keep the text fields the same size but use scrollbars for large areas of text or reduce the line spacing as you increase the text size (smaller text usually requires relatively higher line spacing than larger text).

Final Thoughts

As the need to cater to a number of screen sizes increases (for cell phones, handhelds, PDAs, and other nonstandard devices), the requirement for your text to look good is paramount. The manual solution is to design a different presentation for each major device, but there are several classes of devices or even differences among devices of the same class. Some level of dynamic control is better.

You also have the ability to dynamically change the size of the Flash Stage and/or any text instances on it in response to the screen resolution (and the browser window size). Knowing the relationship between the Flash Stage size and the overall screen size gives you further options to rescale your Flash content dynamically. By incorporating dynamically resized text metrics and a dynamically resizable Stage [Hack #92], you gain a significant amount of control over how your SWFs adapt to differing runtime conditions.

Another useful application of the code listed for this hack is with pop-up help text. The code to create resizable and movable text on the fly can be easily modified to create help text [Hack #47] that always resizes and positions itself to appear near the mouse, but within the Stage area.

You might also want to change the font when changing the size of the text. For example, if you need to render text clearly at small sizes, you should use pixel fonts [Hack #67] .