skip to content

HTML: Forcing INPUT text to uppercase

So you have a form where you want to only accept UPPER CASE text in certain input or textarea fields. There are a number of ways to tackle this ranging from JavaScript to HTML5 patterns, CSS, and server-side code. Some are really annoying.

Using JavaScript to alter text as you type

This is the most obvious and common approaches, but also the least user-friendly. On every keystroke a JavaScript event is triggered to convert the value to uppercase.

Start typing ('abc') and you'll see how it works:

Source code:

<input type="text" onkeyup="this.value = this.value.toUpperCase();">

Aside from the distraction of seeing things change as you type, there are other problems.

Try entering 'AAA' in the input box above, select the middle 'A' and try changing it to 'ABBA'. What you end up with instead is 'ABAB', because just setting the value with JavaScript moves the cursor to the end of the text.

Maintaining cursor position

If you move the cursor to an earlier position in the text and type, it will be bumped back to the end of the text already input. So we need some extra code to retain the cursor position:

Source code:

<input type="text" onkeyup=" var start = this.selectionStart; var end = this.selectionEnd; this.value = this.value.toUpperCase(); this.setSelectionRange(start, end); ">

So far so good, but now we're polluting the JavaScript namespace with global variables, and we have four lines of code that need to be copied to every field with an UPPERCASE requirement.

Making it modular

Rather than polluting our HTML with inline JavaScript, we can create a function and apply it to selected input fields:

Force to uppercase - jumpy

Source code:

<form method="POST" action="#"> <p><label>Input 1<br> <input class="uc-text" type="text" size="24"></label></p> <p><label>Input 2<br> <textarea class="uc-text" cols="24" rows="3"></textarea></label></p> </form> <script> var forceInputUppercase = function(e) { let el = e.target; let start = el.selectionStart; let end = el.selectionEnd; el.value = el.value.toUpperCase(); el.setSelectionRange(start, end); }; document.querySelectorAll(".uc-text").forEach(function(current) { current.addEventListener("keyup", forceInputUppercase); }); </script>

Now we have a generic function which can be applied through an onload event handler and that works on both input fields as well as textareas.

Only we still have that jumping effect.

Smoothing out the UX

To get around the jumping effect we can target the keypress event rather than keyup and overwrite the default action. Again there is the complication of maintaining cursor position in the input field:

Force to uppercase - smoothly

Source code:

<form method="POST" action="#"> <p><label>Input 1<br> <input class="uc-text-smooth" type="text" size="24"></label></p> <p><label>Input 2<br> <textarea class="uc-text-smooth" cols="24" rows="3"></textarea></label></p> </form> <script> const forceKeyPressUppercase = (e) => { let el = e.target; let charInput = e.keyCode; if((charInput >= 97) && (charInput <= 122)) { // lowercase if(!e.ctrlKey && !e.metaKey && !e.altKey) { // no modifier key let newChar = charInput - 32; let start = el.selectionStart; let end = el.selectionEnd; el.value = el.value.substring(0, start) + String.fromCharCode(newChar) + el.value.substring(end); el.setSelectionRange(start+1, start+1); e.preventDefault(); } } }; document.querySelectorAll(".uc-text-smooth").forEach(function(current) { current.addEventListener("keypress", forceKeyPressUppercase); }); </script>

In this new function the inner code is only executed when: the keypress is a lower case character (a-z); and not accompanied by any modifier (Ctrl, Shift, Option, Alt).

In that case we calculate the equivalent upper case character, insert it into the correct position, then (re-)set the cursor position and block the default action.

As an aside, in the bad old Internet Explorer days, we would have needed least twice as much code here just to handle IE quirks and limitations. Be glad we're past that.

All well and good, but what if there was a simpler approach?

CSS to the rescue

In reality it's not important if the form input is in upper or lower case. What matters is that:

  1. the user sees the text they type as UPPERCASE with no jumping; and
  2. our form handler converts the text to upper case before it is used.

With this in mind we can throw out all the preceding JavaScript and instead use a simple CSS and PHP (or equivalent back-end) solution:

From a user's perspective this is identical to the previous example, but there is one important difference.

The CSS style in this example only changes the appearance of the text while the input value remains exactly as typed - so the POST data can contain upper- and lower-case.

Source code:

<input style="text-transform: uppercase;" type="text" name="fieldname">

Our back end code (form handler) then needs to convert values to uppercase before they go into the database:

<?PHP ... $_POST['fieldname'] = strtoupper($_POST['fieldname']); ... ?>

Do you see how much simpler things can be if you use the appropriate technology?!? A single CSS style (which can be moved to an external style sheet), plus a single line of PHP, which was probably there already. No JavaScript or jQuery required.

HTML5 Pattern Validation

As an aid to form validation we can use HTML5 input patterns to flag when an input is not valid.

In the JavaScript examples, the pattern to enforce only uppercase (assuming a single word - no spaces or punctuation) is:

<input type="text" ... pattern="[A-Z]*" ...>

But with our CSS solution for uppercase input your pattern also needs to encompass lower case characters as they can be accepted even if not displayed:

<input type="text" ... pattern="[a-zA-Z]*" ...>

In both cases you will need to include any non-alphanumeric characters you want to allow in the regular expression, plus any restrictions on length.

Enforcing first letter uppercase

In response to a question from Rechie in the Philippines, there is no CSS solution for forcing only the first letter in an INPUT to be uppercase.

For HTML block elements (P, DIV) we do have a CSS solution:

<style> .ucfirst { text-transform: lowercase; color: blue; } .ucfirst:first-letter { text-transform: capitalize; } </style> <p class="ucfirst">first letter UPPERCASE</p>

Which displays the affected paragraph as:

first letter UPPERCASE

But the same approach does not work for INPUT fields so we're back to using JavaScript.

Here's a simple example where we piggy-back off our previous forceKeyPressUppercase method and apply it conditionally according to the position of the cursor in the INPUT field:

<input id="field_ucfirst" type="text"> <script> document.querySelector("#field_ucfirst").addEventListener("keypress", (e) => { if(0 == this.selectionStart) { // uppercase first letter forceKeyPressUppercase(e); } else { // lowercase other letters forceKeyPressLowercase(e); } }); </script>

In practice, if you are working with names, you may want to capitalize each word (e.g. "Mary Jane"), and in certain cases letters within a word (e.g. "McDonald").

For that you will need a more advanced function that uses the position and context of a letter to determine whether to make it upper- or lower-case as the user types.

< HTML

User Comments

Post your comment or question

19 October, 2023

Thank you so much! It has really helped me a lot, I was looking for various options last night, and today I found this solution. I have put it in my project code in Angular.
Greetings from Lima, Peru.
God bless you.

16 September, 2021

How about this?
<input oninput="this.value = this.value.toUpperCase()" />

17 December, 2019

text-transform: capitalize; is a life saver!

Thanks

21 October, 2019

Hi - as regards chapter "CSS to the rescue"... where exactly do I put the PHP code and how do I manage this code when submitting the form (input type="submit") does not only send off the one field that needs to be sent in uppercase but also others that need to be mixed uppercase and lowercase?

23 April, 2019

Hello, Input element's type ('email') does not support selection so how can we maintain cursor position for input type email with forcing text to uppercase/lowercase?

1 February, 2019

The following works in HTML5 just fine

<input type="text" style="text-transform: uppercase;">

13 January, 2019

WRT "5. CSS to the rescue", I have a requirement to auto-lowercase any text typed for an Email Address:

<input type="email" name="EmailAddress" maxlength="50" size="50" style="text-transform: lowercase;" value="">

This works great when I enter text into the <input> element; if I enter uppercase text, it appears as lowercase text.

If, though, I don't enter a valid e-mail address containing uppercase text (e.g., the text 'UPPERCASE'), then when I click on [Save], I get the following error message:

Please include an '@' in the email address. 'UPPERCASE' is missing an '@'.

Note that the web page "realizes" that the text is still in uppercase ('UPPERCASE') whereas the error message should display it in lowercase as follows:

Please include an '@' in the email address. 'uppercase' is missing an '@'.

Unless there's another solution, I'm thinking that I will be forced to abandon the CSS solution and go with a JavaScript solution.

All you need to do is convert the value to lowercase before display:

PHP:

strtolower($_POST['email']);

JavaScript:

form.email.value.toLowerCase();

31 October, 2018

i just want an autocapslock on first letter . how to do that ?

It's complicated, but I've added an example above.

top