Form • Natura11y
Four whale in body of water under cloudy sky

Photo by 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.

Form entry help text

        <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>
    
Figure 1
Line #Details
1

The .form-entry parent selector is required.

It contains each entries elements, including help text and feedback messages.

When more than one .form-entry selector is present, spacing between them occurs automatically.

3-18

The .form-entry__field child selector is required.

It holds the field's label and input elements.

The .form-entry__field__label grandchild selector is required.

It holds the actual label text, and required indicator (when present).

The .form-entry__field__input grandchild selector is required.

It holds the field's actual input elements.

When using help text, aria-describedby is present on the input tag for assistive technology. It equals the help text's id attribute (below).

20-22

The .form-entry__help child selector is not required.

Its id equals its associated aria-describedby attribute.


Select Element

With the example in Figure 2, 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>
    
Figure 2
Line #Details
5-7

The .form-entry__field__label grandchild selector is required.

The for attribute equals its associated <select> tags id.

9-21

The .form-entry__field__select grandchild selector is required.

It holds the actual <select> tag.

The <select> tag's id equals its associated for attribute.


Text Area

Following the previous example's pattern, Figure 3 shows the .form-entry parent selector with a <textarea> element.

Form entry help text

        <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="textInputExample"
                        id="text-input-example"
                        aria-describedby="help-textarea-example"
                    ></textarea>
                </span> 

            </label> 

            <small class="form-entry__help" id="help-textarea-example">
                Form entry help text
            </small> 

        </div>
    
Figure 3
Line #Details
5-7

The .form-entry__field__label grandchild selector is required.

9-16

The .form-entry__field__input grandchild selector is required.

It holds the actual <textarea> tag.


File Upload

Natura11y offers a simple file upload component, as shown in Figure 4 below.

Form entry help text

        <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-uploadsple" accept="image/*">

                        <span class="button button--outline button--has-icon file-upload__button">
                            <span class="icon icon-upload"></span>
                            <span class="button__text">Browse for a File</span>
                        </span>

                    </label>

                </div>

            </div>

            <small class="form-entry__help" id="help-file-uploadsple">
                Form entry help text
            </small>

        </div>
    
Figure 4

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 5 provides the markup required to create a checkbox group.

Label

        <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>
    
Figure 5
Line #Details
9

The .form-entry__option child selector is required.

It holds the options markup for the <fieldset>.

11

The .form-entry__option__check grandchild selector is required.

It holds the actual <label> and <input> tags.

The .form-entry__option__check selector is repeatable for multiple options.

17-22

The .file-uploadsut child selector is required.

It includes the type="file" attribute.

18-20

The .option__label child selector is required.

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 6, line 5). Then associate it with aria-labeledby placed on the surrounding <label> tag (Figure 6, lines 13).


        <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-labeledby="single-option-label">
                            <input
                                type="checkbox"
                                name="singleOption"
                                id="single-option"
                                value="option">
                                <span class="option__label">
                                    Option
                                </span>
                        </label> 

                    </div> 

                </div> 

            </div> 

        </div> 

    
Figure 6

Checkbox Switch

Checkboxes can transform into switches with just a couple of of changes to the markup.

First, change the .form-entry__option__check to .form-entry__option__switch (Figure 7, line 11). Then, above the switch label, add an empty <span> with a .switch__slider class (Figure 7, line 19).


        <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-labeledby="switch-option-label">
                            <input
                                type="checkbox"
                                name="singleOption"
                                id="switch-option"
                                value="option">
                                <span class="switch__slider"></span>
                                <span class="option__label">
                                    Recieve Notifications
                                </span>
                        </label> 

                    </div> 

                </div> 

            </div> 

        </div>
    
Figure 7

Radios

Like checkboxes, radio groups use semantic <fieldset> and <legend> tags.

Label

        <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> 

    
Figure 8
Line #Details
9

The .form-entry__option child selector is required.

It holds each .form-entry__option__radio grandchild selector.

11

The .form-entry__option__radio grandchild selector is required.

It holds the actual <label> and <input> tags.

The .form-entry__option__radio selector is repeatable for multiple options.

17-22

The .file-uploadsut child selector is required.

It includes the type="file" attribute.

18-20

The .option__label child selector is required.

It holds the actual text label for the checkbox.


Required Fields

Natura11y makes it easy to mark required fields. Add data-required="true" to the parent .form-group element of the required field. On the same .form-group 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.

Form entry help text

        <div
            class="form-entry"
            data-required="true"
            data-error-message="Custom error message"> 

            <div class="form-entry__field">
                ...
            </div> 

        </div>
    
Figure 9

The two data attributes mentioned above are shown in Figure 9, lines 3 and 4. When present on the .form group selector, Naturally's Javascript adds the necessary required and data-required attributes to the form entry's child &lt;input&gt; element 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.

Enter your first and last name
Example: janeDoe@email.com
Enter a valid phone number
Contact Preference

        <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>
    
Figure 10

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 11, line 6).



        <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>
    
Figure 11