ColdFusion in Context: Input Field Size

I used to think that input field size was something I could set and forget. Boy, was I wrong! This tip lets you explore the impact of font family, font size, and font weight (e.g., bold) on the number of characters that are displayed in a field that you THOUGHT you had set to display a certain number of characters.

Build It

Put all code in inputsize.cfm. Set defaults needed by the form. Font family is a prioritized list of fonts you want the browser to use. If the browser doesn't have the first font, it will pick the next one. If it has none on the list, it will use whatever it feels like using. Use fonts from a common family, naming the most specific/desirable ones first. Font size is expressed in points. Font Weight isn't really implemented on a continuum. You'll set it where normal weight is anything under 600 and bold is anything 600 or higher.

The length factor is not something you would set through a style sheet. It's something you could multiply the maximum length by to set the field size large enough to show the longest input as it is likely to be entered by the user. (We'll consider this statement more closely later.) If you're not using a style sheet, the browser will probably use Arial, 10-point, 300-weight.

<cfparam name="form.FontFamily" default="Arial, sans-serif">
<cfparam name="form.FontSize" default=10>
<cfparam name="form.FontWeight" default=300>
<cfparam name="form.LengthFactor" default=1>

This small style sheet sets parameters for input tags and select tags. It uses the defaults provided above or the values you have subsequently set through a form.

<style type="text/css">
<cfoutput>
input{
font-size: #FontSize#pt;
font-weight: #FontWeight#;
font-family: #FontFamily#;
}
select{
font-size: #FontSize#pt;
font-weight: #FontWeight#;
font-family: #FontFamily#;
}
</cfoutput>
</style>

Make a list of font lists that you want to choose from for the display. Surround font family names with single quotes for consistency. You'll need to do this anyway for family names of more than one word. Separate the lists using something other than a comma (since the font lists themselves contain commas); a semicolon is used here.

Open a form for post, wrap its contents in a cfoutput tag, accept parameters, and demonstrate inputs. Within the select tag to pick a font family, loop the list of font lists you've just made, being sure to use a semicolon as the delimiter. Create an option for each font list. If the option is the same as the current font family list, cause the word "selected" to appear as a standalone parameter to the option tag. This makes the pulldown match the current value.

<cfset FontList="'Arial', sans-serif; 'Courier New', monospace; 'Times Roman', serif">

<form method="post">
<cfoutput>

<select name="FontFamily">
<cfloop list="#FontList#" index="FontFamilyPick" delimiters=";">
<cfif FontFamilyPick is form.FontFamily>
  <cfset choice="selected">
<cfelse>
  <cfset choice="">
</cfif>
<option value="#FontFamilyPick#" #choice#>#FontFamilyPick#
</cfloop>
</select>

Handle the remaining inputs. Points, weights, and the length factor are straightforward entries, as is the submit button.

Points: <input type="text" size="3" name="FontSize" value="#form.FontSize#">

Weight: <input type="text" size="5" name="FontWeight" value="#form.FontWeight#"><br>

Multiply max length by this factor:
<input type="text" size="5" name="LengthFactor" value="#form.LengthFactor#"><br>

<input type="submit" name="doit" value="Try"><br>

The relationship between the input size and the number of characters shown by the browser is not quite linear. To see this, it is necessary to look at a range of input sizes. To make the examples easily fit in a browser window, loop backwards from 30, and break to a new line after every other entry. To flipflop in this fashion, set Flip to 1, multiply it by -1 on each pass, and add a break whenever Flip becomes greater than zero. Font widths are often depicted as the width of a capital "M". A "W" is used here in every tenth position to make counting easier even though it is slightly wider than an "M". Make the string larger than you'll need - maybe you'll want to increase the starting point to see larger input sizes - and let the loop run. Close the loop, output, and form.

<cfset Flip=1>
<cfloop from="30" to="1" index="Length" step="-1">
<input type="text" size="#evaluate(Length*LengthFactor)#" name="Show"
value="MMMMMMMMMWMMMMMMMMMWMMMMMMMMMWMMMMMMMMMWMMMMMMMMMWMMMMMMMMMW">
#Length#
<cfset Flip=Flip*-1>
<cfif Flip gt 0>
  <br>
</cfif>

</cfloop>
</cfoutput>
</form>

Try It

Font widths are often depicted as the width of a capital M. Using a string of Ms to see how many standard characters can be seen would be more accurate than using a capital W at every tenth position. However, it would be harder for you to count the characters if all Ms were used. Browse inputsize.cfm.

Your Netscape browser (at least a good version: one equivalent to 4.7 or older) behaves very nicely regardless of the font family used. Arial accomodates all field sizes. Times Roman works through 20 characters, at which point the difference between the W and the M is great enough to cause a character to be lost from the display. This isn't a definitional problem; it's a problem with our measuring stick (which contains Ws). A very small adjustment would handle this if expected your inputs to contain an unusual number of wide characters.

However, the calibration of the Internet Explorer browser relative to field size is very bad. Any field size beyond 6 Arial characters or 2 Times Roman characters won't hold the length the size calls for.

Changing other font characteristics (font and weight) doesn't matter matter much. Changing the page fonts with ctrl-{mouse wheel} changes the way the labels are displayed but not the text in the fields. Only forcing the browser to use a non-proportional font (Courier New) fixes the problem.

Action

So what can you do? You can insist that users employ a Netscape browser that isn't brain dead (4.7 or older), you can specify a non-proportional font, or you can adjust the field size to compensate for the effects of a proportional font in an IE browser.

Play with the multiplier: the length factor. Multipliers of 1.75 for Arial or 2 for Times Roman are close to what you need for IE. These multipliers provide a bit more space than you need at small maximum lengths - the relationship between requested and actual field size is not entirely linear, and its intercept is not zero - but these multipliers give reasonable results with IE browsers.

If you choose to adjust field sizes using factors like this, then what will you do for the Netscape users who visit the same site? Their fields will be much longer than they need. To avoid wasting the space taken up by fields, you'll need to adjust the field size based on browser type. However, form design (especially a form to be printed for the user's records) is tough if you go this route. You have to consider how the distortion caused by varying field sizes to accommodate different browsers will impact the overall form.

If you don't mind a non-proportional font, then it will provide consistent results regardless of the browser. You won't have to sense the browser type, you won't have to vary the field size, and your forms will retain a consistent appearance. Now that you know why input field size requires your attention, the choice of what to do about it is up to you. =Marty=