Forms
Form structure tutorial
Unless specifically noted, the same markup is used for all variations of form style and layout. Forms are built up in a hierarchy:
- The Form element contains everything. The FORM element has the base class and layout modifier classes.
- Large forms can be broken into Form Sections with visible headings. Form Sections are comprised of a fieldset and legend (with inner span for styling).
- Form Sections contain Form Groups. There are three types of Form Group: single-input, multi-input and buttons.
- If the form isn't big enough to require Form Sections, simply leave them out and put Form Groups directly inside the Form element.
- Buttons can always appear as their own Group, as a sibling to Sections.
- Form Groups contain Form Items. There are two types of Form Item: label and input. This describes their purpose relative to the overall Form Group.
- Form Items contain input and label elements in a variety of configurations, plus supporting elements for errors, help text and layout purposes. All common HTML5 input types are supported.
Illustration of form structure
Interact to explore the hierarchy of forms - this structure must be followed in order for forms to work.
A short form with two simple inputs and a submit button would have this structure:
A long form with two sections:
Form - base element
The Form element has the base class ace-form
then one of the modifier classes to control the layout:
ace-form-toplabel
(default): labels sit above inputs.ace-form-sidelabel
: labels sit to the left of inputs, in a column style. Sidelabel collapses to top label layout at small screen sizes.ace-form-inline
: all inputs display in one line/row. Note that multi-line inputs like textareas and multi selects are not compatible with this layout.ace-form-filter
: inputs are top-labeled and display in a compact side-by-side layout. Note this is primarily designed for multiple checkbox and multiple radio sets; for the use case where a data set is being filtered by the selections.
If no modifier class is applied, top label style will be applied.
Form sections
Sections are used to break up very large forms; or to provide additional headings to clarify the purpose of sections of a form.
Sections contain form groups.
Sections contain form groups.
<form class="ace-form">
<fieldset class="ace-form-section">
<legend class="ace-form-legend"><span>Section Heading</span></legend>
<!-- Sections contain form groups-->
</fieldset>
<fieldset class="ace-form-section">
<legend class="ace-form-legend"><span>Section Heading</span></legend>
<!-- Sections contain form groups-->
</fieldset>
</form>
Form Groups
Single-input groups
Single input groups contain just one form input and its associated label element. For example, a single text field and a label describing it. Since there is only one input, no extra descriptive information is required.
Label
Input
<!-- Simplified example, do not copy this code-->
<div class="ace-form-group">
<div class="ace-form-item ace-form-item-label">
<!-- Label-->
</div>
<div class="ace-form-item ace-form-item-input">
<!-- Input-->
</div>
</div>
Full example:
<div class="ace-form-group ace-form-group-text" id="texttest-group">
<div class="ace-form-item ace-form-item-label">
<label class="ace-form-label" for="texttest"><span class="ace-text">Simple text input</span>
</label>
</div>
<div class="ace-form-item ace-form-item-text">
<input class="ace-form-input ace-form-input-text" type="text" id="texttest">
</input>
</div>
</div>
Multi-input groups
Multiple input groups contain more than one form input, each with an associated label element. This group of inputs must then have a visible text label describing the purpose of the whole group. For example, a group of checkboxes will have a label for each checkbox; then a legend to describe the group.
To accommodate this extra layer of description, the group is a fieldset instead of a DIV; and a legend is used for the group. The overall structure is the same as a single-input group, but different elements are used.
Group Legend
Input + Label
Input + Label
Input + Label
<!-- Simplified example, do not copy this code-->
<fieldset class="ace-form-group">
<legend class="ace-form-item ace-form-item-label">
<span><!-- Group Legend --></span>
</legend>
<div class="ace-form-item ace-form-item-input">
<!-- Input + Label-->
<!-- Input + Label-->
<!-- Input + Label-->
</div>
</fieldset>
Full example, using checkboxes:
<fieldset class="ace-form-group ace-form-group-checkbox">
<legend class="ace-form-item ace-form-item-label"><span>Multi checkbox</span></legend>
<div class="ace-form-item ace-form-item-input">
<div class="ace-form-input-checkbox-set">
<input class="ace-form-input ace-form-input-checkbox" type="checkbox" id="multicheck1">
</input>
<label class="ace-form-label" for="multicheck1"><span class="ace-text">Check 1</span>
</label>
</div>
<div class="ace-form-input-checkbox-set">
<input class="ace-form-input ace-form-input-checkbox" type="checkbox" id="multicheck2">
</input>
<label class="ace-form-label" for="multicheck2"><span class="ace-text">Check 2</span>
</label>
</div>
</div>
</fieldset>
Form sub-items
Within multi groups, it is sometimes necessary to create sub-groups. By default these render as new 'rows' within the multi-group's input area.
<fieldset class="ace-form-group ace-form-group-text">
<legend class="ace-form-item ace-form-item-label"><span>Subitems example</span></legend>
<div class="ace-form-item ace-form-item-input">
<div class="ace-form-subitem">
<!-- inputs-->
</div>
<div class="ace-form-subitem">
<!-- inputs-->
</div>
</div>
</fieldset>
Form group classes
Form groups have additional classes based on the number and type of input(s) they contain; and the state of the inputs.
Form groups each have a type class matched to the input, eg. ace-form-group-text
for text inputs.
<div class="ace-form-group ace-form-group-text">
</div>
This includes multi-groups for radio buttons and checkboxes:
<fieldset class="ace-form-group ace-form-group-radio">
</fieldset>
When a multi group contains a mix of form input types, they will be displayed as a single row of inputs. That is, mixed groups are displayed in an inline layout. As such they get two extra classes:
<fieldset class="ace-form-group ace-form-group-inline ace-form-group-mixed">
</fieldset>
Form button groups
Buttons get a dedicated group and item pattern:
<div class="ace-form-group ace-form-group-buttons">
<div class="ace-form-item ace-form-item-buttons">
<button class="ace-button" type="submit"><span>Submit</span></button>
</div>
</div>
Error state
Error state is reflected with the class ace-form-error
on both the group and input:
<!-- Simplified example, do not copy this code -->
<div class="ace-form-group ace-form-error">
<div class="ace-form-item ..."><!-- Label--></div>
<div class="ace-form-item ...">
<input class="ace-form-input ace-form-error ...">
</div>
</div>
Error text is supplied in a DIV, associated with the aria-describedby
attribute:
<!-- Simplified example, do not copy this code -->
<div class="ace-form-group ace-form-error">
<div class="ace-form-item"><!-- Label--></div>
<div class="ace-form-item">
<input class="ace-form-input ace-form-error" aria-describedby="errormessage" ...>
<div class="ace-form-input-state ace-form-error" id="errormessage" tabIndex="-1">
Error text explaining what to do
</div>
</div>
</div>
Full example:
<div class="ace-form-group ace-form-error ace-form-group-text" id="errormessage-group">
<div class="ace-form-item ace-form-item-label">
<label class="ace-form-label" for="errormessage"><span class="ace-text">Error state</span>
</label>
</div>
<div class="ace-form-item ace-form-item-text">
<input class="ace-form-input ace-form-input-text ace-form-error" type="text" aria-describedby="errormessagemessage" id="errormessage">
</input>
<div class="ace-form-input-state ace-form-error" id="errormessagemessage" tabIndex="-1">Error text explaining what to do</div>
</div>
</div>
Inputs and labels
- LABEL elements are required for all INPUT elements of all types; and the two must be associated with the FOR and ID attributes.
- All labels require the class
ace-form-label
- All inputs require the class
ace-form-input
- Textareas, radios and checkboxes also require
ace-form-textarea
,ace-form-radio
andace-form-checkbox
respectively - Each radio button and label pair is wrapped in a div with class
ace-form-input-radio-set
- Each checkbox and label pair is wrapped in a div with class
ace-form-input-radio-set
- Each input can be followed by a state or information message DIV, associated with an
aria-describedby
attribute.
Hidden inputs
Hidden form inputs can only be placed in two ways in an ACE Form:
- As the last child of a form group
- Inside an ace-form-hidden
- ace-form-hidden must be the first child element in the ACE Form
- ace-form-hidden can not contain anything other than hidden inputs
Full example:
<form class="ace-form ace-form-toplabel">
<div class="ace-form-hidden">
<input class="ace-form-input ace-form-input-hidden" type="hidden" id="hiddentoptoplabel">
</input>
</div>
<div class="ace-form-group ace-form-group-text">
<div class="ace-form-item ace-form-item-label">
<label class="ace-form-label" for="textvisibletoptoplabel"><span class="ace-text">visible input</span>
</label>
</div>
<div class="ace-form-item ace-form-item-text">
<input class="ace-form-input ace-form-input-text" type="text" id="textvisibletoptoplabel">
</input>
</div>
</div>
</form>