How to create HTML Pages, Dialogs, and User Interfaces that Need No Resizing after Translation
| Introduction | |
| Goals | |
| HAL Quick Reference | |
| HAL Rules | |
| HAL Demo and Code | |
| HAL Testing | |
| HAL Coding Tips | |
| Conclusion |
Until recently the majority of user interfaces on the Windows® platform have been created using WIN32® dialog boxes or Visual Basic® Forms.
These days, many developers are taking advantage of the richness of HTML to create an application's user interface. This is great for development, but causes huge problems for applications that need to be localized into multiple languages. That is because HTML interfaces are a lot harder to resize and readjust after translating the text.
And it's not just user interfaces that are hard to resize after translation. Ordinary Web pages that utilize the full power of cascading style sheets (CSS) can be an absolute nightmare!
In my own company, we found that the cost of translating, resizing, and testing HTML user interfaces is far greater than that of WIN32 dialog boxes.
But with the right coding standards, all HTML user interface elements can be constructed so that international (the localization team) will have zero re-sizing or repositioning work to do.
HAL (i.e., HTML AutoLayout) sets out to show some of the key coding standards to follow. In this documentation, I list a series of rules and the key reasons for these rules. This is followed by a set of coding samples. For this article, I assume that you are familiar with the basic terminology and processes of localizing Web sites and/or applications.
A key point to bear in mind is that HAL is one approach for achieving zero international resizing. There are probably countless other methods. This is fine so long as they achieve the same end result. Even so, other methods will probably benefit from using some of the HAL rules.
Another point to bear in mind is that there are already many HTML dialog boxes out there that are mostly HAL compliant. This is especially true for dialog boxes (or windows) that were designed to be resizable.
Before reading any further it's probably worth checking out the HAL Demo</haldemo/default.htm>.
Adopting HAL will deliver the following important benefits:
1. | Localizers need to translate only the strings. The user interface (UI) will automatically size all controls to fit. |
2. | The preparation work is done once for the original (usually English) version of the product and does not have to be repeated for multiple languages. |
3. | It completely removes the error-prone step of dialog box sizing from the localization process! It also completely removes other steps from the process, such as trying to recycle dialog box sizing from previous versions of the product or from other languages. |
4. | It leaves no opportunity to add cosmetic bugs. Thus the quality of localized dialog boxes should match those in the original English product. |
5. | International teams do not have to fix dialog-box bugs caused by resizing. If there are any problems with the translated UI, the developers fix these bugs and the fix then applies to all other languages. This prevents the bugs from reoccurring in other languages. At worst, the only change international will need to do is re-translation, usually to provide shorter strings. |
6. | There should be an order of magnitude fewer dialog-box bugs to find. In turn, this will greatly reduce or eliminate the number of cosmetic bug testing required. A key point to remember is that a lot of re-testing is required after bugs are fixed. Without any fixing, the amount of testing needed instantly drops. |
7. | Update handling probably takes more time than the initial sizing, because localizers try to adjust dialog boxes when strings change. It's also a step that can introduce quite a few dialog-box bugs of its own if updates are not handled correctly. This problem is also completely removed. |
8. | For developers, dialog boxes can become easier to manage, because it can be faster to add new controls to dialog boxes without having to adjust all the other controls. HAL rules are particularly suited to creating resizable dialog boxes. Also, if dialog-box metrics need to change, you only have to make the change in one place (a global style sheet), rather than in every single dialog box. The global enforcement of dialog-box metrics also ensures cleaner and more consistent UI across the product. |
Of course, nothing of value is completely free. There are some costs involved in adopting the HAL rules.
1. | The pages/dialog boxes can be more complex to construct. This creates the possibility for the original English dialog boxes to have more initial bugs than before. |
2. | The need to use some extra code in the onload event (to size buttons) will also slow down performance. But this is not noticeable by end users. |
3. | The level of control over some element positions is not as finely tuned, and they will change as the size of the dialog-box changes. |
Note: The extensive use of tables versus absolute positions does not slow down performance.
Before tackling the individual rules it's worth spelling out exactly what they are attempting to achieve.
Good-Looking Dialog Boxes
This means the dialog boxes must still look as good as dialog boxes constructed with absolute positions and sizes.
It also means that the dialog boxes must conform to user interface style guides.
No Control Sizing
The dialog box must be constructed so that the localizer does not need to make any adjustments to the individual controls (positions or sizes) when the text is translated.
Dialog Box Width and Height Adjustable
The only factor that the localizer can adjust is the dialog box width and height (except for dialog boxes that must have a fixed size). Elements are constructed so that they scale to the available dialog box width and height.
Easier to Translate
A number of these rules attempt to make the UI as painless to translate as possible.
Language Support
The solution must work correctly for all languages. This includes all Western European, Eastern European, Cyrillic, Middle East, and Far East languages.
Specifically, for Middle East, the localizer needs to set only the DIR attribute in the HTML tag for the dialog box to flip correctly (e.g., <HTML dir=rtl>. They do not have to do any alterations to individual items to get them into the correct position. This includes not having to set any alignment attributes (e.g., align=right).
Platform Support
HAL has only been tested against Internet Explorer 4.0 and later.
The solutions here have not been tested against older versions of Internet Explorer, Netscape, or other browsers.
Good Performance
The solution needs to offer good performance. The baseline is against dialog boxes constructed using absolute positions. HAL's method of using tables does not suffer any performance disadvantage.
We recommend that everyone read the full document to understand the rules and the reasons for them. However, this quick reference is a useful guide to have at hand after you've gone through the rules. (Of course, some of these rules won't make sense until after you've read the full document.)
Rule 1: Never Use Absolute Positions
Do not use CSS properties for absolute positions. The offending combinations are setting the position to absolute and setting fixed left and top values. The following sample shows the wrong way:
<DIV style='position:absolute; left:2em; top:2em; width:5em'> </DIV>
Read full details...<link to Rule 1 heading>
Rule 2: Dialog Boxes Should Use The Available Width and Height
Design the dialog box to take advantage of the available width and height. There are two ways to do this. Build the dialog box using tables sized to width=100%. Or use expression-based positions and sizes based on the dialog box size (e.g., body.clientHeight).
<body>
<table width=100%> <!-- one or more tables -->
<U can contain other tables U>
</table>
</body>
<!-- Sample 2: div sized to take up half width and height of dialog box -->
<div style='position:absolute;
height: expression(document.body.clientHeight / 2);
width: expression(document.body.clientWidth / 2); '>
</div>
Read full details...<link to Rule 2 heading>
Rule 3: Each Control Should Be in a Separate Cell
Try your best to put each control into a separate cell. Doing this will allow the text to wrap independently, and the flipping and alignment to work for Middle East languages.
Read full details...<link to Rule 3 heading>.
Rule 4: Allow Wrapping Text
Do not use the "nowrap" attribute for table cells that contain text (e.g., <td nowrap>). This will prevent the text from wrapping when it grows longer. You can use this only when you want the text to stay on one line and there is enough room for it to grow for all languages.
Read full details...<link to Rule 4 heading>
Rule 5: Separate Check Boxes and Radio Buttons from Labels
Place the labels for checkboxes and radio buttons in cells separate from the controls. This allows them to wrap correctly when the text grows longer. However, you should still design the dialog box so that the text has a reasonable chance of staying on one line when it is translated.
If you don't do it the wrapped text will look like this:
![]()
instead of this:
![]()
<!-- how to code check boxes correctly -->
<table cellspacing=0 cellpadding=0> <tr>
<td valign=middle width=24px>
<input id=x type=checkbox accesskey=C>
</td>
<td valign=middle>
<label for=x> <u>C</u>hoose me </label>
</td>
</tr></table>
Read full details...<link to Rule 5 heading>.
Rule 6: Leave Room for Growth and Avoid Fixed Widths
Try to leave adequate room for longer translations. The first part is to set the cell width to a percentage of the dialog box width so that it can grow with the table.
The next basic rule of thumb is to leave room for 300% growth on short items (< 10 characters), 200% growth on medium length items (10 to 20 characters) and 100% growth on large items (> 20 characters).
Do not use fixed width for cells or controls that contain text, unless you know there is enough room for the translations that will be used in every language. If you need to specify a size, it should be a percentage size (e.g., 10%).
However, you should avoid using too many percentage sizes. Try to leave the HTML layout engine to figure out as much of the layout as possible. This way the dialog box will look good no matter what text is present in the controls.
There are exceptions for buttons, list boxes, and input boxes.
Read full details...<link to Rule 6 heading>
Rule 7: Methods for Sizing Buttons, List Boxes, and Group Boxes
Use classes for buttons. All buttons that need to have the same width should have the same class. Call HAL code in the onLoad event to adjust this button size as needed.
The best solution for list boxes is to leave room for growth. Otherwise, you need to employ the same solution as buttons.
The best solution for group boxes is to leave room for their text to grow, and to size the actual boxes to grow with the table cell. The cell that contains them should be set to "nowrap". Controls inside the group box should be in a table.
Read full details...<link to Rule 7 heading>
Rule 8: When to Set Height
Avoid fixed height table cells. Do not set the cell height for cells that contain text. You may set the height for single line controls as long as the unit of measurement is in font size units.
Every element in the style sheet should have a line height set. Otherwise, the look of the page will change if the user sets the Text Size in Internet Explorer. Remember to also set this for the table cells (td).
<style>
body, td {font-family: tahoma; font-size: 8pt; line-height: 10pt;}
... do the same for all other elements used in the page ...
</style>
Read full details...<link to Rule 8 heading>
Rule 9: Do Not Use Left or Right Align
Do not use "align=left" or "align=right" for any table cell (or the equivalent CSS styles). Otherwise, they will not adjust correctly for Middle East languages. The proper solution is to push cells to the left or right by adding "oversized" cells next to them. Also ensure that "margin-left" and "margin-right" values are equal.
<!-- How to push an OK button to the right without using right align -->
<tr>
<td width=100%> </td>
<td nowrap><button>OK</button> </td>
</tr>
Read full details...<link to Rule 9 heading>
Rule 10: Avoid Inline CSS With Values That International Needs to Change
Keep all CSS values that international may need to change in style sheets. Do not place them in style attributes sprinkled throughout the page. Also, avoid using <font> tags with face attributes throughout the page; specify fonts in the sheet as well.
<!-- Bad Sample -->
<span style = "font-size: 10pt; font-family: Arial;"> Hello </span>
<font name = arial> some text </font>
<!-- Good Sample -->
<style> .myStyle {font-size: 10pt; font-family: Arial;} </style>
<span class = myStyle> Hello </span>
Read full details...<link to Rule 10 heading>
Summary Do not use CSS properties for absolute positions. The offending combinations are those setting the position to absolute and setting fixed left and top values.
It is never acceptable to use absolute positions for any UI element. This is the fundamental rule. This is because absolute positions on elements prevent them from being automatically positioned and sized. Absolute positions are specified using Cascading Style Sheets (CSS).
Position, left, and top are the key CSS properties that control position.
Therefore, the following code is forbidden:
<DIV id = idFindWhatLabel style = "position: absolute; left: 0.98em; top: 1.2168em;
width: 4.8em; height: 1.2168em;">
Fi<U>n</U>d what:
</DIV>
Absolute Position Exceptions
As with all HAL rules, there are exceptions. The exception for this is that you may use absolute positions if they are expression-based. See the next rule for details on this.
Summary Design the dialog box to take advantage of the available width and height. There are two ways to do this. Build the dialog box using tables sized to width=100%. Or use expression- based positions and sizes based on the dialog-box size (e.g., body.clientHeight).
The goal of this rule is to ensure the dialog box can take advantage of the available width and height. In most cases the localizers are allowed to set only the initial width and height of the dialog box.
Fixed dialog-box widths should be used only when absolutely necessary (e.g., the dialog box must match the size of other tabs in tabbed dialog box).
There are two ways to achieve this:
Expression-Based Positioning Based on Size
In this case, the major elements (tables, divisions, etc.) of the dialog box are sized using CSS expressions. The expressions are all ultimately based on the overall size of the dialog box. For example, you might size an item to ¼ the size of the dialog box and place it in the bottom right corner. Or you might center it inside the dialog box.
The fundamental point is that everything is sized to fit within the borders of the dialog box and that the localizers never have to deal with these expressions.
For example:
<!-- div sized to take up half the width and height of the dialog box -->
<div style='position:absolute; left: 0; top: 0;
height: expression(document.body.clientHeight / 2);
width: expression(document.body.clientWidth / 2); '>
Dialog boxes are harder to construct this way, but localizers won't have to be concerned with the construction.
The Entire Dialog Box Consists of Tables
In this case, the entire dialog box must be contained within tables that are sized to 100% of the width of the dialog box (e.g., <table width=100%>). Each of these tables should have the same cell spacing and cell padding.
If there is a single main table, you may also size it to 100% of the height of the dialog box (e.g., <table height=100%>) but this isn't always necessary.
The tables can contain other tables.
This solution is the best for getting all items to size correctly when they are localized and to maintain their proper relative positions. Of course, this is not an easy thing to do. It takes careful planning and you need to explicitly decide up-front how controls are related to each other.
Key decisions are:
1. | Which controls are the same size. These must be contained in the same cell of the table, but can be on a different row. |
2. | Which controls are left- or right-aligned with each other. |
3. | Which controls can push other controls to the right. |
4. | Which controls can have a fixed size (see the rule for this). |
<body>
<!-- Use one main table -->
<table width=100%>
<U can contain other tables U>
</table>
</body>
Example
This example shows a regular dialog box that is constructed as one table:
Now with the tables cell shown:
Summary Try your best to put each control into a separate cell. This allows the text to wrap independently and the flipping and alignment to work in Middle East languages.
Avoid putting more than one control in the same table cell.
This applies to all controls that have text in them. This is necessary so that:
1. | The text on the controls can independently wrap. |
2. | Flipping and alignment work correctly for Middle East languages. |
There are a few cases where you can ignore this rule:
1. | Rows of buttons are all the same size. |
2. | Labels are next to dropdowns. |
However, it's really better in the long run if you just stick with separate cells.
Summary Do not use the "nowrap" attribute for table cells that contain text. This will prevent the text from wrapping when it grows longer. Use this only when you want the text to stay on one line and there is enough room for it to grow for all languages.
Another major advantage of tables is that the text will automatically wrap if it does not fit in a table cell. This greatly increases the amount of space available for translated text.
Of course, you may wish to design the initial dialog box so that the English text does not wrap. This is done by setting the initial size (see below for how to do this) of the cell large enough to contain the text.
It is not permissible to do this by using the nowrap attribute, except in the limited circumstances outlined below. Using the nowrap attribute prevents localizers from being able to trade off the width of a control against the height, which is often necessary to maintain the overall balance in a dialog box. It guarantees that no matter how long the text has to become, it will still display on a single line.
Permitted Workarounds to Prevent Wrapping
Here's the wrong way to stop text from wrapping because it uses the nowrap attribute.
<TD nowrap>
Fi<U>n</U>d what:
</td>
The best solution is just to set an initial size for the table cell (see the separate rule on why you should try to use this as little as possible):
<TD width=20%>
Fi<U>n</U>d what:
</td>
Another way to prevent text from wrapping in a table is to use the non-breaking space name entity ( ) rather than spaces between words.
<TD>
Fi<U>n</U>d what:
</td>
However, the use of non-breaking spaces makes the terms harder for localizers to work on.
Nowrap Exceptions
You may use nowrap in the following cases:
1. | There is adequate room for the text to display on one line in all languages. |
2. | It is highly likely that a single line is good enough for all languages, and there is adequate room to allow the text to grow. In the example below, Address is not allowed to wrap, but this is quite reasonable because there is room to grow by 300% and still the edit box next to it would have enough room: |
3. | The cell that contains text that should always display on a single line. A good example of this is a horizontal grouping. See under Coding Samples. In fact, it is a much better option to use NoWrap in these circumstances. This is because non-breaking space entities can make terms harder for localizers to work on.
|
4. | If the cell contains only input boxes, buttons, or dropdowns you may also use nowrap. An example is the three buttons below, which share the same cell. |
Summary Place the labels for checkboxes and radio buttons in cells separate from the controls. This allows them to wrap correctly when the text grows longer. However, you should still design the dialog box so that the text has a reasonable chance of staying on one line when it is translated.
First of all, you should try to design the dialog box so that there is enough room for the text to grow and still stay on one line. However, you also need to design for the eventuality that the label may become too long and will need to wrap.
In order for check box and radio button labels to wrap correctly (which may be needed if the text grows when it is translated), you need to separate them from the controls.
If you don't do it the wrapped text will look like this:
![]()
instead of this:
![]()
Separate cells from controls by placing the checkbox in a table cell next to the label.
<table cellspacing=0 cellpadding=0>
<tr>
<td valign = middle width=24px>
<input id = chkWholeWord type = checkbox accesskey = w>
</td>
<td valign = middle>
<label id = lblWholeWord for = chckWholeWord>
Match <u>w</u>hole word only
</label>
</td>
</tr>
</table>
Note: Depending on your preferences, you may wish for the check box and radio buttons to align with the top of the text. Do this by changing to "valign = top" for the cells.
This example also shows an element with a fixed width (width=24px). One of the key rules is to avoid this, but this is a clear exception because this element (a check box) contains no text and will be the same size in all languages.
You may ignore this rule if you know absolutely that the label will fit on one line in all languages and has adequate room to grow.
Note: Remember, do not to use nowrap for the table cell containing the label.
Summary Try to leave adequate room for longer translations. First, set the cell width to a percentage of the dialog box width so that it can grow with the table. The next basic rule of thumb is to leave room for 300% growth on short items (< 10 characters), 200% growth on medium length items (10 to 20 characters) and 100% growth on long items (> 20 characters).
Summary Do not use fixed width for cells or controls that contain text, unless you know there is enough room for the translations that will be used in every language. If you need to specify a size, it should be a percentage size (e.g., 10%). There are exceptions for buttons, list boxes, and input boxes.
It is not acceptable to specify a fixed size width for any item that contains text. We define a fixed width to be any unit of measurement other than a percentage. That includes "em" (font height), "ex" (height of "x"), "px" (pixels), "in" (inches), "cm" (centimeters), "mm" (millimeters) "pt" (points = 1/72 inches) and "pc" (picas = 12 points).
The basic principle of using tables is to ensure that the cells will automatically grow when the text is made longer. This means the right sizes to use are percentage sizes (e.g., 30%). Because all of these controls are contained in table cells (the entire dialog box must be one table), it means these controls are sized to a percentage of the cell that contains them. And because this cell in turn is sized to a percentage of the overall table (which is sized to 100% of the dialog box) it means the control will grow as the dialog box grows.
Bad sample:
<div style = "width: 100px">
Good sample:
<div style = "width: 50%">
You Can Specify A Fixed Width for Items with No Text
The following controls do not have text and so it is okay to specify a fixed size:
1. | Edit boxes (with no default text) |
2. | Radio buttons or check boxes (so long as the text is in a separate control) |
3. | Images (so long as the images do not have to be localized) |
The most common unit of measurement for fixed sizes is pixels (e.g., 100px) in this case.
Provide Adequate Room for Text Growth
You can supply a fixed width for certain controls and cells if you leave adequate room to accommodate any possible (but unknown) translation.
The basic rule of thumb is to leave room for 300% growth on short items (< 10 characters), 200% growth on medium length items (10 to 20 characters) and 100% growth on large items (> 20 characters).
Of course if you know all possible translations for the item you can also set the width to fit the widest translation. But this only applies only to items such as OK, Help, Cancel, Yes, and No buttons. But remember that nobody out there has actually calculated these widths!
The following is a good example of this. You could specify fixed widths for Favorite Pet, Cat, and Dog because there is plenty of room for these to grow across the dialog box.

Percentage Sizes
Another acceptable solution is to size the control to a percentage of a cell width where that cell width is set to a percentage of the size of the dialog box.
This means that as the localizer grows the width of the dialog box (remember they are allowed to change only the width or height of the overall dialog box, never the controls) the control will itself grow. This gives the localizer the opportunity to make additional room for the control text.
<td width = 25%>
<input type=text style = "width:100%">
</td>
Note: This sample shows inline CSS for brevity. This should be replaced with a style sheet class.
There are also a few quirks in Internet Explorer when using percentage sizes in combination with cells that span multiple columns. Please see the coding examples <hotlink/bookmark to Coding Tips section>for more details on this.
Specify as Few Percentage Sizes as Possible
Summary Avoid using percentage sizes (e.g., width=30%) whenever you can. Try to let the HTML layout engine to figure out as much of the layout as possible. This way the dialog box will look good no matter what text is present in the controls.
This sub rule applies to sizes given as a percentage. This is a percentage of the size of the element that contains them (body, table cell, or div).
The goal is to specify as few relative sizes (other than 100%) as possible. This is because you want to rely on the HTML layout engine to do most of the work for you. However, in order to maintain proper UI proportions after a dialog box is localized you may need to specify the widths of some elements.
Remember you need to take another HAL rule into account here, i.e., these proportional sizes should be specified in the style sheet, except for table cell widths.
<style>
.myStyle {font-size: 10pt; font-family: Arial; width: 80%;}
</style>
Here is a fuller example. This shows a dialog box from Microsoft Excel 97 (recreated as HTML of course):
<table width=100%>
<tr>
<td><img width=273 height=203 src="./hal/img022.jpg"></td>
<td><img width=272 height=226 src="./hal/img024.jpg"></td>
</tr>
</table>
Both of these dialog boxes are the exact same width and contain all the same text and controls.
In the example on the left there are no widths specified for the main 3 columns in this dialog box. However, in the example on the right, the widths were fixed at 33%. As you can see, this leads to the text wrapping unnecessarily and the dialog box becoming longer when it does not need to.
Summary Buttons: Use classes for buttons. All buttons that need to have the same width should have the same class. Set a fixed width in the button class. Call HAL code in the onLoad event to adjust this button size as needed.
Summary The best solution for list boxes is to leave room for growth.
Summary The only solution for group boxes is to leave room for the text to grow.
Unfortunately, there are some shortcomings in HTML where text in some elements does not cause a table cell to grow wider if it is truncated. The elements are:
1. | <BUTTON>. |
2. | <INPUT>. See the rules on separating radio buttons and check boxes from their labels <holink to Rule 5 section>and rules on leaving adequate room for growth<hotlink to Rule 6 section>. |
3. | <SELECT>. This is not automatically sized to fit the largest <OPTION>. This is a list box. |
4. | <FRAMESET>. This is not automatically sized to fit the text for its <LEGEND>. These are used to construct group boxes. |
This rule outlines the strategies you can use to get around these problems.
How To Size Buttons
Buttons are different from most other controls for the following reasons:
1. | There is usually a set of buttons, and each button in that set needs to have the same size. You cannot leave them to size themselves automatically because this would lead to buttons with different sizes. But if you set the size for buttons, the text in them can be truncated. |
2. | The button text must usually always be on a single line. This removes the choice of using word wrap for longer text. |
3. | Buttons are not the kind of control where you can leave room for growth. Buttons with lots of padding inside them look terrible. |
4. | The same-size buttons can be spread throughout the dialog box or page. This means you can't rely on table behaviors to keep the sizes the same if they share the same column. |
Solution 1: Specify Fixed Widths
The simplest solution is to specify fixed widths for the buttons using a style sheet. All buttons that need to have the same size should use this class.
You only need to alter the style sheet to attain the size needed.
<style>
.mainButton {width: 10em;}
</style>
This is a great solution because the only thing the localizer has to do is alter the style sheet if any of the buttons are truncated. This is a fairly simply task and it's not a lot of work. However, it still means the dialog boxes need to go through testing after localization because it could lead to truncated button text.
Note: It is not possible to leave enough size available for the buttons to grow for any translation without making the buttons look ugly.
Note On Button Measurement
A key sub rule needs to be mentioned here. Whenever you specify fixed widths for items with text, you should not do it using pixels as the unit of measurement.
<style>
.mainButton {width: 10px;} /* example of the wrong way to do it */
</style>
This is because the text could be truncated if the user switches to a larger font size (as they can do by choosing "Large Fonts" in the Display Control Panel). It is far better to use "em", i.e., units of the font height.
Solution 2: Do Not Specify Button Widths
With this solution you do not specify any widths for the buttons. This leaves the HTML layout engine to figure out the size for each button. Obviously, this can lead to buttons with different sizes.
The solution is to use simple code (provided by HAL) that finds all buttons with the same class and adjusts the widths.
<script langauge=jscript src=HALsize.js></script>
<style>
button {font: 9pt tahoma; padding-top: 0px;
padding-bottom: 0px; padding-right: 6px; padding-left: 6px}
.ButtonA{;}
.ButtonOKCancel {;}
</style>
<body onload='HALsizeButtons(document, "ButtonA", false);
HALsizeButtons(document, "ButtonOKCancel", true);'>
<button id=butOne class=ButtonA>One Button</button><br>
<button id=butTwo class=ButtonA>Other Same Size Button</button>
</body>
The HALsizeButtons function takes the following arguments:
1. | Document. The document containing the buttons. |
2. | Class Name. The name of the button class. |
3. | Enforce Minimum Width. This will enforce a minimum width for the buttons. The minimum used is the standard size of an OK button in Windows. |
You need to call HALsizeButtons in the onLoad event for all button classes. You need to call this function again if different text is substituted onto the buttons dynamically.
Solution for Unwanted Button Padding
The biggest disadvantage of this method is that you have no control over the padding around the text in these buttons. Internet Explorer appears to make the padding around the buttons proportionate to the size of the button text.
This could lead to undesirable padding around larger buttons (as show below). Luckily, the text on buttons tends to be shorter in most cases.
However, there is a solution for this. You can add <LABEL> tags inside the buttons. The fixButtons function will use these if they exist to calculate a more precise size for the label text.
<button class=ButtonA><label id=butOneLabel>One Button</label></button><br>
<button class=ButtonA><label id=butTwoLabel>Other Same Size Button</label></button>
Note: The ID attributes in the label tags are optional, but localization will really benefit if these are present.
Alternative Using Expressions
Note: Special thanks to Michael Winser for providing this solution.
The same result can be achieved using expressions (but this will only work with Internet Explorer 5.0).
However, it also requires more changes to the files as shown below. Another disadvantage is that it can require a lot of extra computation whenever you do any manipulation on the page.
The key advantage is that you do not have to call any functions if the text on the buttons is altered dynamically.
<script langauge=jscript src=HALsize.js></script>
<style>
button {font: 9pt tahoma; ; padding-bottom: 0px; padding-top: 0px;}
.ButtonA { width: expression(HALbuttonWidth(sizeButtonA, false))}
.ButtonOKCancel { width: expression(HALbuttonWidth(sizeOKCancel, true));}
</style>
<button id=butOne class=ButtonA><label id=sizeButtonA>
One Button</label></button><br>
<button id=butTwo class=ButtonA><label id=sizeButtonA>Other Same Size
Button</label></button><br>
The key here is that all the buttons that need to share the same size must have the same class. They also must have labels and the labels must have the same ID attribute. Unlike the previous solution, the labels are not optional.
Instead of specifying a width for the buttons, expressions are used. The expression calls the HALbuttonWidth function and passes in the identifier (ID) of the labels in the same size buttons.
Button Sizing Summary
1. | Create a class for the buttons, but do not set a width in this class. |
2. | Set the same class on all buttons that need to have the same width. |
3. | If you are concerned about optimizing the padding around the buttons, use labels inside them. |
4. | For each button class, call the HAL function to HALsizeButtons during the onLoad event. |
How to Size List Boxes
Summary The best solution for list boxes is to leave room for growth.
List boxes share some of the same characteristics as buttons:
1. | The text can be truncated. |
2. | The text for each item must always be on a single line. This removes the choice of using word wrap for longer text. |
3. | There can often be a set of list boxes that need to have the same size. |
But unlike buttons, list boxes have some characteristics that lead to a simpler solution:
1. | List boxes are the kind of control where you can leave room for text growth and they still look fine. This is good because just like buttons, these controls will not size automatically to fit the largest piece of text. |
2. | List boxes that need to have the same size are generally parallel. In other words, they can easily share the same table column. |
Here are the solutions, in order of recommended use:
List Box Solution: Leave Room For Growth and Size to Cells
There are two parts to the proper solution. The first is to leave adequate room for growth. Follow the standard rule for text growth for these controls. This means leaving room for 200% growth for short items and 100% for longer items.
The second part is to place all related list boxes into similarly sized cells and then set the size of each list box to a percentage of the cell size (usually 100%). This cell in turn is a percentage of the overall table size and so can grow as the page grows.
<tr>
<td width = 30%>
<select style = "width:100%">
<option>Bulgaria
<option>Greece
</select>
</td>
</tr>
<tr>
<td> <!-- same column on another row -->
<select style = "width:100%">
<option>Bulgarian
<option>Greek
</select>
</td>
</tr>
Alternative List Box Solution: Adjust Sizes in Code
Even though this is the best solution for buttons, it really should be avoided for list boxes. That's because the first two solutions outlined above should be adequate nearly all the time.
However, if space really is at a premium in the dialog box and you need the list boxes to be as small as possible, you can:
1. | Create a class for each set of list boxes that need to be the same size. |
2. | Do not set a width in this class. |
3. | Apply this class to all list boxes that need to have that same size. |
4. | Call the HAL HALsizeListBoxes function in the onLoad event. This sizes the list boxes to the width of the widest one that shares the same class name. |
<style>
.ListA { }
</style>
<body onload = 'HALsizeListBoxes(document, "ListA"); '>
<select class = ListA>
<option>Bulgaria
<option>Greece
</select>
<select class = ListA>
<option>Hungary
<option>United States
</select>
</body>
The HALsizeListBoxes function takes the following arguments:
1. | Document. The document containing the buttons. |
2. | Class Name. The name of the button class. |
You need to call HALsizeLists in the onLoad event for all list box classes. You need to call this function again if different text is substituted onto the lists dynamically.
How To Size Group Boxes
Summary The best solution for group boxes is to leave room for the text to grow and to have them sized to grow with the table cell. The cell that contains them should be set to nowrap. Controls inside the group box should be in a table.
Group boxes share some of the same characteristics as list boxes:
1. | The text for each item is almost always on a single line. This removes the choice of using word wrap for longer text. |
2. | They are the kind of control for which you can leave room for text growth and they still look fine. |
3. | There can be a set of group boxes that need to have the same size in the dialog box. |
The best solutions available are the same as the first two that apply to list boxes:
1. | Leave plenty of room for the text to grow. |
2. | Place these controls into a table cell so that the control can grow as the dialog box width grows. |
However, you also need set the nowrap attribute for the table cell that contains the <fieldset> and <legend> that make up the group box. This stops other controls from overlapping with the table cell containing the group box.
<td width = 30% nowrap>
<fieldset style = "width:100%; height: 100%">
<legend>Group Box Label</legend>
U controls in the group box should be inside a <table> U
</fieldset>
</td>
Note: Setting the height to 100% is optional. You would do this only if you wanted the group box to align perfectly with another one to its left or right.
The sample on the left below shows the impact of not using the nowrap attribute. The sample on the right has this attribute set.
<table width=80% border=0 cellspacing=0 cellpadding=0>
<tr>
<td valign=top>
<p align=center>
<img width=139 height=60 src="./hal/img028.jpg"></p>
</td>
<td valign=top >
<p align=center>
<img width=195 height=60 src="./hal/img030.jpg" ></p>
</td>
</tr>
</table>
Do Not Specify Table Row or Cell Height
Summary Do not set the cell height for cells that contain text. You may set the height for single line controls so long as the unit of measurement is in font size units.
Do not set a fixed height for any table cell that contains text. This is especially important for table cells. If the text begins to wrap or the localizer has to use a larger font size, the fixed table heights will not look good.
You might try to set a table cell height when you are trying to add horizontal spacing between controls. See the area highlighted in black in the sample picture below:

The wrong way to do this is to set the cell height for the cells containing the dropdown menus or the buttons.
The right way is to add a blank row between them and to set its height:
<TR style = "height: 6px;"> <td colspan=N></td> </TR>
The same applies to the height of controls that can contain text. Avoid this because it will make localization more difficult if localizers need to change the font size of the text in the controls.
Fixed Height Controls
It is perfectly acceptable to set the height on some dialog box controls. But this should only be done for controls that will always use exactly one line of text. This is usually limited to buttons, dropdown list boxes and text input boxes.
However, in all cases this size should be expressed in units that match the font size, so that the control is automatically adjusted if the font size changes.
<style>
button {height: 2.2em;}
</style>
Set Line Height for All Style Sheet Elements
Summary Every element in the style sheet should have a line height set. Otherwise, the look of the page will change if the user sets the Text Size in Internet Explorer. Remember to also do this for the table cells (td).
Every element needs a line-height specified in the style sheet.
Otherwise, if the user sets the text-height for Internet Explorer (e.g., to "Largest" using Text Size on the View menu) it will break the layout.
The trick that most people forget for dialog boxes is to set this for table cells also.
Examples:
<style>
body, td, button {font-family: tahoma; font-size: 8pt; line-height: 10pt;}
</style>
Summary Do not use "align=left" or "align=right" for any table cell (or the equivalent CSS styles). Otherwise, they will not adjust correctly for Middle East languages. The proper solution is to push cells to the left or right by adding "oversized" cells next to them. Also ensure that "margin-left" and "margin-right" values are equal.
Do not use align=left or align=right for any table cell. This prevents the dialog boxes from flipping correctly for Middle East languages. You can use align=center. In most cases these would not have been used. However, there are cases where they are needed, especially in cells with buttons, list boxes or input boxes. A few examples are presented below, along with solutions.
A second arises if you use different values for the margin-left and margin-right properties. When an item is flipped to read from right-to-left, this could cause the text to become unbalanced.
Note: Thanks to Paul Nelson for this tip.
Example for OK and Cancel Buttons
The classic example of using align=right would be for the OK and Cancel buttons below.
The typical code for this is as follows:
<tr><td width=100% nowrap align=right>
<button>OK</button>
<button>Cancel</button>
</td></tr>
Unfortunately, when the document reading order is changed to right-to-left, as required for Middle East languages, it will display as follows:
This is wrong, because the Cancel button should be on the left side of the dialog box. This problem is caused by using align=right. The solution is to use the following code for these buttons:
<tr>
<td width=100%> </td>
<td nowrap>
<button>OK</button>
<button>Cancel</button>
</td>
</tr>
This oversized cell ("width=100%") has the effect of pushing the buttons to the right for normal languages and to the left for Middle East languages -- which is the required result!
Example for Evenly Spaced Buttons
Take a look at the three buttons in the sample dialog box above.
The goal is to have the Add button aligned with the left side of the dialog box and the other controls on the left, and to have the right side of the Remove button right-aligned with controls on the right of the dialog box.
The method is to create a table that spans the width of the dialog box with 3 cells to contain the buttons. The alignment of the three cells is set to left, center, and right, respectively. This can be seen clearer by cutting out the buttons and showing the table borders.
Here is the code needed to create this effect:
<table width=100%>
<tr>
<td width="33%" align=left>
<button class="dlgPushBtn">
<u>A</u>dd...
</button>
</td>
<td width="33%" align=center>
<button class="dlgPushBtn">
<u>E</u>dit...
</button>
</td>
<td width="33%" align=right>
<button class="dlgPushBtn>
<u>R</u>emove
</button>
</td>
</tr>
</table>
However, when the document reading order is changed to right-to-left as required for Middle East languages, it will display as follows:
The Add button is still left-aligned and the Remove button is still right-aligned.
This would cause huge problems for Middle East localizers to track down these bugs and fix them. Luckily, there is a HAL solution.
The solution is to never use align=left or align=right for rows of buttons. The correct method to left-align a button is to use a table with two cells. Place the button in the left cell, and then oversize the right cell so that the button is pushed to the left.
When the reading order is changed, this sub-table will be automatically flipped and the button will be pushed to the right, which is exactly what is needed. The code for this is:
<td width="33%" >
<table width=100% cellpadding=0 cellspacing=0>
<tr>
<td>
<button class="dlgPushBtn">
<u>A</u>dd...
</button>
</td>
<td width=99%> </td> <!-- this is the over sized cell -->
</tr>
</table>
</td>
The correct method for right-aligned buttons is to place the padding cell to the left of the button cell:
<td width="33%" >
<table width=100% cellpadding=0 cellspacing=0>
<tr>
<td width=99%> </td> <!-- this is the over sized cell -->
<td>
<button class="dlgPushBtn">
<u>R</u>emove
</button>
</td>
</tr>
</table>
</td>
No changes are needed for centered buttons.
With the above changes, the dialog box can be seamlessly flipped for Middle East languages:
Note: The same problem and solution applies to list boxes and text input boxes.
Example for Multiple Buttons in a Cell
The same applies when multiple buttons share the same cell.
Here is an example where a few buttons have been placed into a single cell. The buttons are separated with non-breaking spaces. For clarity the table cells are shown:
And the HTML for this is:
<TD width=100% align=right nowrap>
<button class=Btn1> Use <u>S</u>ettings </button>
<button class=Btn1> Use Delete <u>F</u>iles </button>
</TD>
But there is a problem with this. It just won't work properly when the reading order of the dialog box is changed for Middle East languages.
This section of the dialog box will display:
This is not correct because the buttons should be aligned with the left side of the dialog box.
The solution is similar to when there is a single button in the cell, that is, add a table cell to push the buttons to the right, instead of using align=right.
<TD width=100%>
<table width=100% cellpadding=0 cellspacing=0><tr>
<td width=99%> </td>
<TD nowrap>
<button class=Btn1> Use <u>S</u>ettings </button>
<button class=Btn1> Use Delete <u>F</u>iles </button>
</td>
</tr></table>
</TD>
This method produces the following correct result:
Summary Keep all CSS values that international may need to change in style sheets. Do not place them in style attributes sprinkled throughout the page. Also avoid using <font> tags with name attributes.
This is more a coding tip that a concrete rule. But you can make things significantly easier for localizers by following this convention.
Always avoid placing CSS values that need to change for international into inline styles. The only place this information can be put is into the style sheet. The style sheet can be included in the file or referenced with a link.
The key reason for this is to make the content as easy to localize as possible. If the information is contained in the style sheet then it only needs to be altered once by international, and all elements that share the style class will change. If the CSS is peppered through the file as inline CSS, there are far more elements to deal with during translation.
Bad Sample:
<span style = "font-size: 10pt; font-family: Arial;"> Hello </span>
<span style = "width: 100%; border: blue 1px solid"> Goodbye </span>
Good Sample:
<style>
.myStyle {font-size: 10pt; font-family: Arial;}
.myStyle2 {width: 100%;}
</style>
<span class = myStyle> Hello </span>
<span class = myStyle2 style = "border: blue 1px solid"> Goodbye </span>
Note: This sample shows non-localizable inline CSS properties (for border), which is acceptable.
Another reason to follow Rule 10 is the way you need to code buttons for the HAL automatic sizing code to work.
This specifically covers the following CSS values:
1. | font-family, font-size, and line-height |
2. | width, height, left, and top |
Font Tag
Using font tags and setting the font name throughout the files is also strongly discouraged. It's far better to use styles.
<Font face = arial > some text </FONT>
Font Family
This rule is particularly important for fonts. In many languages it is not possible to keep the same font name (or font-family) because these fonts simply do not contain the characters for all languages.
There is far more opportunity for introducing bugs, if the localizer has to work through the file changing the font-family in lots of places.
In fact, you can save international a lot of time if you use Unicode fonts that work for all languages. Examples include the new Microsoft Sans Serif and Arial Unicode.
Note: Thanks to Paul Nelson for this tip.
You can see all the HAL Rules in action in this HAL Demo</haldemo/default.htm>.
The links below can be used to download the HAL Code:
1. | HAL Sizing Code</haldemo/halsize.js> |
2. | HAL Testing Code</haldemo/haltest.js> |
How do you verify that you've followed all the HAL rules correctly?
Unfortunately this part is still the same as it ever was; you need to test the Web pages and dialog boxes visually!
Here are the specific items you should test on your original page or dialog box.
1. | Text Size Test. In Internet Explorer choose View, Text Size, and specify a different size. The dialog box should look exactly the same at any text size. |
2. | Large Font Test. In the control panel, click the Display icon, and change the font size to Large Fonts. The dialog box should work fine at any font size set here. |
3. | Middle East Test. Set the direction to rtl in the <HTML> tag, and verify that the dialog box becomes a complete mirror image. |
4. | Random Text Test. This is really a key test. You need to swap random text into all the dialog box controls, and ensure that the dialog box automatically adjusts itself to account for longer or short text. |
HAL Test Code
Luckily there is HAL test code to automate most of the steps above. Check out the HAL Demo</haldemo/default.htm> to see how this works.
This section provides some samples for avoiding layout problems in Internet Explorer and for coding popular UI elements.
Some of the HAL rules call on you to use percentage sizes for elements. Most of the time this will work fine, but there are problems in Internet Explorer if these are combined with other cells that span multiple columns.
This is best illustrated with a simple example:

This dialog box is constructed as two table rows. The first row contains just one cell that spans three columns containing the word Folder. There are three cells on the second row: Path:, a spacer cell and the input box (sized to 100%). This is illustrated more clearly below with the table borders shown:

The HTML code for this is as follows:
<TABLE width=100%>
<TR>
<TD colspan=3>
Fol<u>d</u>er
</TD>
</TR>
<TR>
<TD width=10% nowrap>
<u>P</u>ath: </td>
<TD style="width:1px">
</TD>
<TD>
<input type=text style="width:100%">
</td>
</TR>
</TABLE>
Although this appears to work fine at first and to be properly coded, it will not work correctly. Making the word Folder longer will highlight the problem. An example is shown here:

Even though the Folder column is set to span three columns, it still has an adverse effect on the following rows.
The simple solution is to wrap the spacer column along with the input box in its own table.
<TR>
<TD width=10% nowrap>
<u>P</u>ath:
</TD>
<TD><TABLE cellspacing=0 cellpadding=0 width=100%><TR>
<TD style="width:1px"> </td>
<TD>
<input type=text style="width:100%">
</TD> </TR></TABLE></td>
</TR>
This method produces the desired correct result:

A popular new style in Microsoft Office dialog boxes is to not use group boxes, but rather to use a horizontal grouping. This means the name of the grouping is following by a horizontal line. The sample below shows Favorite Pet as the grouping.

The standard HTML code to achieve this is:
<table width=100%>
<tr>
<td>Favorite Pet </td>
<td width=100%> <hr> </td>
</tr>
</table>
However, this code will not work when the whole dialog box needs to be stored as a single dialog box. The use of the non-breaking spaces also makes this very hard to localize.
Solution
The solution is to use the same coding, but to place it inside a single cell that spans the width of the main table. Note that you need to remove all padding and spacing for this embedded table (by setting the cellpadding and cellspacing attributes to 0).
Note also the use of the nowrap attribute. This should be used instead of non-breaking spacing ( ) to prevent wrapping, because it is easier to localize terms without non-breaking spaces. Also, an extra table cell is added to separate the line from the text rather than adding a non-breaking space to the end of the term.
<table width = 100% cellpadding = 0 cellspacing = 0>
<tr>
<td nowrap>Favorite Pet</td>
<td> </td>
<td width = 100%> <hr> </td>
</tr>
</table>
The picture below shows a classic problem
There are three things you want to get right here:
1. | The Edit box (next to Address) should be right-aligned with the Use Blank button. |
2. | The right side of the Address label needs to be close to the left of the Edit box. |
3. | The Address label needs to be left-aligned with the You Can label above it. |
Okay, this sounds simple, but it's not when you take one other thing into account:
1. | The Address label should be allowed to word-wrap when translated. |
The answer is that I haven't come up with a useful solution that also takes into account the last requirement. The only way I've gotten this to look good is to force nowrap on the Address label.
Anybody out there with a better solution is invited to let me know!
<td>
<table width=100% cellpadding=0 cellspacing=0>
<td nowrap>
<label for=txtAddress>
Add<u>r</u>ess:
</label>
</td>
<td> </td>
<td style=width:100%>
<input style=width:100% id=txtAddress type=text>
</td>
</table>
</td>
Although this document is somewhat long-winded, it really has two key messages:
1. | All of the rules are very simple to apply. |
2. | This stuff really works and it'll save you a lot of trouble in the long run. |
We hope you can put HAL to good use on your own projects!
Terry Farrell (terryf@microsoft.com) is a senior program manager on the Microsoft Office Global Team (based in Ireland). He's played a hand in practically every major localization/globalization tool created at Microsoft over the years. Strangely enough though, he's yet to master a second language!