jQuery: Textarea maxlength

Being able to restrict the maximum length of user input from the interface directly is very convenient and practical in use. We do this a lot with input elements. Unfortunately textarea elements do not natively support the maxlength attribute. This attribute was finally added in HTML5 but at the time of writing Chrome is the only browser supporting it.

Naturally many have used JavaScript to rectify this problem and I’d be doing the same here. The difference is we won’t be putting anything special in the markup but will simply use the maxlength attribute within our textarea as if it’s native — like so:

HTML

<textarea cols="30" rows="5" maxlength="10"></textarea>

This is looking good for HTML5 compatibility. And here’s the magic:

jQuery

jQuery(function($) {

  // ignore these keys
  var ignore = [8,9,13,33,34,35,36,37,38,39,40,46];

  // use keypress instead of keydown as that's the only 
  // place keystrokes could be canceled in Opera
  var eventName = 'keypress';

  // handle textareas with maxlength attribute
  $('textarea[maxlength]')

    // this is where the magic happens
    .live(eventName, function(event) {
      var self = $(this),
          maxlength = self.attr('maxlength'),
          code = $.data(this, 'keycode');

      // check if maxlength has a value.
      // The value must be greater than 0
      if (maxlength && maxlength > 0) {

        // continue with this keystroke if maxlength
        // not reached or one of the ignored keys were pressed.
        return ( self.val().length < maxlength
                 || $.inArray(code, ignore) !== -1 );

      }
    })

    // store keyCode from keydown event for later use
    .live('keydown', function(event) {
      $.data(this, 'keycode', event.keyCode || event.which);
    });

});

See live example.

This code could probably be enhanced further by triggering custom events when the maximum length is reached or include a character counter of some sort within the keypress handler. Your imagination is the limit!

  • Tontyna

    Thanks for the example, but using keypress instead of keydown is not a good solution – this will ignore the characters with ASCII code 33 to 40 ('!', '"' .. '(') – i.e.: you can enter them after maxlength is reached.

    Seems to be a decision between Opera and 'not-so-frequently-used' letters.

    46 = delete should also be included in the ignore array.

    • caphun

      @Tontyna: thanks for the input. I have updated this post to add 46 to the ignore list. To fix the keyCode issue I'm using $.data to store the keyCode value from keydown, then use that rather than the one from keypress which seemed to be the problem in the previous version. Also the code now uses live binding.

      I actually think keypress is the best place to stop user input since it also stops repeat keystrokes if the user keeps a key pressed down.

  • roren

    Great post. Really helped me a lot. Thank you very much.

  • http://jquery-plugin.buss.hk Cloudgen

    Thanks for sharing Caphun. By the way, I've tried your code in jsbin :P
    http://jsbin.com/ebime4/edit

  • Tom

    Thanks for creating this solution. But it doesn't allow the following scenario:

    - Fill the textarea until maxlength is reached.

    - Select some of the characters.

    - Type a letter to replace the selected part.

    The replacement will not occur.

  • Donyking

    Thanks for your share

    but if i press Ctrl+v it will not work

    How to resolve this situation?

    • caphun

      @donyking: pasting seems to work?

      This simple demo doesn't cover cases such as those mentioned by Tom above. To handle more complex cases such as highlighting you need to look into text range and selections.

  • Donyking

    OK,Thanks all

  • pacotole

    I use a more simple solution that works on replace selection and paste:

    $('textarea[maxlength]').keyup( function(e) {
    this.value = this.value.substr(0, $(this).attr('maxlength') );
    });