form

Associates a form control with a form element by ID, even when the control is outside the form's DOM tree. Enables complex layouts without nesting constraints.

Overview

The form attribute associates a form control with a <form> element by referencing the form's id. The control does not need to be a descendant of the form — it can be anywhere in the document. When the form is submitted, all associated controls (both nested and remote) are included in the form data.

This solves a real layout problem: sometimes the visual design requires form controls to be placed outside the form's DOM tree. Sticky footers, sidebar filters, dialog-based settings, and split-panel editors all benefit from this attribute.

Applies to: <input>, <select>, <textarea>, <button>, <output>, <fieldset>

Values

AttributeValueEffect
form="form-id"The id of a <form>Associates the control with that form
(no form attribute)Control belongs to its nearest ancestor <form>

Basic Association

Place a control anywhere on the page and point it at a form with the form attribute. The value must exactly match the form's id.

<form id="checkout" action="/checkout" method="post" class="stacked"> <label for="item">Item</label> <input type="text" id="item" name="item" /> <label for="qty">Quantity</label> <input type="number" id="qty" name="qty" min="1" value="1" /> <button type="submit">Purchase</button> </form> <!-- This input is outside the form's DOM tree but belongs to it --> <label for="promo">Promo Code</label> <input type="text" id="promo" name="promo_code" form="checkout" />

Sticky Footer Buttons

A common layout: the form is in the content area and the submit/action buttons are in a sticky footer outside the form. The form attribute on the buttons connects them to the form.

<!-- Form in the main content area --> <form id="editor" action="/save" method="post" class="stacked"> <label for="title">Title</label> <input type="text" id="title" name="title" required /> <label for="content">Content</label> <textarea id="content" name="content" rows="10" required></textarea> </form> <!-- Sticky footer is outside the form --> <footer style="position: sticky; bottom: 0; background: var(--color-surface-raised); padding: 1rem;"> <button type="submit" form="editor">Save</button> <button type="submit" form="editor" formaction="/preview" formmethod="get"> Preview </button> </footer>

The formaction and formmethod attributes work on remote buttons just as they do on nested buttons. See novalidate for the formnovalidate pattern.

Multiple Forms on One Page

When a page has multiple forms, the form attribute lets you assign shared controls to the correct form without nesting them.

<!-- Two forms on the same page --> <form id="search-form" action="/search" method="get"> <label for="q">Search</label> <input type="search" id="q" name="q" /> <button type="submit">Search</button> </form> <form id="filter-form" action="/search" method="get"> <fieldset> <legend>Filters</legend> <label><input type="checkbox" name="type" value="article" /> Articles</label> <label><input type="checkbox" name="type" value="video" /> Videos</label> </fieldset> <button type="submit">Apply Filters</button> </form> <!-- This field submits with the search form, not the filter form --> <label for="sort">Sort by</label> <select id="sort" name="sort" form="search-form"> <option value="relevance">Relevance</option> <option value="date">Date</option> <option value="title">Title</option> </select>

Supported Elements

The form attribute works on every form-associated element.

<!-- All these element types support the form attribute --> <form id="profile" action="/profile" method="post"> <button type="submit">Save Profile</button> </form> <!-- input --> <input type="text" name="display_name" form="profile" /> <!-- select --> <select name="timezone" form="profile"> <option value="UTC">UTC</option> <option value="EST">Eastern</option> <option value="PST">Pacific</option> </select> <!-- textarea --> <textarea name="bio" rows="3" form="profile"></textarea> <!-- button --> <button type="reset" form="profile">Reset</button> <!-- output --> <output name="char_count" form="profile">0</output> <!-- fieldset (associates all its children) --> <fieldset form="profile"> <legend>Notifications</legend> <label><input type="checkbox" name="notify_email" /> Email</label> <label><input type="checkbox" name="notify_sms" /> SMS</label> </fieldset>

Dialog Pattern

When advanced settings live inside a <dialog>, the fields are in a separate DOM subtree. The form attribute lets them contribute to the main form's submission data.

<form id="settings" action="/settings" method="post" class="stacked"> <label for="name">Display Name</label> <input type="text" id="name" name="name" /> <button type="submit">Save</button> </form> <!-- Dialog is a separate DOM subtree, but controls belong to the form --> <dialog id="advanced-dialog"> <h2>Advanced Settings</h2> <label for="api-key">API Key</label> <input type="text" id="api-key" name="api_key" form="settings" /> <label for="webhook">Webhook URL</label> <input type="url" id="webhook" name="webhook_url" form="settings" /> <button onclick="this.closest('dialog').close()">Done</button> </dialog> <button onclick="document.querySelector('#advanced-dialog').showModal()"> Advanced Settings </button>

JavaScript API

The .form property on form controls returns the associated <form> element, whether the association is via nesting or the form attribute. FormData automatically includes remote controls.

// Check which form an element belongs to const input = document.querySelector('#promo'); console.log(input.form); // → <form id="checkout"> console.log(input.form.id); // → "checkout" // FormData includes elements associated via the form attribute const form = document.querySelector('#checkout'); const data = new FormData(form); console.log(data.get('promo_code')); // → value of the #promo input

Accessibility

  • Screen readers associate controls with their form regardless of DOM position when the form attribute is used. The accessibility tree respects the attribute.
  • Tab order follows DOM order, not form association. If a remote control is far from the form in the DOM, it may be reached much earlier or later during keyboard navigation. Place associated controls near the form when possible.
  • Ensure remote controls are visually connected to their form through layout and proximity. Users should understand which form a control belongs to without inspecting the HTML.

Limitations

  • The form attribute value must be an id, not a selector. It must exactly match the id attribute of a <form> element on the page.
  • A control can only be associated with one form. If it has a form attribute and is also nested inside a different <form>, the form attribute wins.
  • Constraint validation applies to remote controls just like nested ones. A remote required field will block submission if empty.
  • The form attribute does not work across documents. The form and the control must be in the same document (not in different iframes).
  • Some older JavaScript form libraries may not account for remote controls. If you use form.elements or new FormData(form), remote controls are included — but manual DOM traversal (e.g., form.querySelectorAll('input')) will miss them.

See Also