608.620.5104 | info@tenforwardconsulting.com

How to make a text field's width increase and decrease dynamically based on user input

Published November 5, 2018

Welcome to another blog post from Hilary on "How to Do a Simple Thing (for Which It Can Be Surprisingly Hard to Find Reasonable Instructions)."

The problem

One of our B2B software clients wanted to add a feature that let their users specify a custom subdomain. For the user interface, we added a form field for "custom subdomain" to the user's account page. 

However, the general form styles didn't quite cut it for what we were doing - having a default length for the input just looked weird, especially when the subdomain was particularly short.

The solution

So we made it dynamic! Now, as the user types, the input field grows or shrinks accordingly. 

The Code


  = text_field_tag :subdomain


class Habit.SubdomainChoiceDisplay  
  constructor: ->    
    $(document).ready =>      
  initListeners: =>    
    $(".js-subdomain-field input").on "keyup", @onSubdomainFieldKeyup  

  onSubdomainFieldKeyup: ->    
    $subdomainField = $(".js-subdomain-field input")    
    subdomain = $subdomainField.val()    
    if subdomain == ""      
      $subdomainField.attr('size', 20)    
      $subdomainField.attr('size', subdomain.length * 0.97)

We run this check both when a user is typing and also at the beginning, so that it properly sizes the input when the user already has a subdomain saved. 

We get the value of the input, then calculate its length. If the input value is blank, we default to size 20 for UX purposes (so that it's more obvious to the user that they can type there).

If it's not blank (ie: they're typing), we then multiply the value by 0.97 to get our new size. This is because length refers to number of characters, where as size in most browsers refers to em units:

It's the width of the capital M in the default font size as applied by CSS styling to the text box, but the font size of the text inside the text box is usually smaller. 


In practice, this means that we end up with a lot of whitespace if we keep the ratio 1 em to 1 character, because "M" is wider than most (all?) other letters. 0.97 is the magic number that best balanced showing all of the letters without creating too much extra whitespace at the end (at least in our case, because subdomains are generally pretty short).

Related reading

Author details

Hilary Stohs-Krause

Software developer