

Photo: Vivek Kumar
Form
Introduction
Forms are notoriously challenging to style and make accessible. Natura11y provides basic style and behavior for building user friendly, accessible forms.
Form Entries
The form entry parent selector (.form-entry) wraps each entry within a form. Child elements within form entries vary depending on their input types. Such types include text inputs, textareas, selects, checkboxes, and radios.
In Figure 1, the .form-entry selector contains an <input> field with the type="text" attribute.
<div class="form-entry">
<label class="form-entry__field">
<span class="form-entry__field__label"> Form Entry Label </span>
<span class="form-entry__field__input"> <input type="text" name="textInputExample" id="text-input-example" aria-describedby="help-text-input-example" /> </span>
</label>
<small class="form-entry__help" id="help-text-input-example"> Form entry help text </small>
</div>| Lines | Details |
|---|---|
| 1 | The It contains each entries elements, including help text and feedback messages. When more than one |
| 3-18 | The It holds the field’s label and input elements. The It holds the actual label text, and required indicator (when present). The It holds the field’s actual input elements. When using help text, |
| 20-22 | The Its id equals its associated |
Search Entry
Use the .form-entry--search modifier on the .form-entry element to create an accessible search field. A [data-search-clear] button inside .form-entry__field__input is shown automatically by Natura11y’s JavaScript when the field has a value, and hidden when it is empty.
The label can be visually hidden with .screen-reader-only — a visible label is not required when a leading search icon makes the purpose clear.
<div class="form-entry form-entry--search">
<label class="form-entry__field">
<span class="form-entry__field__label screen-reader-only"> Search </span>
<span class="form-entry__field__input"> <span class="icon icon-search opacity-50" aria-hidden="true"></span> <input type="search" id="search-example" name="searchExample" />
<button type="button" class="button button--icon-only" data-search-clear aria-label="Clear search" aria-controls="search-example"> <span class="icon icon-clear" aria-hidden="true"></span> </button>
<button type="submit" class="button theme-primary"> Search </button> </span>
</label>
</div>| Lines | Details |
|---|---|
| 1 | The It suppresses the browser’s native clear button on |
| 10 | The leading icon is optional. When present, the input’s |
| 17-24 | The The |
| 26-28 | The submit button is optional. Use |
Pre-populated Search (Search Results Page)
When linking to a search results page, pre-apply the has-value class to the .form-entry--search element and set the value attribute on the input to reflect the active query. This ensures the clear button is visible on page load — no JavaScript required for that initial state. It’s a small detail that makes a meaningful difference in usability.
The Search Results Template demonstrates this pattern in a full page layout, including a refined search field, filter sidebar, results list, and pagination.
Select Element
With the example in Figure 3, the same .form-entry container holds a <select> element.
<div class="form-entry">
<label class="form-entry__field">
<span class="form-entry__field__label"> Form Entry Label </span>
<span class="form-entry__field__select"> <select id="select-example" name="selectExample" aria-describedby="help-select-example"> <option value="">Select</option> <option value="Option One">Option One</option> <option value="Option Two">Option Two</option> <option value="Option Three">Option Three</option> <option value="Option Four">Option Four</option> <option value="Option Five">Option Five</option> </select> </span>
</label>
<small class="form-entry__help" id="help-select-example"> Form entry help text </small>
</div>| Lines | Details |
|---|---|
| 5-7 | The The label is associated implicitly because the |
| 9-21 | The It holds the actual The |
Text Area
Following the previous example’s pattern, Figure 4 shows the .form-entry parent selector with a <textarea> element.
<div class="form-entry">
<label class="form-entry__field">
<span class="form-entry__field__label"> Form Entry Label </span>
<span class="form-entry__field__input"> <textarea rows="8" name="textAreaExample" id="text-area-example" aria-describedby="help-textarea-example" ></textarea> </span>
</label>
<small class="form-entry__help" id="help-textarea-example"> Form entry help text </small>
</div>File Upload
Natura11y offers a simple file upload component, as shown in Figure 5 below.
<div class="form-entry">
<div class="form-entry__field">
<span class="form-entry__field__label"> Upload a Single File </span>
<div class="form-entry__field__input">
<label class="file-upload"> <span class="file-upload__drop"> <span class="file-upload__drop__text">Drag and Drop</span> </span>
<input class="file-upload__input" type="file" name="fileUploadExample" id="file-upload-example" accept="image/*">
<span class="button button--outline file-upload__button"> <span class="icon icon-upload" aria-hidden="true"></span> <span class="text">Browse for a File</span> </span>
</label>
</div>
</div>
<small class="form-entry__help" id="help-file-upload-example"> Form entry help text </small>
</div>Checkboxes
Checkbox (and radio) groups use semantic <fieldset> and <legend> tags. They stack vertically, with a healthy amount of padding. This helps to ensure an accessible target size.
Figure 6 provides the markup required to create a checkbox group.
<div class="form-entry">
<fieldset class="form-entry__field">
<legend class="form-entry__field__label"> Form Entry Label </legend>
<div class="form-entry__option"> <div class="form-entry__option__check"> <label> <input type="checkbox" name="checkboxGroupExample" id="check-option-one" value="optionOne"> <span class="option__label"> Option One </span> </label> </div> <div class="form-entry__option__check"> <label> <input type="checkbox" name="checkboxGroupExample" id="check-option-two" value="optionTwo"> <span class="option__label"> Option Two </span> </label> </div> <div class="form-entry__option__check"> <label> <input type="checkbox" name="checkboxGroupExample" id="check-option-three" value="optionThree"> <span class="option__label"> Option Three </span> </label> </div> </div>
</fieldset>
</div>| Lines | Details |
|---|---|
| 9 | The It holds the options markup for the |
| 10 | The It holds the actual The |
| 17-19 | The It holds the actual text label for the checkbox. |
Single Checkbox
For a single checkbox, do not use a <fieldset> and <legend>. Instead, provide an id on the .form-entry__field__label selector (Figure 7, line 5). Then associate it with aria-labelledby placed on the surrounding <label> tag (Figure 7, line 11).
<div class="form-entry">
<div class="form-entry__field">
<span class="form-entry__field__label" id="single-option-label"> Form Entry Label </span>
<div class="form-entry__option"> <div class="form-entry__option__check"> <label aria-labelledby="single-option-label"> <input type="checkbox" name="singleOption" id="single-option" value="option"> <span class="option__label"> Option </span> </label> </div> </div>
</div>
</div>Checkbox Switch
Checkboxes can transform into switches with just a couple of of changes to the markup.
First, change .form-entry__option__check to .form-entry__option__switch (Figure 8, line 10). Then, above the option label, add an empty <span> with the .switch__slider class (Figure 8, line 17).
<div class="form-entry">
<div class="form-entry__field">
<span class="form-entry__field__label" id="switch-option-label"> Form Entry Label </span>
<div class="form-entry__option"> <div class="form-entry__option__switch"> <label aria-labelledby="switch-option-label"> <input type="checkbox" name="singleOption" id="switch-option" value="option"> <span class="switch__slider"></span> <span class="option__label"> Receive Notifications </span> </label> </div> </div>
</div>
</div>Radios
Like checkboxes, radio groups use semantic <fieldset> and <legend> tags.
<div class="form-entry">
<fieldset class="form-entry__field">
<legend class="form-entry__field__label"> Form Entry Label </legend>
<div class="form-entry__option"> <div class="form-entry__option__radio"> <label> <input type="radio" name="radioGroupExample" id="radio-option-one" value="optionOne"> <span class="option__label"> Option One </span> </label> </div> <div class="form-entry__option__radio"> <label> <input type="radio" name="radioGroupExample" id="radio-option-two" value="optionTwo"> <span class="option__label"> Option Two </span> </label> </div> <div class="form-entry__option__radio"> <label> <input type="radio" name="radioGroupExample" id="radio-option-three" value="optionThree"> <span class="option__label"> Option Three </span> </label> </div> </div>
</fieldset>
</div>| Lines | Details |
|---|---|
| 9 | The It holds each |
| 10 | The It holds the actual The |
| 17-19 | The It holds the actual text label for the radio. |
Required Fields
Natura11y makes it easy to mark required fields. Add data-required="true" to the parent .form-entry element of the required field. On the same .form-entry element, include a custom error message using the data-error-message={x} attribute. Here x equals the message displayed to the user during the validation process.
<div class="form-entry" data-required="true" data-error-message="Custom error message"> <div class="form-entry__field"> ... </div></div>The two data attributes mentioned above are shown in Figure 10, lines 3 and 4. When data-required="true" is present on the .form-entry selector, Natura11y’s JavaScript adds the required attribute to the form entry’s child field automatically.
With the previous example, notice the red asterisk placed before the label. This too, is added automatically to required fields (via Natura11y’s CSS file). The asterisk has become the standard identifier for required fields.
Form Validation
Natura11y provides superficial client-side form validation. Include the novalidate attribute on the <form> tag.
<form data-validate novalidate>
<div class="form-entry" data-required="true" data-error-message="Username is required!">
<label class="form-entry__field form-entry__field--float"> <span class="form-entry__field__label"> Username </span> <span class="form-entry__field__input"> <input type="text" id="account-username" name="accountUsername"> </span> </label>
</div>
</form>Floating Labels
For short forms (such as a sign in form) floating labels would be fine to use. Add the .form-entry__field--float modifier class to the .form-entry__field selector (see Figure 12, line 5).
<div class="form-entry" data-required="true" data-error-message="Username is required!"> <label class="form-entry__field form-entry__field--float"> <span class="form-entry__field__label"> Username </span> <span class="form-entry__field__input"> <input type="text" id="account-username" name="accountUsername"> </span> </label> </div>














































