Structure to follow for consistent and accessible forms.
Whenever possible, we only use semantic HTML elements (ex: fieldset, legend) to style and lay out forms. But when required, we have a number of BEM classes to help build flexible but consistent forms.
All elements below are required unless marked as optional.
FormTop-level element required to for all forms. In order for all the default base styles to be applied, a class "ui-icon" must be used.
FieldsetUsed to visually and semantically group multiple form inputs together.
Legend (optional)Legend is used in conjunction with fieldset to display a title for the fieldset group
LabelEach input should have a label. By default, we recommend to wrap the <label> around the input, this allows the input to get focus when we click the label without having to use ID or for="" attributes.
An optional sublabel can be displayed between the label and text input, by adding a class "ui-form__sublabel" to an element (div).
InputInput (or radio, checkbox, textarea, etc...) should be placed inside a label element.
Error message (optional)Validation message ("ui-form__error") displayed when form field has error(s).
<!-- basic form -->
<form class="ui-form">
<!-- related form inputs should be grouped under a <fieldset> -->
<fieldset>
<legend>...</legend>
<!-- each form input is inside a div with class "ui-form__group" -->
<!-- this allows better control of the layout for different breakpoints -->
<div class="ui-form__group">
<label>
<div class="ui-form__label">...</div>
<div class="ui-form__sublabel">...</div>
<div class="ui-form__input-wrapper">
<input class="ui-input" type="text" />
</div>
</label>
</div>
<div class="ui-form__group">
<label>
<div class="ui-form__label">...</div>
<div class="ui-form__sublabel">...</div>
<div class="ui-form__input-wrapper">
<input class="ui-input" type="text" />
</div>
</label>
</div>
</fieldset>
</form>
<!-- dropdown (select) -->
<form class="ui-form">
<!-- related form inputs should be grouped under a <fieldset> -->
<fieldset>
<legend>...</legend>
<div class="ui-form__group">
<label>
<div class="ui-form__label">...</div>
<div class="ui-form__sublabel">...</div>
<!-- dropdown component -->
<div class="ui-form__dropdown-wrapper">
<!-- the <select> will be hidden with CSS but its value can be updated with javascript -->
<!-- this allows the form to be submitted with the chosen value -->
<select>
<option>...</option>
<option value="1">...</option>
<option value="2">...</option>
<option value="3" disabled="">...</option>
</select>
<!-- the custom dropdown markup starts here -->
<!-- the "ui-dropdown" element takes 2 modifier classes: -->
<!-- "ui-dropdown--active" ==> expands the options list -->
<!-- "ui-dropdown--selected" ==> collapses the options list and displays the selected options -->
<div class="ui-dropdown">
<button class="ui-dropdown__selection">
<div class="ui-dropdown__placeholder">...</div>
<div class="ui-dropdown__current">...</div>
</button>
<ul class="ui-dropdown__list">
<li class="ui-dropdown__option">
<button class="ui-dropdown__btn">...</button>
</li>
<li class="ui-dropdown__option">
<button class="ui-dropdown__btn">...</button>
</li>
<li class="ui-dropdown__option ui-dropdown__option--disabled">
<button class="ui-dropdown__btn">...</button>
</li>
</ul>
</div>
</div>
</label>
</div>
</fieldset>
</form>
<!-- form with errors -->
<form class="ui-form">
<!-- related form inputs should be grouped under a <fieldset> -->
<fieldset>
<legend>...</legend>
<!-- form group has an error modifier class -->
<div class="ui-form__group ui-form__group--error">
<label>
<div class="ui-form__label">...</div>
<div class="ui-form__sublabel">...</div>
<div class="ui-form__input-wrapper">
<input class="ui-input" type="text" />
</div>
<!-- a message element is added to display error/warning messages -->
<div class="ui-form__message">...</div>
</label>
</div>
</fieldset>
</form>
For multi-column form layouts, simply use the grid and include .ui-form__group within each column.
<!-- 2-colum form -->
<!-- will render any number of "ui-form__group" in 2 columns -->
<form class="ui-form">
<fieldset>
<legend>...</legend>
<!-- use grid row/col to layout form inputs in columns -->
<div class="ui-row">
<div class="ui-col">
<div class="ui-form__group">...</div>
</div>
<div class="ui-col">
<div class="ui-form__group">...</div>
</div>
</div>
</fieldset>
</form>