Skip to content
Español

Navigate

Type to search. Press Escape to close.

    Components · css

    Form

    Native controls styled with tokens. Every control needs a visible <label>; help and error text are linked with aria-describedby. No JavaScript, no custom widgets.

    CSS: included in ivolt.css; standalone css/components/form.css.

    Fields, labels and help textfixtures/form/basic.htmlOpen alone — Fields, labels and help text
    <form class="iv-stack" style="max-width: 28rem" action="#" method="get" onsubmit="return false" aria-describedby="demo-form-note">
      <p class="iv-u-text-sm iv-u-text-muted iv-u-m-0" id="demo-form-note">Demo form: nothing is submitted.</p>
      <div class="iv-field">
        <label class="iv-label" for="f-name">Full name <span class="iv-label__required" aria-hidden="true">*</span></label>
        <input class="iv-input" id="f-name" name="name" type="text" required autocomplete="name" aria-describedby="f-name-help">
        <p class="iv-field__help iv-u-m-0" id="f-name-help">As it should appear on the invoice.</p>
      </div>
      <div class="iv-field">
        <label class="iv-label" for="f-plan">Plan</label>
        <select class="iv-select" id="f-plan" name="plan">
          <option>Starter</option><option>Team</option><option>Enterprise</option>
        </select>
      </div>
      <div class="iv-field">
        <label class="iv-label" for="f-notes">Notes</label>
        <textarea class="iv-input" id="f-notes" name="notes" rows="3"></textarea>
      </div>
      <fieldset class="iv-fieldset">
        <legend class="iv-fieldset__legend">Notifications</legend>
        <div class="iv-checks">
          <label class="iv-check"><input type="checkbox" name="n" value="product" checked> Product updates</label>
          <label class="iv-check"><input type="checkbox" name="n" value="security"> Security alerts</label>
        </div>
      </fieldset>
      <fieldset class="iv-fieldset">
        <legend class="iv-fieldset__legend">Billing</legend>
        <div class="iv-checks iv-checks--inline">
          <label class="iv-check"><input type="radio" name="billing" value="monthly" checked> Monthly</label>
          <label class="iv-check"><input type="radio" name="billing" value="yearly"> Yearly</label>
        </div>
      </fieldset>
      <div class="iv-cluster">
        <button class="iv-button iv-button--primary" type="submit">Save (demo)</button>
        <button class="iv-button iv-button--ghost" type="reset">Reset</button>
      </div>
    </form>

    Error and disabled

    Mark invalid fields with aria-invalid="true" and point aria-describedby at the iv-field__error element. Disabled controls use the native attribute.

    Error and disabledfixtures/form/error.htmlOpen alone — Error and disabled
    <div class="iv-stack" style="max-width: 28rem">
      <div class="iv-field">
        <label class="iv-label" for="f-email">Work email</label>
        <input class="iv-input" id="f-email" type="email" value="dave@" aria-invalid="true" aria-describedby="f-email-error" autocomplete="email">
        <p class="iv-field__error iv-u-m-0" id="f-email-error">Enter a complete email address, like [email protected].</p>
      </div>
      <div class="iv-field">
        <label class="iv-label" for="f-locked">Plan</label>
        <input class="iv-input" id="f-locked" type="text" value="Team (locked)" disabled>
      </div>
    </div>

    Floating labels and input groups

    iv-field--float keeps the label inside the control until it has focus or a value (give the control placeholder=" "). iv-input-group joins prefixes, suffixes and buttons to a control.

    Floating labels and input groupsfixtures/form/float.htmlOpen alone — Floating labels and input groups
    <div class="iv-stack" style="max-width: 30rem">
      <p class="iv-u-text-sm iv-u-text-muted iv-u-m-0">Demo fields with made-up values. Nothing is submitted; the CSS here needs no JavaScript.</p>
    
      <div class="iv-field iv-field--float">
        <input class="iv-input" id="fl-email" name="email" type="email" placeholder=" " autocomplete="email">
        <label class="iv-label" for="fl-email">Work email</label>
      </div>
    
      <div class="iv-field iv-field--float">
        <input class="iv-input" id="fl-company" name="company" type="text" placeholder=" " value="iNTERVOLUTIONS" autocomplete="organization">
        <label class="iv-label" for="fl-company">Company</label>
      </div>
    
      <div class="iv-field iv-field--float">
        <select class="iv-select" id="fl-plan" name="plan">
          <option value="">Choose a plan</option>
          <option value="starter">Starter</option>
          <option value="team">Team</option>
          <option value="enterprise">Enterprise</option>
        </select>
        <label class="iv-label" for="fl-plan">Plan</label>
      </div>
    
      <div class="iv-field iv-field--float">
        <textarea class="iv-textarea" id="fl-notes" name="notes" placeholder=" "></textarea>
        <label class="iv-label" for="fl-notes">Notes for the team</label>
      </div>
    
      <div class="iv-field">
        <label class="iv-label" for="fg-site">Site address</label>
        <div class="iv-input-group">
          <span class="iv-input-group__addon">https://</span>
          <input class="iv-input" id="fg-site" name="site" type="text" value="intervolutions" autocomplete="off">
          <span class="iv-input-group__addon">.com</span>
        </div>
      </div>
    
      <div class="iv-field">
        <label class="iv-label" for="fg-key">API key</label>
        <div class="iv-input-group">
          <input class="iv-input" id="fg-key" name="key" type="text" value="iv_demo_8f2c" readonly autocomplete="off">
          <button class="iv-input-group__addon iv-input-group__addon--button" type="button">Copy</button>
        </div>
        <p class="iv-field__help iv-u-m-0">Made-up key. The button is a demo: it copies nothing.</p>
      </div>
    </div>

    Switch, range, file and sizes

    A checkbox becomes a switch, a range input gets a filled track, a file input becomes a drop zone that keeps the real input accessible, textareas grow with their content where the browser supports it, and inputs come in three sizes like buttons.

    Switch, range, file and sizesfixtures/form/controls.htmlOpen alone — Switch, range, file and sizes
    <div class="iv-stack" style="max-width: 32rem">
      <p class="iv-u-text-sm iv-u-text-muted iv-u-m-0">Demo controls with made-up values. Nothing is submitted; none of this needs JavaScript.</p>
    
      <fieldset class="iv-fieldset">
        <legend class="iv-fieldset__legend">Notifications</legend>
        <div class="iv-checks">
          <label class="iv-switch">
            <input type="checkbox" name="deploys" role="switch" checked>
            <span class="iv-switch__track"><span class="iv-switch__thumb"></span></span>
            <span>Email me about deploys</span>
          </label>
          <label class="iv-switch">
            <input type="checkbox" name="digest" role="switch">
            <span class="iv-switch__track"><span class="iv-switch__thumb"></span></span>
            <span>Weekly digest</span>
          </label>
          <label class="iv-switch">
            <input type="checkbox" name="sms" role="switch" disabled>
            <span class="iv-switch__track"><span class="iv-switch__thumb"></span></span>
            <span>SMS alerts (not available in this demo)</span>
          </label>
        </div>
      </fieldset>
    
      <div class="iv-field">
        <label class="iv-label" for="ct-budget">Monthly budget: 620 €</label>
        <input class="iv-range" id="ct-budget" name="budget" type="range" min="0" max="1000" step="20" value="620" style="--iv-range-value: 62%">
        <p class="iv-field__help iv-u-m-0">The filled part comes from <code>--iv-range-value</code>, set here in the markup. Moving the slider does not update it without JavaScript.</p>
      </div>
    
      <div class="iv-field">
        <label class="iv-label" for="ct-file">Brand assets</label>
        <label class="iv-file">
          <input type="file" id="ct-file" name="assets" multiple accept="image/*">
          <span class="iv-file__zone">
            <span>Choose files or drop them here</span>
            <span class="iv-u-text-sm iv-u-text-muted">PNG or SVG, up to 5 MB each. Demo only: nothing is uploaded.</span>
          </span>
        </label>
      </div>
    
      <div class="iv-field">
        <label class="iv-label" for="ct-notes">Release notes</label>
        <textarea class="iv-textarea" id="ct-notes" name="notes" placeholder="What changed?">The box grows with the text where the browser supports field-sizing, and stays resizable everywhere else.</textarea>
      </div>
    
      <div class="iv-field">
        <label class="iv-label" for="ct-small">Coupon (small)</label>
        <input class="iv-input iv-input--sm" id="ct-small" name="coupon" type="text" value="IVOLT-25" autocomplete="off">
      </div>
    
      <div class="iv-field">
        <label class="iv-label" for="ct-medium">Project (default)</label>
        <input class="iv-input" id="ct-medium" name="project" type="text" value="Spectacular forms" autocomplete="off">
      </div>
    
      <div class="iv-field">
        <label class="iv-label" for="ct-large">Headline (large)</label>
        <input class="iv-input iv-input--lg" id="ct-large" name="headline" type="text" value="Forms with character" autocomplete="off">
      </div>
    
      <div class="iv-cluster">
        <button class="iv-button iv-button--primary iv-button--lg" type="button">Large button</button>
        <button class="iv-button" type="button">Default</button>
        <button class="iv-button iv-button--sm" type="button">Small</button>
      </div>
    </div>
    .iv-root {
      --iv-range-value: 62%;
    }

    Classes

    ClassElement
    iv-fieldWrapper: label, control, help/error stacked.
    iv-label, iv-label__required<label> and the required marker (keep required on the control).
    iv-input<input> (text-like types) and <textarea>.
    iv-selectNative <select>.
    iv-check, iv-checks, iv-checks--inlineLabel wrapping a checkbox or radio; vertical or inline groups.
    iv-fieldset, iv-fieldset__legendGrouping with a legend.
    iv-field__help, iv-field__errorHelp and error text.

    Common mistakes

    • Placeholder used as the only label.
    • Error text not referenced by aria-describedby.
    • Demo forms that post to a backend that does not exist: say it is a demo, as the examples above do.

    Class index

    Parts and modifiers of this family that the examples above do not show. The full list per stylesheet lives in the reference.

    ClassWhat it does
    iv-form__summary-titleHeading of the error summary; its text is the summaryTitle option.
    iv-form__summary-listList of links to the invalid fields.
    iv-input-group__addonPrefix or suffix glued to an input: a currency, a unit, a domain.
    iv-input-group__addon--buttonAdd-on that is a real button and keeps its focus ring.