Skip to main content

HTML elements

Forms

Controls and the structure around them. Buttons, fields, selects, labels and fieldsets are styled with no class, and so are output, meter and progress. A .luz-* class adds a role, a size or the parts a bare element cannot say.

Runs an action when clicked or pressed. Always set type: inside a form it submits by default.

HTML
<button type="submit">Save</button>
<button type="button">Cancel</button>
<button type="button" disabled>Disabled</button>

Styled by elements/forms.css, with no class. A button with no type, or with type="submit", is the primary action; type="button" and type="reset" are the secondary one. Add .luz-btn to an a that must look like a button, and for the danger and ghost roles and the sizes.

Suggestions offered while the user types in an input. The user can still type anything else.

HTML
<label for="d-datalist">Browser</label>
<input id="d-datalist" list="d-browsers" placeholder="Start typing">
<datalist id="d-browsers">
  <option value="Chrome"></option>
  <option value="Firefox"></option>
  <option value="Safari"></option>
</datalist>

LUZ adds no style to the datalist: the browser draws the suggestions. The field takes the look of a bare text field, from elements/forms.css.

Wraps related controls, such as the parts of an address or a set of radio buttons. A legend as its first child names the group.

Plan
HTML
<fieldset>
  <legend>Plan</legend>
  <label><input type="radio" name="d-plan" checked> Free</label>
  <label><input type="radio" name="d-plan"> Team</label>
</fieldset>

Styled by elements/forms.css, with no class: a box with the legend on its edge. A label that holds a radio button or a checkbox puts it beside the text. The component classes .luz-check-group and .luz-check-item draw the box and the dot themselves.

Wraps controls whose values are sent together. The browser checks required fields and formats before it sends anything.

HTML
<form action="#">
  <label for="d-form-name">Name</label>
  <input id="d-form-name" name="name" required>
  <button type="submit">Send</button>
</form>

A form has no style of its own: it is structure. The controls inside it carry the look, and the space between them comes from their own rules. Leave Name empty and press Send: the browser stops the submit and says why.

A field the user fills in. The type attribute decides which one: text, email, number, range, color, date and more.

HTML
<label for="d-input">Email</label>
<input id="d-input" type="email" placeholder="jane@example.com" autocomplete="off">

Styled by elements/forms.css, with no class: text, email, number, date and the other text types fill their container. Add .luz-input to a color or file input, and .luz-field to a label with a help text and an error.

The visible name of a control. Connect them with for and id: screen readers announce it, and clicking it focuses or toggles the control.

HTML
<label for="d-label">Project name</label>
<input id="d-label" type="text">

Styled by elements/forms.css, with no class: a block above its field, or beside the checkbox or radio button it holds.

The name of a fieldset, announced when the user enters the group. It is the first child of the fieldset.

Notifications
HTML
<fieldset>
  <legend>Notifications</legend>
  <label><input type="checkbox" checked> Email</label>
  <label><input type="checkbox"> Push</label>
</fieldset>

Styled by elements/forms.css, with no class: small uppercase text in the secondary color, on the edge of the fieldset.

Shows a measurement on a known scale, such as storage used or a password score. To show how far a task has got, use progress.

6 of 10 GB
HTML
<label for="d-meter">Storage used, 6 of 10 GB</label>
<meter id="d-meter" min="0" max="10" low="3" high="8" optimum="2" value="6">6 of 10 GB</meter>

Styled by elements/forms.css, with no class: the size of the bar. The browser draws its colors; .luz-meter draws them in the brand color.

A labelled set of options inside a select, such as cities grouped by country. The label itself cannot be chosen.

HTML
<label for="d-optgroup">Role</label>
<select id="d-optgroup">
  <optgroup label="Product">
    <option>Designer</option>
    <option>Product manager</option>
  </optgroup>
  <optgroup label="Engineering">
    <option>Developer</option>
  </optgroup>
</select>

LUZ adds no style to the optgroup: the browser draws the list. The closed box is the style of the select.

One choice in a select, or one suggestion in a datalist.

HTML
<label for="d-option">Role</label>
<select id="d-option">
  <option value="">Select a role</option>
  <option value="dev">Developer</option>
  <option value="design">Designer</option>
</select>

LUZ adds no style to the option: the browser draws the list. The closed box is the style of the select.

Shows the result of a calculation or of something the user did. Screen readers announce it when it changes.

HTML
<label for="d-range">Volume <output id="d-range-out" for="d-range">50</output></label>
<input id="d-range" type="range" min="0" max="100" value="50" data-output="d-range-out">

Styled by elements/forms.css, with no class.

Worth using

Use it for the result of a calculation or of an action, tied to the controls that produced it with for. Its value is not submitted with the form. Widely available since October 2018.

Screen readers: MDN: many browsers implement it as a live region, so a change is announced without moving focus. Updates are announced as plain text: a link or a button inside it may not be conveyed.

Source: MDN, checked on 11 October 2026.

Shows how far a task has got, such as an upload. Leave out value while you cannot tell, and the bar shows activity without an amount.

70% Working
HTML
<label for="d-progress">Uploading, 70%</label>
<progress id="d-progress" max="100" value="70">70%</progress>
<label for="d-progress-wait">Working</label>
<progress id="d-progress-wait">Working</progress>

Styled by elements/forms.css, with no class: the size of the bar and the brand color of its fill. .luz-progress draws the track and the fill itself.

A list of fixed choices the user picks from. When there are only a few and they should all stay in view, radio buttons are quicker.

HTML
<label for="d-select">Role</label>
<select id="d-select">
  <option value="">Select a role</option>
  <option value="dev">Developer</option>
  <option value="design">Designer</option>
</select>

Styled by elements/forms.css, with no class: the closed box. The open list is the browser’s. Add .luz-select to style the open list too, where the browser can.

<selectedcontent>

Experimental MDN reference for the selectedcontent element

Repeats the chosen option inside the button of a customizable select, so its icons and formatting carry over. Experimental: check the browser compatibility table on MDN before you rely on it.

Markup only: this element is not rendered.

HTML
<select>
  <button>
    <selectedcontent></selectedcontent>
  </button>
  <option value="design">Design</option>
  <option value="build">Build</option>
</select>

LUZ adds no style: the browser look is kept.

A field for text that runs over several lines, such as a message. LUZ lets it grow vertically only.

HTML
<label for="d-textarea">Notes</label>
<textarea id="d-textarea" rows="3" placeholder="Anything else?"></textarea>

Styled by elements/forms.css, with no class: the look of a text field, taller, and it grows vertically only. The classes .luz-input and .luz-input--textarea give the same look inside a .luz-field.

The 22 input types

One element, <input>, becomes a different control with its type. Each has a live example with no class, except color and file, which take .luz-input; hidden and image have nothing to show. The browser validates and offers the right keyboard on its own: pick the most specific type before reaching for a script.

  • type="button"

    A push button with no behaviour of its own: a script gives it one. Prefer the button element, which can hold markup.

  • type="checkbox"

    On or off, or one of several choices that can all be on.

  • type="color"

    Opens the browser’s color picker. The value is always #rrggbb.

  • type="date"

    A day: year, month and day. The value is YYYY-MM-DD whatever the display language.

  • type="datetime-local"

    A day and a time with no time zone.

  • type="email"

    One address, or several with multiple. The browser checks the shape and shows an @ on a phone keyboard.

  • type="file"

    Chooses files from the device. accept filters them, multiple allows several.

  • type="hidden"

    Not shown: its value travels with the form. Never put anything secret in it, the reader can read it.

    Nothing to show here.

  • type="image"

    A submit button drawn as an image. It needs src and alt. Prefer a button that holds an img.

    Nothing to show here.

  • type="month"

    A year and a month. Firefox and Safari on a computer show a text field: write YYYY-MM, and add a pattern.

  • type="number"

    A number with steps: min, max and step. For a postal code or a card number use inputmode="numeric" on a text field instead.

  • type="password"

    Hides the characters. Set autocomplete to current-password or new-password so a password manager can help.

  • type="radio"

    One choice among several that share a name.

  • type="range"

    A slider between min and max. It does not show its value: pair it with an output.

  • type="reset"

    Puts the fields of its form back to their first values. Rarely wanted: it is easy to press by mistake.

  • type="submit"

    Sends its form. Without a form it does nothing.

  • type="tel"

    A phone number. The browser checks no format, and shows a keypad on a phone.

  • type="text"

    The default: one line of free text.

  • type="time"

    A time of day with no date.

  • type="url"

    One absolute address, checked by the browser.

  • type="week"

    A year and an ISO week. Firefox and Safari on a computer show a text field: write YYYY-Www, and add a pattern.