Custom Input Component

A custom input component replaces a native form control with your own. When it is worth it, and how to keep it accessible, usable and form-aware.

What is a custom input component?

A custom input component is a form control you build yourself instead of using the browser's native one: a date range picker, a tag field, a combobox, a masked phone field or a styled slider. It should look and behave like an input from the user's side, and take part in the form like one from the code's side: it has a name, a value, a label, validation and keyboard support. If any of those is missing, it is a widget that looks like an input, not an input.

Native first, custom when you must

MDN lists many native input types: text, email, url, tel, number, range, date, time, datetime-local, month, week, color and file, plus the inputmode, autocomplete, required, pattern and min/max attributes. They bring keyboard behavior, mobile keyboards, autofill and validation for free. The W3C ARIA Authoring Practices Guide makes the cost of the alternative explicit: unlike HTML inputs, ARIA roles do not give browsers keyboard behavior or styling, so you must build all of it, and "no ARIA is better than bad ARIA". Build a custom component only when no native control does the job, for example a searchable combobox or a multi-value field.

How to build one that works

  • Start from a native element where you can. A styled wrapper around a real <input> or <select> keeps most behavior intact.
  • Follow the APG pattern for your widget (combobox, listbox, slider, and so on). It defines the roles, states and keys users expect. A role is a promise: if you set role="combobox", you must deliver what that role implies.
  • Give it a visible label tied to the control, and do not use placeholder text as the label. MDN notes it disappears when the user types and is not reliably announced.
  • Make it keyboard operable with a sensible focus order, a visible focus style and the keys the pattern calls for. Test with the mouse unplugged.
  • Expose state with ARIA where native semantics are missing: name, role, expanded, invalid, required.
  • Join the form. A web component can become form-associated: set static formAssociated = true, call attachInternals(), then use setFormValue() for the submitted value and setValidity() for constraint validation. The same ElementInternals object can set default role and ARIA properties. MDN marks it as widely available across browsers since March 2023. Without it, your component's value will not be submitted with the form.
  • Keep the native fallback. If JavaScript fails, a plain input should still work.

Common mistakes

  • A <div> with a click handler and no role, label or keyboard support.
  • Reimplementing a native control (a date field, a file picker) with worse accessibility than the browser's own.
  • Showing validation only through color, or with an error message screen readers never hear.
  • Breaking paste, autofill, undo or text selection with an aggressive input mask.
  • Testing with one browser and no assistive technology. The APG itself says to test each browser and assistive technology combination before production.

Custom inputs, standards and monitoring

Custom inputs touch the Web Content Accessibility Guidelines (WCAG) directly: labels, keyboard access and error identification are WCAG territory, and they shape the wider user experience. A rich text editor is a common example, and one of the hardest to make accessible. Heavy widget code also costs speed. LoadFocus page speed monitoring runs scheduled Lighthouse audits, including the Accessibility category and Core Web Vitals, so a slow or flagged form shows up after a release. Automated checks catch only part of the issues, so keep manual keyboard and screen reader testing.

FAQ: custom input components

When should I use a custom input instead of a native one?

When no native control fits, such as a searchable combobox, a tag input or a date range. For plain text, numbers, dates, colors and files, a native input is more accessible and cheaper to maintain.

Do custom inputs submit with a form?

Only if they are wired to it. A form-associated custom element using ElementInternals can set a submission value and validity. Otherwise, keep a hidden native input in sync or send the value yourself.

Do I always need ARIA?

No. A control built on a real input needs little or none. ARIA is for filling semantic gaps in custom widgets, and wrong ARIA is worse than none.

How do I test a custom input for accessibility?

Use it with the keyboard only, check the label and state are announced by a screen reader, and run an automated audit. Then test on the browsers and assistive technologies your users actually use.

How fast is your website?

Elevate its speed and SEO seamlessly with our Free Speed Test.

Free Website Speed Test

Analyze your website's load speed and improve its performance with our free page speed checker.