Building up a form takes time, but should be a simple case of combining all the elements here in a sensible way.
The basic unit in forms is the form-element. This is a molecule, made up of one or more atoms. The atoms can be an input
, a textarea
, a number of checkbox
or radio
buttons, or a select
dropdown. It combines a label with these form elements and boxes them all up in a handy-sized div
.
Firstly, a few different input types (note the hidden
type at the end):
<div class="c-form__element">
<label class="c-form__label" for="a">Name</label>
<input class="c-form__input c-form__input--text" type="text" id="a" name="a" placeholder="Enter your name" />
</div>
<div class="c-form__element">
<label class="c-form__label" for="b">Email</label>
<input class="c-form__input c-form__input--email" type="email" id="b" name="b" />
</div>
<div class="c-form__element">
<label class="c-form__label" for="c">Image</label>
<input class="c-form__input c-form__input--file" type="file" id="c" name="c" />
</div>
<div class="c-form__element">
<label class="c-form__label" for="d">Password</label>
<input class="c-form__input c-form__input--password" type="password" id="d" name="d" />
</div>
<div class="c-form__element">
<label class="c-form__label" for="e">Website</label>
<input class="c-form__input c-form__input--url" type="url" id="e" name="e" value="http://" />
</div>
<div class="c-form__element">
<label class="c-form__label" for="f">Phone</label>
<input class="c-form__input c-form__input--tel" type="tel" id="f" name="f" />
</div>
<div class="c-form__element">
<label class="c-form__label" for="f2">Search</label>
<input class="c-form__input c-form__input--search" type="search" id="f2" name="f2" />
</div>
<div class="c-form__element">
<label class="c-form__label" for="g">Your Comment</label>
<textarea class="c-form__input c-form__input--textarea" id="g" name="g" placeholder="Please add a well-written, grammatically correct comment"></textarea>
</div>
<div class="c-form__element">
<label class="c-form__label" for="g">Your Comment</label>
<textarea class="c-form__input c-form__input--textarea c-form__input--textarea--double" id="g" name="g" placeholder="Please add a slightly longer well-written, grammatically correct comment"></textarea>
</div>
<div class="c-form__element">
<label class="c-form__label" for="g">Your Comment</label>
<textarea class="c-form__input c-form__input--textarea c-form__input--textarea--treble" id="g" name="g" placeholder="Please add a very long well-written, grammatically correct comment"></textarea>
</div>
<div class="c-form__element">
<input class="c-form__input c-form__input--hidden" type="hidden" id="h" name="h" value="this is a secret value" />
</div>
Of course, you're not just going to need input
s and textarea
s. Checkbox lists, select
dropdowns and radio lists are molecules, made up of an array of checkbox
, option
or radio
atoms.
<div class="c-form__element c-form__element--select">
<label class="c-form__label" for="i">What is your favourite colour?</label>
<div class="c-form__input c-form__input--select">
<select class="c-form__select" name="i" id="i">
<option value="red">Red</option>
<option value="blue">Blue</option>
<option value="green">Green</option>
<option value="yellow">Yellow</option>
</select>
</div>
</div>
<div class="c-form__element">
<label class="c-form__label" for="j">What instruments do you play?</label>
<div class="c-form__element-group" id="j">
<div class="c-form__checkbox-group">
<input class="c-form__checkbox" type="checkbox" id="j-ukulele" name="j" value="ukulele" />
<label for="j-ukulele" class="c-form__label">Ukulele</label>
</div>
<div class="c-form__checkbox-group">
<input class="c-form__checkbox" type="checkbox" id="j-mandolin" name="j" value="mandolin" />
<label for="j-mandolin" class="c-form__label">Mandolin</label>
</div>
<div class="c-form__checkbox-group">
<input class="c-form__checkbox" type="checkbox" id="j-banjo" name="j" value="banjo" checked />
<label for="j-banjo" class="c-form__label">Banjo</label>
</div>
<div class="c-form__checkbox-group">
<input class="c-form__checkbox" type="checkbox" id="j-guitar" name="j" value="guitar" />
<label for="j-guitar" class="c-form__label">Guitar</label>
</div>
</div>
</div>
<div class="c-form__element">
<label class="c-form__label" for="k">Do you know the way to San Jose?</label>
<div class="c-form__element-group" id="k">
<div class="c-form__radio-group">
<input class="c-form__radio" type="radio" id="k-yes" name="k" value="yes" />
<label for="k-yes" class="c-form__label">Yes</label>
</div>
<div class="c-form__radio-group">
<input class="c-form__radio" type="radio" id="k-no" name="k" value="no" />
<label for="k-no" class="c-form__label">No</label>
</div>
<div class="c-form__radio-group">
<input class="c-form__radio" type="radio" id="k-unsure" name="k" value="unsure" />
<label for="k-unsure" class="c-form__label">Not sure</label>
</div>
</div>
</div>
Form hints
You can add a hint
to any form-element
, to give users more information about a form field.
<div class="c-form__element">
<label class="c-form__label" for="l">Password</label>
<input class="c-form__input c-form__input--password" type="password" id="l" name="l" />
<small class="c-form__hint">Must contain a letter, a number, a hieroglyph and at least two Cyrillic characters</small>
</div>
You can put these together in the usual grid system: a grid-row
can be form-elements
that are three third
s, two half
s, a half
and two quarter
s, and so on.
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element">
<label class="c-form__label" for="l2">Bippity</label>
<input class="c-form__input c-form__input--text" type="text" id="l2" name="l2" />
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element">
<label class="c-form__label" for="m">Boppity</label>
<input class="c-form__input c-form__input--text" type="text" id="m" name="m" />
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element">
<label class="c-form__label" for="n">Boo</label>
<input class="c-form__input c-form__input--text" type="text" id="n" name="n" />
</div>
</div>
</div>
And finally, the form
organism: a load of grid-row
s. The default style is form-stacked
.
<form action="#" method="get" class="c-form c-form--stacked">
<fieldset>
<legend class="c-form__legend">Fill in this form</legend>
<div class="o-grid">
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element">
<label class="c-form__label" for="sa">Text input</label>
<input class="c-form__input c-form__input--text" type="text" id="sa" name="sa" />
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element">
<label class="c-form__label" for="sb">File input</label>
<input class="c-form__input c-form__input--file" type="file" id="sb" name="sb" />
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element">
<label class="c-form__label" for="sc">Password</label>
<input class="c-form__input c-form__input--password" type="password" id="sc" name="sc" />
<small class="c-form__hint">Must contain a letter, a number, a hieroglyph and at least two Cyrillic characters</small>
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element">
<label class="c-form__label" for="sd">Email</label>
<input class="c-form__input c-form__input--email" type="email" id="sd" name="sd" />
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element">
<label class="c-form__label" for="se">URL</label>
<input class="c-form__input c-form__input--url" type="url" id="se" name="se" />
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element">
<label class="c-form__label" for="sf">Telephone</label>
<input class="c-form__input c-form__input--tel" type="tel" id="sf" name="sf" />
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element c-form__element--select">
<label class="c-form__label" for="sg">Select</label>
<div class="c-form__input c-form__input--select">
<select class="c-form__select" name="sg" id="sg">
<option value="red">Red</option>
<option value="blue">Blue</option>
<option value="green">Green</option>
<option value="yellow">Yellow</option>
</select>
</div>
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element">
<label class="c-form__label" for="sh">Radio</label>
<div class="c-form__element-group" id="sh">
<div class="c-form__radio-group">
<input class="c-form__radio" type="radio" id="sh-yes" name="sh" value="yes" />
<label for="sh-yes" class="c-form__label">Yes</label>
</div>
<div class="c-form__radio-group">
<input class="c-form__radio" type="radio" id="sh-no" name="sh" value="no" />
<label for="sh-no" class="c-form__label">No</label>
</div>
<div class="c-form__radio-group">
<input class="c-form__radio" type="radio" id="sh-unsure" name="sh" value="unsure" />
<label for="sh-unsure" class="c-form__label">Not sure</label>
</div>
</div>
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element">
<label class="c-form__label" for="si">Checkbox</label>
<div class="c-form__element-group" id="si">
<div class="c-form__checkbox-group">
<input class="c-form__checkbox" type="checkbox" id="si-ukulele" name="si" value="ukulele" />
<label for="si-ukulele" class="c-form__label">Ukulele</label>
</div>
<div class="c-form__checkbox-group">
<input class="c-form__checkbox" type="checkbox" id="si-mandolin" name="si" value="mandolin" />
<label for="si-mandolin" class="c-form__label">Mandolin</label>
</div>
<div class="c-form__checkbox-group">
<input class="c-form__checkbox" type="checkbox" id="si-banjo" name="si" value="banjo" checked />
<label for="si-banjo" class="c-form__label">Banjo</label>
</div>
</div>
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<div class="c-form__element">
<label class="c-form__label" for="sj">Textarea</label>
<textarea class="c-form__input c-form__input--textarea" id="sj" name="sj"></textarea>
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<button class="c-btn c-btn--medium">Submit</button>
</div>
</div>
</div>
</fieldset>
</form>
Inline forms
Inline forms have the label and the input on the same line. By default, the label is 25% of the width of the row, and the input is the remaining 75%. Because of this it's not recommended to put inline forms into quarter- or third-width grid boxes. Here is the same form as above but as a form-inline
version.
<form action="#" method="get" class="c-form c-form--inline">
<fieldset>
<legend class="c-form__legend">Fill in this form</legend>
<div class="o-grid">
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<div class="c-form__element">
<label class="c-form__label" for="ia">Text input</label>
<input class="c-form__input c-form__input--text" type="text" id="ia" name="ia" />
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<div class="c-form__element">
<label class="c-form__label" for="ib">File input</label>
<input class="c-form__input c-form__input--file" type="file" id="ib" name="ib" />
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<div class="c-form__element">
<label class="c-form__label" for="ic">Password</label>
<input class="c-form__input c-form__input--password" type="password" id="ic" name="ic" />
<small class="c-form__hint">Must contain a letter, a number, a hieroglyph and at least two Cyrillic characters</small>
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<div class="c-form__element">
<label class="c-form__label" for="id">Email</label>
<input class="c-form__input c-form__input--email" type="email" id="id" name="id" />
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<div class="c-form__element">
<label class="c-form__label" for="ie">URL</label>
<input class="c-form__input c-form__input--url" type="url" id="ie" name="ie" />
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<div class="c-form__element">
<label class="c-form__label" for="if">Telephone</label>
<input class="c-form__input c-form__input--tel" type="tel" id="if" name="if" />
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<div class="c-form__element c-form__element--select">
<label class="c-form__label" for="ig">Select</label>
<div class="c-form__input c-form__input--select">
<select class="c-form__select" name="ig" id="ig">
<option value="red">Red</option>
<option value="blue">Blue</option>
<option value="green">Green</option>
<option value="yellow">Yellow</option>
</select>
</div>
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<div class="c-form__element">
<label class="c-form__label" for="ih">Radio</label>
<div class="c-form__element-group" id="ih">
<div class="c-form__radio-group">
<input class="c-form__radio" type="radio" id="j-yes" name="j" value="yes" />
<label for="j-yes" class="c-form__label">Yes</label>
</div>
<div class="c-form__radio-group">
<input class="c-form__radio" type="radio" id="j-no" name="j" value="no" />
<label for="j-no" class="c-form__label">No</label>
</div>
<div class="c-form__radio-group">
<input class="c-form__radio" type="radio" id="j-unsure" name="j" value="unsure" />
<label for="j-unsure" class="c-form__label">Not sure</label>
</div>
</div>
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<div class="c-form__element">
<label class="c-form__label" for="ii">Checkbox</label>
<div class="c-form__element-group" id="ii">
<div class="c-form__checkbox-group">
<input class="c-form__checkbox" type="checkbox" id="j-ukulele" name="j" value="ukulele" />
<label for="j-ukulele" class="c-form__label">Ukulele</label>
</div>
<div class="c-form__checkbox-group">
<input class="c-form__checkbox" type="checkbox" id="j-mandolin" name="j" value="mandolin" />
<label for="j-mandolin" class="c-form__label">Mandolin</label>
</div>
<div class="c-form__checkbox-group">
<input class="c-form__checkbox" type="checkbox" id="j-banjo" name="j" value="banjo" checked />
<label for="j-banjo" class="c-form__label">Banjo</label>
</div>
</div>
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<div class="c-form__element">
<label class="c-form__label" for="ij">Textarea</label>
<textarea class="c-form__input c-form__input--textarea" id="ij" name="ij"></textarea>
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<button class="c-btn c-btn--medium">Submit</button>
</div>
</div>
</div>
</fieldset>
</form>
Joined forms
A joined form is a single-field form with the submit button joined to the end. It must be a text-style input that is joined to the button (or it won't fit). No label is required.
<form action="#" method="get" class="c-form c-form--joined">
<fieldset>
<legend class="c-form__legend">A joined form and button</legend>
<div class="o-grid">
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<div class="c-form__element">
<input class="c-form__input c-form__input--text" type="text" id="ja" name="ja" placeholder="Enter your search term here" aria-label="Search" />
<button type="submit" class="c-btn c-btn--medium">Search<i class="c-icon c-icon--search c-icon--after"></i></button>
</div>
</div>
</div>
</div>
</fieldset>
</form>
Form validation
Add an is-invalid
class to the form-element
div to flag it up as invalid its contents. You can also add a hint-invalid
message to each invalid element, if required.
<form action="#" method="get" class="c-form c-form--stacked">
<fieldset>
<legend class="c-form__legend">Fill in this form</legend>
<div class="o-grid">
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element is-invalid">
<label class="c-form__label" for="sa2">Text input</label>
<input class="c-form__input c-form__input--text" type="text" id="sa2" name="sa2" />
<small class="c-form__hint is-invalid">This field cannot be empty</small>
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element is-invalid">
<label class="c-form__label" for="sb2">File input</label>
<input class="c-form__input c-form__input--file" type="file" id="sb2" name="sb2" />
<small class="c-form__hint is-invalid">This field cannot be empty</small>
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element is-invalid">
<label class="c-form__label" for="sc2">Password</label>
<input class="c-form__input c-form__input--password" type="password" id="sc2" name="sc2" />
<small class="c-form__hint">Must contain a letter, a number, a hieroglyph and at least two Cyrillic characters</small>
<small class="c-form__hint is-invalid">This field cannot be empty</small>
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element is-invalid">
<label class="c-form__label" for="sd2">Email</label>
<input class="c-form__input c-form__input--email" type="email" id="sd2" name="sd2" />
<small class="c-form__hint is-invalid">This field cannot be empty</small>
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element is-invalid">
<label class="c-form__label" for="se2">URL</label>
<input class="c-form__input c-form__input--url" type="url" id="se2" name="se2" />
<small class="c-form__hint is-invalid">This field cannot be empty</small>
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element is-invalid">
<label class="c-form__label" for="sf2">Telephone</label>
<input class="c-form__input c-form__input--tel" type="tel" id="sf2" name="sf2" />
<small class="c-form__hint is-invalid">This field cannot be empty</small>
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element c-form__element--select is-invalid">
<label class="c-form__label" for="sg2">Select</label>
<div class="c-form__input c-form__input--select">
<select class="c-form__select" name="sg2" id="sg2">
<option value="red">Red</option>
<option value="blue">Blue</option>
<option value="green">Green</option>
<option value="yellow">Yellow</option>
</select>
</div>
<small class="c-form__hint is-invalid">This field cannot be empty</small>
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element is-invalid">
<label class="c-form__label" for="sh2">Radio</label>
<div class="c-form__element-group" id="sh2">
<div class="c-form__radio-group">
<input class="c-form__radio" type="radio" id="sh2-yes" name="sh2" value="yes" />
<label for="sh2-yes" class="c-form__label">Yes</label>
</div>
<div class="c-form__radio-group">
<input class="c-form__radio" type="radio" id="sh2-no" name="sh2" value="no" />
<label for="sh2-no" class="c-form__label">No</label>
</div>
<div class="c-form__radio-group">
<input class="c-form__radio" type="radio" id="sh2-unsure" name="sh2" value="unsure" />
<label for="sh2-unsure" class="c-form__label">Not sure</label>
</div>
</div>
<small class="c-form__hint is-invalid">This field cannot be empty</small>
</div>
</div>
<div class="o-grid__box o-grid__box--third">
<div class="c-form__element is-invalid">
<label class="c-form__label" for="si2">Checkbox</label>
<div class="c-form__element-group" id="si2">
<div class="c-form__checkbox-group">
<input class="c-form__checkbox" type="checkbox" id="si2-ukulele" name="si2" value="ukulele" />
<label for="si2-ukulele" class="c-form__label">Ukulele</label>
</div>
<div class="c-form__checkbox-group">
<input class="c-form__checkbox" type="checkbox" id="si2-mandolin" name="si2" value="mandolin" />
<label for="si2-mandolin" class="c-form__label">Mandolin</label>
</div>
<div class="c-form__checkbox-group">
<input class="c-form__checkbox" type="checkbox" id="si2-banjo" name="si2" value="banjo" checked />
<label for="si2-banjo" class="c-form__label">Banjo</label>
</div>
</div>
<small class="c-form__hint is-invalid">This field cannot be empty</small>
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<div class="c-form__element is-invalid">
<label class="c-form__label" for="sj2">Textarea</label>
<textarea class="c-form__input c-form__input--textarea" id="sj2" name="sj2"></textarea>
<small class="c-form__hint is-invalid">This field cannot be empty</small>
</div>
</div>
</div>
<div class="o-grid__row">
<div class="o-grid__box o-grid__box--full">
<button class="c-btn c-btn--medium">Submit</button>
</div>
</div>
</div>
</fieldset>
</form>
Options
Atoms
input
- type: one of text (default), file, hidden, password, email, url and tel
- value: the default
value
of theinput
- placeholder: placeholder text (don't rely on this text being there - it's not supported in <IE10)
option
- label: the text in the option field (required)
- value: the
value
of theoption
(required)
checkbox
- label: the text in the accompanying label field (required)
- value: the
value
of thecheckbox
(required) - name: the `name attribute (must be the same for all checkboxes/radios) (required)
radio
- label: the text in the accompanying label field (required)
- value: the
value
of theradio
(required) - name: the `name attribute (must be the same for all checkboxes/radios) (required)
Molecules
- form-element
- label: the label attached to the form element (required)
- name: the name of the form field (required)
- select: true if this is a
select
dropdown - size: one of half, quarter or third (leaving blank will render full-width)
- hint: (string) Help users out with tricky form questions
- invalid: (Boolean) (default
false
) whether the field is invalid or not - hint-invalid: (string) Error message for invalid fields
- atoms: an array of atoms (multiple
options
,checkboxes
orradios
) or an atom object (i.e. oneinput
). If this is missing a textinput
is added by default
Organisms
- form
- type: supported types are stacked (default), joined or inline
- action: URL to submit the form to. Can be absolute or relative. Defaults to "#"
- method: either post (default) or get
- id: an _id_ to identify the form
- legend: some text to go in the
legend
of the form. Default is to omit it altogether. - atoms: an array of
grid-row
molecules.
TODO
- Add validation options? (as
data-validation
option) - Fancy select boxes?
- Fancy file input?