No Time Dad

A blog about web development written by a busy dad

The Humble Input Field

Styling input fields is hard. There is a lot to consider, and your input field will almost certainly not look the same on all browsers. If you really think about it, input fields are a critical component to your page. This is especially true if you have a product or checkout page. I can’t tell you how many times I’ve abandoned buying something online because the input fields I had to fill out did not work right.

Take a look at the MDN documentation for the input element. It is huge. It would take you over an hour just to read the page and ten times as long to understand everything. No wonder everyone has such a hard time with input fields.

I don’t have an answer for why input fields are so complicated. I have to think it is because each browser implements them differently and its difficult to account for all of the differences. It might also be because they’re so flexible and have so many different uses (email address, phone number, url, etc) that there is an inherit complexity that comes with supporting all of the input types. I would love to have a simple input field that looked how I wanted on all browsers, but I think that might be just a dream.

Maybe we can get close, though. Below is a mostly unstyled text input field with a label. I borrowed the css properties and comments for this input from normalize.css. This input field will look different depending on which browser you use. For example, on Firefox it has rounded corners but on Chrome the corners are not rounded. I am already frustrated.

<label for="name">Name</label>
<input type="text" name="name" id="name" placeholder="Enter first name"/>
input {
  /* Change the font styles in all browsers. */
  font-family: inherit;
  font-size: 100%; 
  line-height: 1.15;
  /* Remove the margin in Firefox and Safari. */
  margin: 0;
  /* Show the overflow in Edge. */
  overflow: visible;
}

label {
  padding-right: 0.5rem;
}

I have been giving the input field and its appearance across different browsers a hard time so far. I do want to mention that there is an important thing default input elements do well, and that is accessibility. The form displayed above with the label, element attributes, and default focus ring is accessible to all users. Once you begin adding custom styles to your input element its easy to make it less accessible.

We should fix the issue with the input corners looking different between browsers. To do that, we’ll add the border-radius property to our input selector from above. Our html will remain the same as above.

input {
  /* Existing selectors */
  font-family: inherit;
  font-size: 100%; 
  line-height: 1.15;
  margin: 0;
  overflow: visible;

  /* Round the corners */
  border-radius: 0.5rem;
}

That looks better, but now the field looks a little squished. I think we should make it larger. In my opionion, larger fields look better and they’re easier for the user to click on if they’re using a mouse. To make the input field bigger we’ll add padding to our input selector. I like to use padding-bottom, padding-left, etc explicitly because I can never seem to remember the order when using the short-hand padding: 1rem 0.5rem 1rem 0.5rem;. It is also easier to read at a glance.

input {
  /* Existing selectors */
  font-family: inherit;
  font-size: 100%; 
  line-height: 1.15;
  margin: 0;
  overflow: visible;
  border-radius: 0.5rem;

  /* Make the input field larger */
  padding-bottom: 0.5rem;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
  padding-top: 0.5rem;
}

The input field is looking great now. I’ve noticed a few sites that add color borders to their input fields and I think that is nice touch. We’ll use the border property with a neutral color.

input {
  /* Existing selectors */
  font-family: inherit;
  font-size: 100%; 
  line-height: 1.15;
  margin: 0;
  overflow: visible;
  border-radius: 0.5rem;
  padding-bottom: 0.5rem;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
  padding-top: 0.5rem;

  /* Add border around the input field */
  border: 2px solid lightblue;
}

Things are going well with styling the input field until this point, but we have a problem. We created problem the moment we added the border-radius property but it was as noticeable until we added the border property. Click or tab to the input field, putting it into a focus state. What you’ll see is that the input corners are rounded to the 0.5rem we set on the border-radius property, but the focus ring is not.

input_corners

There is good news and bad news here. The bad news is that you can’t change the radius of the focus outline directly. The good news is that we can make it look like it has a matching radius by removing the outline and using box-shadow instead.

Our input selector will remain the same, but we’ll add another input selector with the :focus pseudo-class appended.

input {
  /* Existing selectors */
  font-family: inherit;
  font-size: 100%; 
  line-height: 1.15;
  margin: 0;
  overflow: visible;
  border-radius: 0.5rem;
  padding-bottom: 0.5rem;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
  padding-top: 0.5rem;
  border: 2px solid lightblue;
}

input:focus {
  outline: none;
  /* Same as lightblue but softens the color slightly */
  box-shadow: 0 0 0 0.2rem rgb(173, 216, 230, 0.5);
}

Now we have a really nice looking input that is still accessible and will mostly look the same across multiple browsers. You can continue to modify the input selector but I’d encourage you to set a baseline set of properties and stop there. This is why we went with a neutral border color at the start. We can then add modifier selectors to change the input field for certain scenarios. This approach is good for reusing styles and reducing the size of your css file.

<label for="name">Name</label>
<input class="Green_Input" type="text" name="name" id="name" placeholder="Enter first name"/>
input {
  font-family: inherit;
  font-size: 100%; 
  line-height: 1.15;
  margin: 0;
  overflow: visible;
  border-radius: 0.5rem;
  padding-bottom: 0.5rem;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
  padding-top: 0.5rem;
  border: 2px solid lightblue;
}

input:focus {
  outline: none;
  box-shadow: 0 0 0 0.2rem rgb(173, 216, 230, 0.5);
}

.Green_Input {
  border: 2px solid lightgreen;
}

.Green_Input:focus {
  box-shadow: 0 0 0 0.2rem rgb(144, 238, 144, 0.5);
}