A wrapper component for forms

MathematicsGeographyPhysicsHistoryCancelCreate course
  <sl-form-field hint="Please enter a descriptive name for the course." label="Course name">
    <sl-text-field name="courseName" required></sl-text-field>

  <sl-form-field label="Subjects">
    <sl-checkbox-group name="subjects">

  <sl-button-bar align="end">
    <sl-button fill="outline">Cancel</sl-button>
    <sl-button variant="primary">Create course</sl-button>

When to use

The form component should be used whenever you have a form that needs to be filled out by a user. The form component is a container for form fields.

When not to use

Do not use the form component if you only have one form field. Usually this indicates a specific usage of a form control, and that it should be used on its own.

Added to prevent rendering additional paragraph around, which causes navigation problems

The <sl-form> component fulfills four functions:

  1. It provides a default layout for form fields.
  2. It manages the way required/optional fields should be marked.
  3. It provides a way to validate all form fields at once.
  4. It allows you to query the state of the form.


By default, the form component has a vertical flexbox layout. This means that form fields will stack on top of each other. If you want to change this, you can customize the CSS to use a grid layout instead.

/* Define a two column grid layout. */
sl-form {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr 1fr;

/* Position the form fields in specific columns here... */

/* Make the button bar span both columns. */
sl-button-bar {
  grid-column: 1 / 3;

Required or optional

The form itself manages a mark state. This determines how required or optional labels should be shown. If the required fields outnumber the optional fields, only the optional fields will be marked. If it is the other way around, then only the required fields will be marked.

This behavior happens automatically, and the developer does not need to do anything to make it work.


The form component provides a way to validate all form fields at once. The reportValidity() method can be used to trigger validation on all form fields. This method returns a boolean indicating whether the form is valid or not.

submitButton.addEventListener('click', event => {
  const form ='sl-form');

  if (form?.reportValidity()) {
    // Submit the form


You can query the state of the entire form by simply getting the valid property on the <sl-form>. This will return false if any form field within the form is not valid.


Form component is meant as a wrapper around form fields.


controls-Array<HTMLElement & FormControl>[]The controls in the form; not necessarily the same amount as the fields.
dirty-booleanA form is marked dirty when the user has modified a form control.
disableddisabledboolean | undefinedWill disable the entire form when true.
fields-FormField[][]The fields in the form.
invalid-booleanWhether the form is invalid.
pristine-booleanA form is marked pristine as long as the user hasn't modified anything in the form.
showValidity-booleanIndicates whether to show validity state.
touched-booleanA form is marked touched once the user has triggered a blur event on a form control.
untouched-booleanA form is marked untouched as long as the user hasn't trigger a blur event on a form control.
valid-booleanWhether the form is valid.
value-TThe aggregated value of all form controls.


reportValiditybooleanCalls `reportValidity()` on all form controls.

Keyboard interactions

Here's an overview of the common keyboard interactions associated with a form:

TabWhen focus is outside the form, moves focus to the first form field.
Interactive example