Whether you are a veteran or just getting started with web development, working with web forms is not the sexiest thing but there is no avoiding them. Forms on a website are critical to the website's mission and the visitors using them. In this post I am going to show you how to properly style webforms and form elements so you can ensure they are consistent with your brand and provide a pleasant user experience.

Resources:

I have recording video tutorials on some of the concepts covered in this post. Scroll to the bottom if you are the kind of person who learns better watching tutorials.

Where to start

One thing about forms you can count on is that they are not consistent. In today's API era forms can be generated from any source and you don't always have control of their HTML. I personally work with Drupal a lot and even within it forms can originate from Views, Blocks, Nodes, Paragraphs, Modules, and more. I imagine this is the case with most Content Management Systems. So how do you address something where you can't always predict source or markup of forms?

If you can't beat them, join them

Whether is Drupal or other system, it is best to let that system dictate the markup of forms. Try to bend a system to your needs can prove challenging and not worth the trouble. This is the approach I take and so far this has worked very well for me.

Attributes are your friends

As a Front-End developer for many years, I love a good css class. They make my job a lot easier than not having a class. When it comes to form elements however, it is best to ignore classes and rely solely in attributes. What attributes you may be asking yourself? Let's take a look

From element types

The type attribute in form elements make it easy to style them in a global manner. Rather than styling form elements based on their css class or ID, the type attribute is the best approach. Each form field has a type attribute which makes it possible for browsers to render the element as expected. The type attribute can also play a factor in Javascript and form handling, but for now we are going to focus on styling.

As you can see from the examples above, text fields may seem simple but they come in all flavors. In most cases, the goal of form elements is to be styled the same across an entire site. So it is recommended you style these elements globally so no matter where they are used they automatically inherit the intended styles. So how do you style them globally? Let's take a look:

Here are a couple of examples of differnt input fields which we will style to ensure they all look similarly everywhere.

<input type="text" name="firstname">

<input type="password" name="password">

<input type="email" name="email">

Styling

  input[type='text'],
input[type='password'],
input[type='email'],
input[type='tel'],
input[type='search'],
textarea
{
background-color: #ffffff;
border: 1px solid #000000;
height: 40px;
padding: 10px;
width: 100%;
}

textarea {
height: initial;
}

By using the element's type attribute we can collectively style them with a single set of rules. As you may have noticed I included textarea as on of the elements because I want textareas boxes (multi-row textbox), to inherit all of the styles from text boxes with the exception of the height property; thus we override the height property while keeping all other styles the same as text boxes.

Button elements

Buttons are elements you typically want to display with consistent styles across your entire website. This includes buttons you may create yourself and those provided by the content management system you may be working with. So similarly to input fields above, we can't always rely on IDs or classes to style them. However, similarly to the input fields above, we can rely on the type attribute to style the different type of buttons in our site. Different type of buttons? yes, there are different types. Let's tae a look.

Markup

<a class='button'>I want to look like a button</a>

<button>I'm an actual button</button>

<input type='submit' value='Yo tambien'>

<input type='reset' value='Me too'>

Styles

.button,
button,
input[type='submit'],
input[type='reset']
{
background-color: rebeccapurple;
border-radius: 2px;
border: 2px solid rebeccapurple;
color: #ffffff;
cursor: pointer;
display: inline-block;
font-size: 18px;
line-height: 1;
padding: 20px 40px;
text-align: center;
text-decoration: none;
white-space: nowrap;
margin-bottom: 20px;
}

.button:hover,
.button:focus,
button:hover,
button:focus,
input[type='submit']:hover,
input[type='submit']:focus
{
background-color: rgb(126, 63, 189); /* lighter purple */
color: #ffffff;
text-decoration: none;
}
input[type='reset'] {
background-color: #ffffff;
border-color: rebeccapurple;
color: rebeccapurple;
}

input[type='reset']:hover,
input[type='reset']:focus
{
background-color: #ffffff;
border-color: #444444;
color: #444444;
}

Radio buttons and Check boxes

Probably the hardest elements to style due to their dynamic nature, they have a hard time fitting in with the rest of HTML elements. Rather than link you to another blog post where you can copy and paste the necessary CSS to style these elements, I am walk you through the process of styling them.

Checkout the Codepen for these elements.

Markup

The typical markup for a checkbox or radio button looks like this:

<div class="checkbox__item">
<input type="checkbox" id="checkbox1" name="checkboxname" value="Item 2">
<label for="checkbox1">Item 2</label>
</div>
<div class="checkbox__item">
<input type="checkbox" id="checkbox2" name="checkboxname" value="Item 2">
<label for="checkbox2">Item 2</label>
</div>
<div class="radio__item">
<input type="radio" id="radio1" name="radioname" value="Item 2">
<label for="radio1">Item 1</label>
</div>
<div class="radio__item">
<input type="radio" id="radio2" name="radioname" value="Item 2">
<label for="radio2">Item 2</label>
</div>

Styles

Out of the box, you can not style the native checkbox nor radio button elements. To be able to apply custom styles we need to do it in a hacky way. This is my favorite way to style these elements.

Drawing the checkbox

/* visually hide the native checkbox and radio buttons. */
input[type='checkbox'],
input[type='radio']
{
position: absolute;
opacity: 0;
}
/* Add space to the left of the label for later use. */
label {
position: relative;
padding-left: 35px;
}
/* Draw a square box with border  using a pseudo element (`::before`). */
input[type='checkbox'] + label::before {
border: 2px solid #e15b00;
content: '';
display: inline-block;
height: 24px;
left: 0;
position: absolute;
top: -2px;
width: 24px;
}
/* Draw checkmark using a ::after pseudo elment on the label */
input[type='checkbox'] + label::after {
border-bottom: 3px solid #fff;
border-left: 3px solid #fff;
content: '';
display: inline-block;
height: 10px;
left: 4px;
position: absolute;
top: 2px;
transform: rotate(-45deg);
width: 18px;
}

Drawing the radio button

Before proceeding with the styles, let's repeat the steps above but this time for the radio buttons. These styles are extremely similar with the exception of in stead of drawing a square box, we will be drawing a circle with an outline, and instead of a checkmark, we will be drawing a filled circle in the middle of the outlined circle.

/* Draw a circle and add borders to it */
input[type='radio'] + label::before {
border-radius: 50%;
border: 2px solid #e15b00;
content: '';
display: inline-block;
height: 24px;
left: 2px;
position: absolute;
top: -4px;
width: 24px;
}

/* Draw an inner circle */
input[type='radio'] + label::after {
background-color: #e15b00;
border-radius: 50%;
content: '';
display: inline-block;
height: 20px;
left: 6px;
position: absolute;
top: 0;
width: 20px;
}
/* Hide checkmark and inner circle by default */
.radio input[type='radio'] + label::after,
.checkbox input[type='checkbox'] + label::after
{
content: none;
}
/* Show checkmark and inner circle when input is checked */
input[type='radio']:checked + label::after,
input[type='checkbox']:checked + label::after
{
content: '';
}
/* When box is checked, add background color. */
input[type='checkbox']:checked + label::before {
content: '';
background-color: #e15b00;
}
/* Add focus styles when elements are in focus */
input[type='radio']:focus + label::before,
input[type='checkbox']:focus + label::before
{
outline: rgb(59, 153, 252) auto 5px;
}

Resources

I have recorded tutorials on severalof these things. Check them out if you are the kind of person who learns better through video tutorials.