Site icon Ampersand Tutorials

Materialize CSS Forms: Inputs, Select and Validation

Quick answer: A Materialize form field is an input wrapped in a div.input-field with a label after it — the label animates into the field on focus. Add class="validate" to trigger inline validation with the invalid and valid helper classes. select and textarea work inside the same wrapper but are not initialized automatically on 1.0.0 — you must call M.FormSelect.init() for selects and M.CharacterCounter.init() for counters. The single most common mistake is forgetting the input-field wrapper, which removes all styling and animation.

A complete form in one block

Text input, select, textarea and a submit button — the shapes used in almost every real form, on Materialize 1.0.0.

<form class="col s12">
  <div class="row">
    <!-- Text input -->
    <div class="input-field col s6">
      <input id="email" type="email" class="validate" required>
      <label for="email">Email</label>
    </div>

    <!-- Select -->
    <div class="input-field col s6">
      <select id="plan">
        <option value="" disabled selected>Choose a plan</option>
        <option value="basic">Basic</option>
        <option value="pro">Pro</option>
      </select>
      <label>Plan</label>
    </div>

    <!-- Textarea with counter -->
    <div class="input-field col s12">
      <textarea id="bio" class="materialize-textarea" data-length="120"></textarea>
      <label for="bio">Short bio</label>
    </div>

    <button class="btn waves-effect waves-light" type="submit">Save</button>
  </div>
</form>
document.addEventListener('DOMContentLoaded', function () {
  M.AutoInit(); // initializes select, textarea counter and more
});

If you prefer explicit control, swap M.AutoInit() for M.FormSelect.init(document.querySelectorAll('select')) and M.CharacterCounter.init(document.querySelectorAll('[data-length]')). Selects must be initialized or they render as the browser’s default control with none of the Materialize styling.

Validation classes and options

PieceWhereEffect
validateon the inputAdds built-in validation for email, url, number and required
helper-textspan under the labelMessage shown when validation runs
invalidadded automaticallyRed state applied by Materialize on failure
validadded automaticallyGreen state applied on success
data-error / data-successon the inputCustom text for the helper message
materialize-textareaon the textareaEnables auto-growing height and counter
<div class="input-field col s12">
  <input id="email" type="email" class="validate"
         data-error="Enter a valid email" data-success="Looks good">
  <label for="email">Email</label>
  <span class="helper-text">We never share your address.</span>
</div>

This is HTML5 validation surfaced through Materialize’s styling — it catches format mistakes in the browser before any server round-trip. For a ready-made login and signup layout built from these pieces, see the login and register forms post.

Switches, checkboxes and radios

These three share one pattern: a real input, a styled span or label, and no JavaScript. Put switch on the label to turn a checkbox into a toggle.

<!-- Switch -->
<div class="switch">
  <label>
    Off
    <input type="checkbox" checked>
    <span class="lever"></span>
    On
  </label>
</div>

<!-- Checkbox -->
<p>
  <label>
    <input type="checkbox" class="filled-in" checked />
    <span>Subscribe</span>
  </label>
</p>

Styling the submit button, including icons and color variants, is covered in the button guide, and the shade names for colored states come from the colors reference.

Two more field types round out the set. A file input uses the same input-field wrapper with type="file" and renders a styled choose-file button. Date and time pickers are separate components: add a class of datepicker or timepicker to the input and initialize them with M.Datepicker.init() and M.Timepicker.init(), both of which M.AutoInit() also covers. Because a picker binds to one specific input, that is the one place where explicit per-element initialization is usually clearer than a global auto-init.

When the form looks wrong: four checks

All of these assume a clean 1.0.0 setup; if your page loads 0.97.x JavaScript, the component APIs differ entirely. The Materialize CSS tutorial covers version pinning and the CDN imports to match.

Building a checkout or onboarding form and want it reviewed field by field? Ampersand Academy teaches front-end form work one-to-one, using your own project as the curriculum.

Frequently asked questions

Why does my Materialize input look unstyled?

The input is missing its wrapper. Materialize draws the underline and animates the label only when the input sits inside a div with class input-field, with the label placed after the input.

How do I initialize a Materialize select?

Call M.FormSelect.init(document.querySelectorAll(‘select’)) before use, or run M.AutoInit() to initialize every component on the page at once. Uninitialized selects keep the browser default look.

How does validation work in Materialize forms?

Add class validate to the input. Materialize then applies invalid or valid states using the browser validation rules for the input type, and shows any helper-text message you provide.

How do I add a character counter to a textarea?

Give the textarea the materialize-textarea class plus a data-length attribute, then initialize it with M.CharacterCounter.init(). The counter appears beneath the field automatically.

Do Materialize forms need jQuery?

No. Materialize 1.0.0 uses vanilla JavaScript initialization such as M.FormSelect.init(). The jQuery-based form code from older tutorials was removed in 1.0.0.

Exit mobile version