How can I make a field readonly in a Web form?

In HTML, the readonly attribute for a form field specifies that the field should not be changeable by the user. However, this feature is not universally supported yet. As a workaround, one can additionally use simple JavaScript code via onfocus="this.blur()", or a cleverer code which focuses on the next field, though such methods of course do not work in all browsing situations. Depending on the reason for making a field readonly, a more robust method of using hidden fields might be feasible.

Content:

Why readonly?

There are several reasons why a Web page author might wish to make a form field readonly:

  1. The form should contain some data which is submitted along with the form but is not be changed by the user. The data might e.g. originate from previous input from the user, processed by a server side script which has then generated a new form with some prefilled fields.
  2. The author might be using a textarea element just to create a "scrollable subwindow" of text, i.e. for data display, without actually using a form at all. Note that this isn't such a great idea, and using inline frames might do the job better (though you'd still need some fallback for browsers not supporting iframe).
  3. An input field might be used just as "output area" for JavaScript code (see e.g. my example of dynamically displaying the sum of fields). The reason is that for displaying results of JavaScript calculations, using a form field (however illogical) is the way which works most universally across JavaScript implementations.
  4. The author might wish to make some fields in a form take different state according to data entered in the form. For example, some field F might need to be fixed unless a particular selection is made in another field, in which case F would need to be changed (via client-side scripting) to a normal, user-changeable input field.

The methods used to make a field readonly, especially the workaround methods, need to be selected according to the purpose.

A word of warning: it can't be absolutely readonly

In addition to limitations listed below, there is a more fundamental restriction. Even if all browsers supported the HTML way of declaring a field as readonly, a user could still create his private copy of the author's form, edit it, making the field a normal input field, and using that form to submit data. (The author cannot hide the HTML source.) Or the user might write a form of his own from scratch, based on information or assumptions about what the form handler expects to get.

It is true that the server-side form handler could be written so that it checks the Referer field in the HTTP transaction. Specifically, it could check that the Referer field matches the address of the document containing the form to be used. This approach is not without problems though. It could limit usability (e.g. by preventing the fair use of local copies of that document), and it wouldn't protect against browsers or other programs which have been written to send faked Referer fields.

Thus, do not rely on readonly fields actually remaining readonly. In particular, when such fields will be used in server-side form handlers, normal data presence and integrity tests should be performed.

The HTML way: the readonly attribute

In HTML 4, the readonly attribute can be used for input and textarea elements. It is defined as follows in the specification:

No value is needed for the readonly attribute. But to conform to XHTML, a restricted version of HTML where "attribute minimization" is not allowed, you can write readonly="readonly".

However, this attribute is currently supported (among widely used browsers) only by Internet Explorer 4 and newer.

You can see whether your current browser supports readonly if you try to modify the second field in the following form (you should not be able to focus on it, still less to change its content; submitting the form causes just an echo of the form data):

Note the difference between readonly and disabled. The latter, which lacks universal support, too, also implies that the field cannot be changed, but additionally it means that the field is currently not part of the form data at all. That is, if the form is submitted, disabled fields are not included into the submitted data (but readonly fields are, according to normal rules).

The other HTML way: using hidden fields

In case 1 among the reasons discussed above in the Why readonly? section, one could also use a hidden field, i.e. input type="hidden". Hidden fields are supported universally among browsers, practically speaking. But since they are not displayed at all, you need to consider whether you need to include their content as normal text into the document. It depends on the case whether you should inform the user about some data being transmitted automatically.

For example, if you wish to include a field, say surname, containing the user's surname, say Korpela, which you have got from somewhere (e.g. previous form submission), you could include
Surname: <input type="text" name="surname" value="Korpela">
into a form, thereby letting the user fix it if it is wrong. But it might be the case that such fixing is undesirable; perhaps you want to make the user go back in a chain of form submissions to fix it where it went wrong, instead of just fixing it here. Then you could make the field readonly:
Surname: <input type="text" name="surname" value="Korpela" readonly>
But this isn't particularly effective, due to limited browser support. It would be better to use a hidden field and normal text:
Surname: Korpela
<input type="hidden" name="surname" value="Korpela">

The normal text and the hidden field need not be consecutive. The positioning of a hidden field within a form is immaterial. But it's natural to put things together when they contain the visible and invisible presentation of the same data.

If the data to be included is not relevant to the user but e.g. just some technical data for bookkeeping purposes, there's no reason to include it visibly, i.e. you'd use hidden fields only. Things like customer or order numbers require due consideration. Perhaps they are potentially relevant to the user e.g. when he wishes to report a failure in the form functionality.

The JavaScript way: onfocus="this.blur()"

In JavaScript, you can use the blur() method to make a form field lose focus. And by invoking that in an onfocus event handler, you would effectively prevent the field from ever gaining focus.

The following example uses this technique, i.e. input onfocus="this.blur()"...:

In JavaScript, the this keyword denotes the "current object", which here means the browser's internal data structure corresponding the input element where the onfocus attribute occurs.

However, in addition to the general limitations of JavaScript approaches (the browser might not have JavaScript enabled), there's the specific problem that not being focusable does not logically imply being unchangeable; some browsers might, now or in the future, provide a method of changing form field content without focusing on it. Moreover, there seem to be bugs in Netscape in this area; a test of mine failed to make the field readonly on Netscape 4.0 on WinNT, but that problem disappeared when I removed the stylesheet (which should of course have no effect on focusing). See also problems with tabbing discussed below.

Note that there is no reason not to use the readonly attribute too. (Our example above lacks it just to let you test the effect of the JavaScript method in separation.) Specifically, on IE 4+ or Netscape 6+ with JavaScript disabled, readonly makes a difference.

See also JavaScript Form FAQ section Protecting Field Values, which discusses issues not covered here, such as making select elements "readonly" and dynamically turning readonly status on or off.

Pay attention to tabbing: use a better JavaScript way, and use tabindex

Browsers generally support "tabbing" in forms, so that the user can get from one field to another using the tab key. This is often very convenient and users might be accustomed to it, therefore annoyed when it does not work. And it can be more than just a convenience; see Web Content Accessibility Guidelines, especially guideline 9: Design for device-independence.

One might expect that setting a field readonly removes it from the "tabbing ring" so that tabbing in the previous field takes us to the field after the readonly field. This however is not the case in the IE implementation for the readonly attribute. Moreover, the JavaScript this.blur() operation doesn't have such an effect either. For both of them, tabbing in a field preceding the readonly field will take us to an indeterminate state (no focus), and only after another tab do we get to the next field. (On one browser, I observed that tabbing in a field when the next field has onfocus="this.blur()" took me to a state where that next field is colored but nothing can be typed, and tabbing does not work at all!) This is rather clumsy and confusing; well, try it yourself (type something into the first field and press tab):




<form action="http://jkorpela.fi/cgi-bin/echo.cgi">
<input name="fld1"><br>
<input type="text" name="readonly-field" value="read-only"
readonly onfocus="this.blur()" ><br>
<input name="fld3"><br>
<input type=submit>
</form>

A better approach uses this.form.nextfield.focus() instead of this.blur() as well as tabindex attributes so that the readonly field is skipped in the tabbing order:




<form action="http://jkorpela.fi/cgi-bin/echo.cgi">
<input name="fld1" tabindex=1><br>
<input type="text" name="readonly-field" value="read-only"
readonly onfocus="this.form.fld3.focus()" ><br>
<input name="fld3" tabindex=2><br>
<input type=submit tabindex=3>
</form>

This is just a little more laborious to write than the simpler method. Instead of mechanically using this.blur() you need to pick up the name (nextfield) of the next field or, more generally, the next non-readonly field in the form.

The tabindex attribute is supported by some browsers only only, so even this combined method is far from 100 % sure, but it works on most JavaScript-enabled browsers and on e.g. IE 4+ and Netscape 6+ even with JavaScript disabled.

Jim Ley has remarked that code like this.form.fld3.focus() should be avoided and a safer construct like document.forms['formname'].elements['fld3'].focus() should be used instead.

How to make it look readonly?

The visual appearance of readonly fields on IE (and Netscape 6) is the same as for normal fields, whereas disabled fields look different. This isn't quite natural. You may wish to suggest a change using style sheets, e.g. using a different background color. Be careful: a readonly field should not resemble the default appearance of a disabled field!

The following example contains various fields, one of which is a readonly field with the attribute
style="background:#eee none; color:#222; font-style: italic"
suggesting a light grey background color and not quite black text color as well as an italics version of the font in use:

(normal field)
(disabled field)
(readonly field)
(readonly field with CSS)

If you have several readonly fields on a page, you probably wish to put the stylistic suggestions into a style element or an external style sheet instead of including a copy of them into each field. Then you would invent a suitable class name (it could be ro for example) and use class="ro" in the elements which have the readonly attribute. Unfortunately it is currently not possible to specify in a style sheet that some rules are to be applied to all elements which have a certain value for a certain attribute. (Such possibilities exist in CSS2, but they are not supported yet by browsers.)

Note that the possibilities of affecting form field appearance are relatively limited. The CSS methods for it work to some extent on IE 4+ but not on many other browsers. In our example, Netscape 4.0 shows the readonly field with CSS so that the text is in italics but the appearance is otherwise that of a normal input field, i.e. the color and background suggestions are ignored.

Depending on your reason for trying to make field readonly, you might wish to suppress the border around the field, so that it does not really look like a field at all. This is technically simple (using border:none in a style sheet) but works on some browsers only. For a simple example (for JavaScript-enabled browsers), see Yet another example: dynamically displaying the sum of fields.


This document is part of my material on HTML forms.

Date of last update: 2002-07-25.

Jukka Korpela