Extending CSS capabilities in Flash

June 13th, 2005 by Thomas

Following up our post Flash: Using CSS I found out that Flash internally converts every CSS-class into a TextFormat Object. That's why it only supports CSS properties that have a direct relation to a TextFormat property. It doesn't support "line-height" for example, nor the TextFormat alternative "leading".

Then I found these comments on the Macromedia site, where somebody explains how to extend the TextFormat.StyleSheet class to support custom CSS properties by overwriting its transform method. It works! I copied out a more complete version below that supports all TextFormat properties through CSS (even tabStops!).

In terms of memory usage and performance using CSS is probably worse than using TextFormat objects directly, as it has to convert the CSS code first, and parse every TextField to apply the correct implicitly created TextFormat object. It's defintiely better in terms of flexibility and maintenance though, which is good enough for me to use it...

Supported CSS poperties:

CSS:
  1. .fullsample
  2. {
  3.     font-family: "Arial";
  4.     font-size: 11pt;
  5.     font-weight: bold;
  6.     font-style: bold;
  7.     color: #000000;
  8.     text-align: left;
  9.     text-decoration: none;
  10.     display: none;
  11.     margin-left: 5px;
  12.     margin-right: 5px;
  13.     text-indent: 5px;
  14.  
  15.     /* these aren't standard css... */
  16.     leading: 5pt;
  17.     block-indent: 5px;
  18.     tab-stops: 150, 300;
  19.     bullet: true;
  20. }


The AS class looks like this:

Actionscript:
  1. import TextField.StyleSheet;
  2.  
  3. class your.package.ExtendedStyleSheet extends TextField.StyleSheet
  4. {
  5.     /*
  6.     strips the unit from the end of the string and returns the number only
  7.     supported units are "pt" and "px" (or anything that starts with a "p" really...)
  8.     textformat doesn't need the units as they're fixed (i.e. size is always pt, indent always px etc.)
  9.     */
  10.     function stripUnit(input:String):Number
  11.     {
  12.         return Number(input.substr(0, input.indexOf("p")));
  13.     }
  14.    
  15.     /*
  16.     Flash ignores a negative leading and sets it to zero:
  17.     textFormat.leading = -10;
  18.     trace(textFormat.leading); // prints "0"
  19.    
  20.     However it works when setting it through the constructor (don't ask!):
  21.     textFormat = new TextFormat(null, null, null, null, null, null, null, null, null, null, null, null, -10);
  22.     trace(textFormat.leading); // prints "-10"!
  23.    
  24.     This function works around this bug by creating a new TextFormat object with the leading in
  25.     the constructor and re-setting all the previously set properties, except leading...
  26.     It's dirty but it works...
  27.     */
  28.     function negativeLeadingFix( textFormat:TextFormat, leading:Number ):TextFormat
  29.     {
  30.         if (leading>=0)
  31.         {
  32.             textFormat.leading = leading;
  33.             return textFormat;
  34.         }
  35.         else
  36.         {
  37.             var newTextFormat:TextFormat = new TextFormat(null, null, null, null, null, null, null, null, null, null, null, null, leading);
  38.             for (var property:String in textFormat)
  39.             {
  40.                 if (property!="leading") newTextFormat[property]=textFormat[property];
  41.             }
  42.             return newTextFormat;
  43.         }
  44.     }
  45.    
  46.     // override the transform method
  47.     function transform(style:Object):TextFormat
  48.     {
  49.         var format:TextFormat = super.transform(style);
  50.         for (var property:String in style)
  51.         {
  52.             switch (property)
  53.             {
  54.                 case "leading": format = negativeLeadingFix( format, stripUnit(style[property]) ); break;
  55.                 case "blockIndent": format.blockIndent = stripUnit(style[property]); break;
  56.                 case "tabStops": format.tabStops = String(style[property]).split(","); break;
  57.                 case "bullet": format.bullet = (style[property]=="true"); break;
  58.             }
  59.         }
  60.         return format;
  61.     }
  62. }


You can use it like the normal TextField.StyleSheet:

Actionscript:
  1. css:TextField.StyleSheet = new ExtendedStyleSheet();
  2. css.load(cssURL);
  3. /*
  4. .....
  5. */


14 Responses to “Extending CSS capabilities in Flash”

  1. Playfool » Extending CSS in Flash Says:

    […] sh I was writting my own TextField Class at work and I noticed this post on Lessrain which seems to get around the problems with you not being able to use the Css propertiers lik […]

  2. Thomas Says:

    I had to add a fix to the class to address a well known bug in Flash ignoring negative leadings.
    See live docs

    You can work around this bug by setting the leading in the TextFormat constructor. See comments in the class code…

  3. Thomas Says:

    I found yet another annoying bug: attributes in the CSS file must be followed immediately by the colon.

    this works
    color: #000000;

    …this doesn’t
    color : #000000;

  4. François Says:

    Did you know that you can access to ALL Textformat properties directly in your styled text? Ok, it’s not in the CSS, but you can write this:

    <textformat leading=’6′><p class=’bodytext’>My text</p></textformat></pre>

  5. Umka ホスティング Says:

    I am not sure if it is a fflash bug or not, but when you load external html tagged file and external css is applied, whe links look ok until you rollover.

    When you rollover the lines of text change there position which makes an unpleasent effect.

    you can see at links - http://www.ai-web-hosting.com/links-j.html
    Any ideas how to fix it?

  6. cedric Says:

    another way to set negative leading :
    try passing all the args in the Constructor function…

    // font:String, size:Number, color:Number, bold:Boolean, italic:Boolean, underline:Boolean, url:String, target:String, align:String, leftMargin:Number, rightMargin:Number, indent:Number, leading:Number
    var fmt = new TextFormat(”Arial”, 20, 0xff0000, false, false, false, “”,”" , “left”, 0, 0,0 , -12);

    leading WILL WORK (crazy thing!!!)
    I suspect Macromedia to have a ‘Math.abs()’ somewhere it shouldn’t ;) like in the setter method of TextFormat’s leading property

  7. jonathan Says:

    Passing the negative leading in constructor does work - though I am encountering a strange effect - the second and or 3rd lines disappear - though the text height measures as if they were there. Same in test publishing and in html page. Any one else have this issue? (Mac OsX, v7.24 of plugin)

  8. ulf Says:

    ok guys! Leading works fine! But what about setting the letterSpacing to floating point (noninteger) values? TextFormat won’t work while using stylesheets and setting the letter-spacing in the stylesheet doesn’t allow you to set the value to floating point (noninteger) values (such as 2.6). Any Ideas?

  9. LutinCapucheBlog » Says:

    […] t en classes Un article intéressant pour l’extension de la classe : lessrain Entry Filed under: Flash AS2 Leave a Comment Name Required Email […]

  10. Davey’s Flash Blog » Blog Archive » Internationalization (Localization) of Flash Applications with Flash 8 (AS 2) Says:

    […] apanese and am working on Greek and Chinese. Notable Links: Flash and CSS: http://www.blog.lessrain.com/?p=98 http://www.connectedpixel.com/blog/fonts/cssembedding Flash Shared Font Lib […]

  11. Jaime Says:

    Thanks it works .

  12. James Says:

    I know this is an ooooooooooold post, but in response to the question raised by ‘Umka ホスティング’ above, and for the sake of anyone stumbling across this post like I just did… the problem is the autoSize property.

    A html textfield, with tags styled by a Flash StyleSheet, jumps around when rolling over said tags… only when this text field is multilined, with a set width, and set to autoSize.

    The solution is… after you’ve populated that html textfield (ie. set its htmlText property), capture the dimensions of said textfield, turn off autoSize, then set said textfields _width and _height properties.

    Eg, after setting the htmlText property…

    /*
    SNAPSHOT…
    /
    var o:Object = { w:Math.ceil(txt._width), h:Math.ceil(txt._height) };
    /

    TURN OFF AUTOSIZE…
    /
    txt.autoSize = false;
    /

    SET THE WIDTH AND _HEIGHT…
    */
    txt.
    width = o.w;
    txt._height = o.h;

    …problem solved.

  13. James Says:

    Damn. That last post had all its less than and greater than tags stuffed up. Oh well, dear moderator, if you can be bothered fixing it, please do so, otherwise, meh. Internet’s loss.

  14. David Hay Says:

    I know this is old but just in case you’re having the same trouble as ‘Umka ホスティング, you can fix it with autoSize if you do TextFieldAutosize.CENTER.

Leave a Reply