Ask Reuben

Right Justified Labels

Why don’t my field labels align?

( Also how can I hide and/or localize text and/or apply a presentation style to a field label? )

To understand why your right justified field labels may not right align as intended, it is first necessary to have an understanding of …

  1. fonts, and the concept of monospaced fonts, and proportional fonts.
  2. how field labels inside a .per are compiled as a LABEL widget with a posX and width/gridWidth property.

A font has the property that it is either monospaced or proportional.  A monospaced font has the property that each character takes up the same amount of space.  So no matter what the characters, any two words with the same number of characters will take up the same amount of space. The text below, each line has 6 characters

Genero
iiiiii
MMMMMM
WWWWWW
000000
123456
Little
Medium

A proportional font has the property that each character will take up a different amount of space depending up on the character.  Typically i is the narrowest, whilst M or W are the widest.  So compare the same test cases as above using a proportional font

Genero

iiiiii

MMMMMM

WWWWWW

000000

123456

Little

Medium

Note how the line with just i’s is narrow whilst the line with just W’s is a lot wider.

The second thing to understand is how Genero handles the case where you have raw text inside GRID, SCROLLGRID or SCREEN container when compiling a form.  The key thing to note is that for each bit of clearly identifiable text, a LABEL widget is created and it has a posX attribute and a gridWidth attribute computed from where the raw text begins and end.  If you look in the compiled .42f in a text editor you will see these two attributes.

If you defined a GRID like so …

LAYOUT
GRID
{
    Login [f01       ]
 Password [f02       ]
}
END
END
ATTRIBUTES
f01 = formonly.login;
f02 = formonly.password, INVISIBLE;

… if you look in the .42f you will see the Label node with posX and gridWidth attributes …

<Label text="Login" posY="0" posX="4" gridWidth="6"></Label>
...
<Label text="Password" posY="1" posX="1" gridWidth="9"></Label>

… and when the form is previewed or run you will observe that the Login and Password are NOT right-aligned like the developer intended …

That is because the “Login” has been defined to start in column 4  whilst the “Password” has been defined to start in column 1, and although the addition of the gridWidth means they should end in the same place, with a proportional font, there is no guarantee that the ending position of the n from Login and the d from Password will equate to the same position.  The form compiler is not smart enough to deduce that the developer intended the fields to be right-aligned and add a justify=”right” attribute.

You might also ask yourself the following questions with raw text inside forms defined like this?

  • How can I hide the text?
  • How can I assign a presentation style to this text i.e change colour?
  • How can I use localization to change the text of this label?

The solution to the alignment question and the other questions is to define the LABEL explicitly.  To get the right alignment, then you can add the JUSTIFY=RIGHT property to explicitly signify you want the text to right-align.  We do have a section introducing this concept in the documentation.

The above example with LABEL’s explicitly coded, the code looks like …

LAYOUT
GRID
{
[l01 |f01 ]
[l02 |f02 ]
}
END
END
ATTRIBUTES
LABEL l01: lbl_login, TEXT="Login", JUSTIFY=RIGHT;
LABEL l02: lbl_password, TEXT="Password", JUSTIFY=RIGHT;
f01 = formonly.login;
f02 = formonly.password, INVISIBLE;

… the Label nodes in the .42f have the same posX, gridWidth values, the justify attribute is now populated, and there is now also a name attribute …

<Label name="lbl_login" width="10" text="Login" justify="right" posY="0" posX="1" gridWidth="10"></Label>
...
<Label name="lbl_password" width="10" text="Password" justify="right" posY="1" posX="1" gridWidth="10"></Label>

… and now the two labels are right aligned as the developer intended …

One thing I would recommend is to make the LABEL widget as big as the space allocated.  A temptation is to make it only as wide as the original text.  So in this case, the width was 10 rather than 5 for Login and 8 for Password.  This future proof’s your LABEL for future code changes.

Explicitly using a LABEL widget in your form also has a few other advantages over raw text …

  • it allows you to assign a name to the label so you can use it in methods such as ui.Form.elementHidden to show/hide an individual label.
  • it allows you to use a presentation style via use of the STYLE attribute, to alter an individual label’s appearance.
  • it allows you to use localized strings for the label e.g. TEXT=%”login”
  • and is also a better fit for when you decide to use .4fd and GUI Form Designer forms.  After all, in the GUI Form Designer you add these LABEL widgets, rather than typing in raw text.

For these reasons I would encourage you to explicitly use LABEL widgets inside a .per, rather than having raw text inside your .per, even if your coding standard is to left-align labels.   (Similarly table column headers instead of being raw text inside a form can be coded using TITLE property to gain similar advantages as in this example).

As an interesting aside to finish, on the subject of monospaced and proportional fonts, I also recently came across this interesting article https://blog.usejournal.com/proportional-vs-monospaced-numbers-when-to-use-which-one-in-order-to-avoid-wiggling-labels-e31b1c83e4d0.  So if choosing to use a proportional font, it is normally desirable to choose one where the digits 0-9 take up the same amount of space.  Most proportional fonts have this property, but some don’t.