consolelog.tools

Accessible Form Builder

Build a form visually and get markup that’s genuinely accessible — not just an input next to a div. Every field is tied to its <label for>; radio and checkbox groups are wrapped in <fieldset><legend>; help text and an inline error region are wired with aria-describedby; required fields get aria-required; and a focusable error-summary sits at the top. It emits the right type/inputmode and an autocomplete token per field for WCAG 1.3.5, in HTML or JSX, and audits your form for the bugs people ship every day.

About this ToolHow it works, benefits & use cases

Most “form builders” hand you an input sitting next to some text and call it accessible. This one emits markup that a screen reader can actually use. Add fields visually — text, email, password, phone, URL, number, date, textarea, select, radio groups, checkbox groups, or a single checkbox — and the generator ties every control to a real <label for>, wraps radio and checkbox sets in <fieldset><legend>, wires help text and an inline error region through aria-describedby, marks required fields with both the native required attribute and aria-required, and drops a focusable error-summary region at the top of the form. It also sets the right type and inputmode for each field and emits an autocomplete token (WCAG 1.3.5, Identify Input Purpose) so browsers and password managers can fill it. A live preview renders the form as you build it, an audit panel flags the classic mistakes (missing labels, placeholder-as-label, known fields without autocomplete, choice groups without a fieldset, duplicate names), and you can copy the whole thing as HTML or JSX. The full configuration is captured in a shareable URL.

How to Use

  1. 1Give the form a title — it becomes the form’s <h2> heading and accessible name via aria-labelledby.
  2. 2Add fields and pick a type for each; the editor shows only the relevant options (e.g. an options list for selects and groups).
  3. 3Set the label and name, toggle Required, and add help text — it’s wired to the field with aria-describedby.
  4. 4For known fields, choose an autocomplete token (email, name, tel, postal-code…) so the form satisfies WCAG 1.3.5.
  5. 5Reorder fields with the up/down controls, watch the live preview update, and read the audit panel for issues.
  6. 6Toggle HTML or JSX, copy the generated markup, or share the URL.

Key Benefits

  • Every field gets a real <label for> tied by id — never a placeholder masquerading as a label
  • Radio and checkbox groups are wrapped in <fieldset><legend> so the group has one shared accessible name
  • Help text and a per-field role="alert" error region are wired with aria-describedby
  • Required fields get the native required attribute plus aria-required and a visible marker
  • A focusable error-summary region (role="alert", aria-live) sits at the top of the form
  • Correct type/inputmode and an autocomplete token per field for WCAG 1.3.5 (Identify Input Purpose)
  • Live audit catches missing labels, placeholder-as-label, missing autocomplete, group-without-fieldset, and duplicate names
  • Copy as HTML or JSX, with a shareable URL that captures the whole form

Common Use Cases

  • Scaffolding a contact, signup, or checkout form whose fields are correctly labelled and grouped
  • Adding autocomplete tokens to an existing form to pass WCAG 1.3.5 and enable browser autofill
  • Getting a fieldset/legend pattern for a set of radio buttons or checkboxes without writing it by hand
  • Producing a reference example of an inline error pattern (aria-describedby + role="alert") and error summary
  • Generating accessible React/JSX form markup with htmlFor and self-closing inputs

Accessible markup — HTML

<form id="contact-us" class="accessible-form" aria-labelledby="contact-us-title" novalidate>
  <h2 id="contact-us-title">Contact us</h2>
  <p class="form-intro">Send us a message and we’ll get back to you.</p>
  <div
    id="contact-us-errors"
    class="error-summary"
    role="alert"
    aria-live="polite"
    tabindex="-1"
    hidden
  >
    <h3>There’s a problem</h3>
    <ul></ul>
  </div>
  <div class="field">
    <label for="name" class="field-label">Full name <span class="req" aria-hidden="true">*</span></label>
    <input type="text" id="name" name="name" required aria-required="true" autocomplete="name" aria-describedby="name-error">
    <p class="field-error" id="name-error" role="alert" aria-live="polite"></p>
  </div>
  <div class="field">
    <label for="email" class="field-label">Email address <span class="req" aria-hidden="true">*</span></label>
    <input type="email" id="email" name="email" required aria-required="true" autocomplete="email" inputmode="email" aria-describedby="email-help email-error">
    <p class="field-help" id="email-help">We’ll only use this to reply.</p>
    <p class="field-error" id="email-error" role="alert" aria-live="polite"></p>
  </div>
  <div class="field">
    <label for="message" class="field-label">Message <span class="req" aria-hidden="true">*</span></label>
    <textarea id="message" name="message" rows="4" required aria-required="true" aria-describedby="message-error"></textarea>
    <p class="field-error" id="message-error" role="alert" aria-live="polite"></p>
  </div>
  <button type="submit" class="submit">Contact us</button>
</form>

Live preview

Contact us

Send us a message and we’ll get back to you.

We’ll only use this to reply.

No accessibility issues found

Form

Fields (3)

Field 1Text

Field 2Email

Field 3Textarea

An input next to text isn’t a labelled field

A screen reader only announces a field’s name when the <label> is programmatically tied to it — usually with for/id. A placeholder isn’t a label: it disappears the moment someone types, fails colour-contrast, and isn’t reliably read. This builder always emits a real label, wires help text and an inline error region through aria-describedby, and adds an autocomplete token so browsers and password managers can fill the field (WCAG 1.3.5).

What it gets right that hand-rolled forms miss

  • Groups — radio and checkbox sets are wrapped in <fieldset><legend> so the group has one shared name.
  • Required — both the native required attribute and aria-required, plus a visible marker.
  • Errors — a per-field role="alert" region tied by aria-describedby, and a focusable error-summary at the top of the form.
  • Input purpose — the right type/inputmode and an autocomplete token per field.

Was this tool helpful?

Share Your Experience

Help others discover this tool!

Related tools