The online home of Daniel Winer

MOSTO: A lightweight framework for forms Feb 08, 2013

Forms aren't much fun to build, I think most web designers find them pretty tedious to design and code. For that reason I wanted to make this framework which should suit most situations where you need a form on your site.

Why not just use a framework like Bootstrap or Foundation?

I think both Bootstrap and Foundation are awesome frameworks but when it comes to forms I like to wrap the <input> in a <label>, and by doing that you can reduce structural HTML. It also means you forget about the for="" attribute because wrapping the <input> with the <label> gives you implicit association. End result is less code to write and easier maintenance.

Apart from using less HTML, I also wanted a framework with less CSS and more emphasis on using this as your basic starter kit from which you can extend and embellish per site. However, if you're not that worried about the size of your HTML and CSS files and you would prefer to just have an all-in-one solution, then you're probably better of with something like Bootstrap or Foundation. If you want flexible forms with very minimal markup, then read on.

1. Stacked forms

The simplest, most basic form has the input below the label and the help text below the input. This layout will be referred to as "stacked".

Code structure overview:
  
<form>
  <label>
    Label text
    <input>
  </label>
</form>
  
  
<form>
  <label>
    Name
    <input type="text" placeholder="Name" tabindex="1">
  </label>
  <label>
    Email address
    <input type="email" placeholder="Email address" tabindex="1">
  </label>
  <label>
    Favourite beer?
    <select tabindex="1">
      <option>Heineken</option>
      <option>Carlsberg</option>
      <option>Stella Artois</option>
      <option>Cronenberg</option>
      <option>Guiness</option>
      <option>Amstel</option>
      <option>Corona</option>
    </select>
  </label>
</form>
  

What's so great about this? There is no extra markup, all the HTML used is the minimum requirement for building a form.

1.1 Radios and checkboxes

Once we start to add collections of radio options or checkboxes, then we need a wrapper <div class="label-group"> to go around them all.

Which is better?
Who's the boss?
  
<form>
  <div class="label-group">
    Which is better?
    <label>
      <input type="radio" name="cartoons" value="simpsons" tabindex="1">The Simpsons
    </label>
    <label>
      <input type="radio" name="cartoons" value="family_guy">Family Guy
    </label>
    <label>
      <input type="radio" name="cartoons" value="southpark">Southpark
    </label>
  </div>
  <div class="label-group">
    Who's the boss?
    <label>
      <input type="checkbox" name="invite" value="homer" tabindex="1">Homer Simpson
    </label>
    <label>
      <input type="checkbox" name="invite" value="peter">Peter Griffin
    </label>
    <label>
      <input type="checkbox" name="invite" value="frank">Frank the Tank
    </label>
  </div>
</form>
  

1.2 Complete form

Put it all together and your form will look like this:

Which is better?
Who's the boss?

So to build the complete form the only additional markup used for styling purposes is the <div class="label-group"> that wraps groups of radio or checkbox inputs, all other markup is the bare minimum required for building forms.

2. Horizontal forms

The horizontal form has the label text next to the input. To do that you need to

If you're not sure whether stacked or horizontal forms are going to be better for your site then always use the markup for the horizontal forms. This means switching between one or the other is as easy as adding or removing a class from the <form>.

Code structure:
  
<form class="form-horizontal">
  <label>
    <div>Label text</div>
    <input>
  </label>
</form>
  
Which is better?
Who's the boss?
  
<form class="form-horizontal">
  <label>
    <div>Name</div>
    <input type="text" placeholder="Name" tabindex="1">
  </label>
  <label>
    <div>Email address</div>
    <input type="email" placeholder="Email address" tabindex="1">
    <span class="message">Please use a valid email address</span>
  </label>
  <label>
    <div>Favourite beer?</div>
    <select tabindex="1">
      <option>Heineken</option>
      <option>Carlsberg</option>
      <option>Stella Artois</option>
      <option>Cronenberg</option>
      <option>Guiness</option>
      <option>Amstel</option>
      <option>Corona</option>
    </select>
  </label>
  <div class="label-group">
    <div>Which is better?</div>
    <label>
      <input type="radio" name="cartoons" value="simpsons" tabindex="1">The Simpsons
    </label>
    <label>
      <input type="radio" name="cartoons" value="family_guy" tabindex="1">Family Guy
    </label>
    <label>
      <input type="radio" name="cartoons" value="southpark" tabindex="1">Southpark
    </label>
  </div>
</form>
  

Remove the class "form-horizontal" if you want to go back to the stacked layout.

3. Help messages and hints

To add a help message related to the input just put the text in a <span class="message"> directly after the input.

Stacked form
  
<form>
  <label>
    Email address
    <input type="email" placeholder="Email address" tabindex="1">
    <span="message">Please use a valid email address</span>
  </label>
</form>
  
Horizontal form
  
<form class="form-horizontal">
  <label>
    <div>Email address</div>
    <input type="email" placeholder="Email address" tabindex="1">
    <span class="message">Please use a valid email address</span>
  </label>
</form>
  

3.1 Stacked forms with inline help

If you want a stacked form but with inline help, then you need to use this form class: <form class="help-inline"> and also wrap the label text in a <div> (same structure as the horizontal forms).

  
<form class="help-inline&quot>
  <label>
    <div>Email address</div>
    <input type="email" placeholder="Email address" tabindex="1">
    <span="message">Please use a valid email address</span>
  </label>
</form>
  

3.2 Horizontal forms with help message below

To use the horizontal form layout but have the help messages below (eg. for modal windows where you need the forms compact but not too wide) then use <form class="form-horizontal message-below&quot>

  
<form class="form-horizontal message-below&quot>
  <label>
    <div>Email address</div>
    <input type="email" placeholder="Email address" tabindex="1">
    <span="message">Please use a valid email address</span>
  </label>
</form>
  

3.3 Help message displayed on :focus

If you want to keep your forms as clean and uncluttered as possible you might prefer to display the relevant help message only when the user focuses on (clicks inside) the input. All you have to do is follow the same code structure as above but add the class "hint" to the <span>.

Stacked form
Horizontal form
  
<form>
  <strong>Stacked form</strong>
  <label>
    Name
    <input type="text" placeholder="Name" tabindex="1">
    <span class="message hint">Please enter your full name</span>
  </label>
  <label>
    Email address
    <input type="email" placeholder="Email address" tabindex="1">
    <span class="message hint">Must be a valid email address</span>
  </label>
</form>
<form class="form-horizontal">
  <strong>Horizontal form</strong>
  <label>
    <div>Name</div>
    <input type="text" placeholder="Name" tabindex="1">
    <span class="message hint">Please enter your full name</span>
  </label>
  <label>
    <div>Email address</div>
    <input type="email" placeholder="Email address" tabindex="1">
    <span class="message hint">Must be a valid email address</span>
  </label>
</form>
  

4. Overriding the defaults

Defaults are great but sometimes you need to do things a bit differently...here are some examples:

4.1 Stacked form with everything inline

Sometimes when using the stacked form you'll find that it makes no sense to have the radio or checkbox inputs stacked because the associated text is so short that you may as well keep it all inline.

All you have to do is add the class "inline" to the <div class="label-group"> so it becomes <div class="label-group inline">.

Which is better?
  
<form>
  <div class="label-group inline">
    Which is better?
    <label>
      <input type="radio" name="cartoons" value="simpsons" tabindex="1">The Simpsons
    </label>
    <label>
      <input type="radio" name="cartoons" value="family_guy" tabindex="1">Family Guy
    </label>
    <label>
      <input type="radio" name="cartoons" value="southpark" tabindex="1">Southpark
    </label>
  </div>
</form>
  

4.2 Stacked forms with only the inputs inline

If you're using the stacked forms and you want all the inputs inline but you want to keep the label text above the inputs. Then you can wrap it in a <div&gt to make it a block element, like so:

Of the following animated series which one do you prefer?
  
<form>
  <div class="label-group inline">
    <div&gtOf the following animated series which one do you prefer?</div>
    <label>
      <input type="radio" name="cartoons" value="simpsons" tabindex="1">The Simpsons
    </label>
    <label>
      <input type="radio" name="cartoons" value="family_guy" tabindex="1">Family Guy
    </label>
    <label>
      <input type="radio" name="cartoons" value="southpark" tabindex="1">Southpark
    </label>
  </div>
</form>
  

5. Dimensions

Some classes to have a bit more control over the sizes of the inputs.

5.1 Simple classes

These are very simple classes: mini, small, large and xl. You don't need to specify "medium" because it's the default size.

  
<form class="form-horizontal">
  <label>
    <div>Mini</div>
    <input type="text" tabindex="1" class="mini">
  </label>
  <label>
    <div>Small</div>
    <input type="text" tabindex="1" class="small">
  </label>
  <label>
    <div>Medium</div>
    <input type="text" tabindex="1">
    <span class="message">(default)</span>
  </label>
  <label>
    <div>Large</div>
    <input type="text" tabindex="1" class="large">
  </label>
  <label>
    <div>Xlarge</div>
    <input type="text" tabindex="1" class="xl">
  </label>
</form>
  

5.2 Specific classes

More specific classes to get the exact sizes you need.

  
<form class="form-horizontal">
  <label>
    <div>Size 1</div>
    <input type="text" tabindex="1" class="size1">
  </label>
  <label>
    <div>Size 2</div>
    <input type="text" tabindex="1" class="size2">
  </label>
  <label>
    <div>Size 3</div>
    <input type="text" tabindex="1" class="size3">
  </label>
  <label>
    <div>Size 4</div>
    <input type="text" tabindex="1" class="size4">
  </label>
  <label>
    <div>Size 5</div>
    <input type="text" tabindex="1" class="size5">
  </label>
  <label>
    <div>Size 6</div>
    <input type="text" tabindex="1" class="size6">
  </label>
  <label>
    <div>Size 7</div>
    <input type="text" tabindex="1" class="size7">
  </label>
  <label>
    <div>Size 8</div>
    <input type="text" tabindex="1" class="size8">
  </label>
  <label>
    <div>Size 9</div>
    <input type="text" tabindex="1" class="size9">
  </label>
  <label>
    <div>Size 10</div>
    <input type="text" tabindex="1" class="size10">
  </label>
  <label>
    <div>Size 11</div>
    <input type="text" tabindex="1" class="size11">
  </label>
  <label>
    <div>Size 12</div>
    <input type="text" tabindex="1" class="size12">
  </label>
</form>
  

6. Prepended and appended inputs

Some little labels to add before or after an input eg. to show expected currency.

6.1 Prepend

The prepend is really simple, just add a <i class="prepend"></i> before the input.

  
<form class="form-horizontal">
  <label>
    <div>Amount</div>
    <i class="prepend">$</i>
    <input type="text" placeholder="Amount" tabindex="1" class="size3">
    <span class="message">How much would you like to donate?<span>
  </label>
</form>
  

6.2 Append

The append is similar to the prepend but you need to add a class to the input that is being appended, so <i class="append"></i> for the append itself and <input class="appended"> for the input.

  
<form class="form-horizontal">
  <label>
    <div>Amount</div>
    <i class="prepend">$</i>
    <input type="text" placeholder="Amount" tabindex="1" class="size3">
    <span class="message">How much would you like to donate?<span>
  </label>
</form>
  

6.3 Both

You can use the prepend and append together, just combine all the classes above.

  
<form class="form-horizontal">
  <label>
    <div>Amount</div>
    <i class="prepend">$</i>
    <input type="text" placeholder="Amount" tabindex="1" class="appended size3">
    <i class="append">.00</i>
    <span class="message">How much would you like to donate?<span>
  </label>
</form>
  

7. Search

This form relies on using <input class="search-input"> and the submit button inmediately following the input using <button class="search-submit">.

  
<form>
  <label>
    <input type="search" class="search-input" placeholder="Search here..." tabindex="1">
    <button type="submit" class="search-submit">Go</button>
  </label>
</form>
  

8. Errors

For form validation you will need an error class, just add the class "error" to the <label> or <div class="label-group">

  
<form>
  <label class="error">
    Email address
    <input type="email" value="bob@something.domain" tabindex="1">
    <span class="message">Please use a valid email address</span>
  </label>
</form>

<form class="form-horizontal">
<label class="error">
<div>Email address</div>
<input type="email" value="bob@something.domain" tabindex="1">
<span class="message">Please use a valid email address</span>
</label>
</form>


9. Fieldsets and legends

Fieldsets and legends can be great for breaking up long forms, just use them the way you normally would:

Account details
Address
  
<form class="form-horizontal">
  <fieldset>
    <legend>Account details</legend>
    <label>
      <div>Username</div>
      <input type="text" placeholder="Username" tabindex="1"">
      <span class="message hint">Must be at least five characters</span>
    </label>
    <label>
      <div>Password</div>
      <input type="password" placeholder="Password" tabindex="1">
      <span class="message hint">Must contain one number and one capital letter</span>
    </label>
    <label>
      <div>Repeat password</div>
      <input type="password" placeholder="Password" tabindex="1">
    </label>
    <label>
      <div>Email address</div>
      <input type="email" placeholder="Email" tabindex="1">
      <span class="message hint">Must be a valid email address</span>
    </label>
  </fieldset>

<fieldset>
<legend>Address</legend>
<label>
<div>First name</div>
<input type="text" placeholder="First name" tabindex="1">
</label>
<label>
<div>Last name</div>
<input type="text" placeholder="Last name" tabindex="1">
</label>
<label>
<div>Address</div>
<textarea placeholder="Address (House number and street)" tabindex="1"></textarea>
</label>
<label>
<div>City</div>
<input type="text" placeholder="City" tabindex="1">
</label>
<label>
<div>Postcode</div>
<input type="text" placeholder="Postcode" tabindex="1">
</label>
<label>
<div>Country</div>
<select tabindex="1">
<option>Spain</option>
<option>United Kingdom</option>
</select>
</label>
</fieldset>
</form>


10. Buttons

There is some default styling for buttons, the basic uses a .button class and for your primary action combine it with .primary. There are also two positions for buttons, either sitting directly below the form or right aligned.

10.1 Standard positioning

  
<form>
  <label>
    Email address
    <input type="email" tabindex="1">
  </label>
  <label>
    Password
    <input type="password" tabindex="1">
  </label>
  <button type="submit" class="button">Login</button>
</form>

<form class="form-horizontal">
<label>
<div>Email address</div>
<input type="email" tabindex="1">
</label>
<label>
<div>Password</div>
<input type="password" tabindex="1">
</label>
<button type="submit" class="button">Login</button>
</form>


10.2 Right aligned

Just wrap your submit button in a <div class="submit-wrapper">.

  
<form>
  <label>
    Email address
    <input type="email" tabindex="1">
  </label>
  <label>
    Password
    <input type="password" tabindex="1">
  </label>
  <div class="submit-wrapper">
    <button type="submit" class="button">Login</button>
  </div>
</form>

<form class="form-horizontal">
<label>
<div>Email address</div>
<input type="email" tabindex="1">
</label>
<label>
<div>Password</div>
<input type="password" tabindex="1">
</label>
<div class="submit-wrapper">
<button type="submit" class="button">Login</button>
</div>
</form>


11. Required fields

Just add the class .required to the <label>

  
<form>
  <label class="required">
    Email
    <input type="email" tabindex="1">
  </label>
</form>

<form class="form-horizontal">
<label class="required">
<div>Email</div>
<input type="email" tabindex="1">
</label>
</form>


Responsive?

The horizontal forms turn into stacked forms on small screens.

comments powered by Disqus