How to Build HTML Forms Right: Styling

This article covers HTML form design patterns, common gotchas, and CSS tips. You should be able to walk away with some new knowledge and helpful code snippets.

I’ve written a couple of articles now on how to write HTML forms for the modern web. The previous articles focused on semantics and accessibility, which are the foundation for any good form. If you’re interested in the overview of the entire series, here’s what it looks like:

This will be part 3, and it’s probably the article I’m most excited for. We’re going to look at some common form design patterns, some of the gotchas, and how to approach them with CSS. Hopefully we won’t need to get too hacky and you’ll be able to walk away with some new knowledge and code snippets.

Styling Forms is Not Great

As a web developer, you will run into the scenario where you have to write custom styles for some form input. If you’re lucky, it will be a simple text field. Those are pretty straight forward.

If you’re not lucky, however, you will need to style one of the “troublesome” elements in MDN’s “Advanced Form Styling” article. These are elements that have their own browser-provided styles which are tricky to customize.

The list of troublesome input includes:

That’s not a short list. Fortunately, we are going to look at solutions to cover the most common needs you will have. The thing to remember before styling is to get the semantics and accessibility correct first!

I like to start with some global styles applied to all my inputs, and a visualy-hidden utility class for accessible, but hidden content:

input,
select,
textarea {
  width: 100%;
  max-width: 100%;
  font: inherit;
  color: inherit;
}

input[type="checkbox"],
input[type="radio"],
input[type="submit"],
input[type="button"] {
  width: auto;
}

fieldset,
legend {
  margin: 0;
  border: 0;
  padding: 0;
}

.visually-hidden {
  position: absolute;
  overflow: hidden;
  clip: rect(0 0 0 0);
  width: 1px;
  height: 1px;
  margin: -1px;
  border: 0;
  padding: 0;
}

The following examples will highlight only the critical points of markup and CSS, but I’ll also link to more practical examples that look nice.

The Easier Ones

Number