Field

The wrapper that binds a label, a control and an error message into one form row.

<x-atlas::field>

Every Atlas form is built from fields. A field is a plain block wrapper: it sets the type scale for its contents and gives the row a predictable width, then leaves the arrangement to the components inside it. Start here, then reach for label, input and error to fill it.

Full name
<x-atlas::field>
    <x-atlas::label for="full-name">Full name</x-atlas::label>
    <x-atlas::input id="full-name" name="full_name" type="text" placeholder="Ada Lovelace" />
</x-atlas::field>
Preview follows the site's light/dark mode. Open standalone →

Errors

An invalid value needs three things said at once: mark the control with invalid so it turns red and gains aria-invalid, put the reason in an error, and point the control at that error with aria-describedby so a screen reader reads the two together.

Work email Enter an email address, including the part after the @.
<x-atlas::field>
    <x-atlas::label for="work-email" is-required>Work email</x-atlas::label>
    <x-atlas::input
        id="work-email"
        name="work_email"
        type="email"
        value="ada@"
        aria-describedby="work-email-error"
        invalid
    />
    <x-atlas::error id="work-email-error">Enter an email address, including the part after the @.</x-atlas::error>
</x-atlas::field>
Preview follows the site's light/dark mode. Open standalone →

Any control

Anything that can be labelled belongs in a field — input, textarea, select. Wrapping every control the same way is what keeps a long form from drifting out of rhythm.

Department Handover notes
<x-atlas::field>
    <x-atlas::label for="department">Department</x-atlas::label>
    <x-atlas::select id="department" name="department">
        <x-atlas::select.option value="design">Design</x-atlas::select.option>
        <x-atlas::select.option value="engineering">Engineering</x-atlas::select.option>
        <x-atlas::select.option value="support">Support</x-atlas::select.option>
    </x-atlas::select>
</x-atlas::field>

<x-atlas::field>
    <x-atlas::label for="handover">Handover notes</x-atlas::label>
    <x-atlas::textarea id="handover" name="handover" rows="4" placeholder="Anything the next person needs to know" />
</x-atlas::field>
Preview follows the site's light/dark mode. Open standalone →

Inline

variant="inline" lays the label out beside the control instead of above it, collapsing back to a stack under 768px. Use it for short, self-evident values — a quantity, a date — where a full-width label would waste a line. Anything that needs a hint or an error reads better stacked. Each label sizes to its own text, so stacked inline fields will not line their controls up in a column; give the labels a shared width yourself if that matters.

Seats Starts on
<x-atlas::field variant="inline">
    <x-atlas::label for="seats">Seats</x-atlas::label>
    <x-atlas::input id="seats" name="seats" type="number" value="4" min="1" max="20" />
</x-atlas::field>

<x-atlas::field variant="inline">
    <x-atlas::label for="starts-on">Starts on</x-atlas::label>
    <x-atlas::input id="starts-on" name="starts_on" type="date" value="2026-09-01" />
</x-atlas::field>
Preview follows the site's light/dark mode. Open standalone →

A whole form

Fields stack; a fieldset gathers the ones that belong together and a legend names the group. That is the entire layout system — there is no grid or column prop to learn.

<x-atlas::fieldset role="group" aria-labelledby="delivery-legend">
    <x-atlas::legend id="delivery-legend">Delivery address</x-atlas::legend>

    <x-atlas::field>
        <x-atlas::label for="street" is-required>Street and number</x-atlas::label>
        <x-atlas::input id="street" name="street" type="text" placeholder="Keizersgracht 123" required />
    </x-atlas::field>

    <x-atlas::field>
        <x-atlas::label for="postcode" is-required>Postcode</x-atlas::label>
        <x-atlas::input id="postcode" name="postcode" type="text" placeholder="1015 CJ" required />
    </x-atlas::field>

    <x-atlas::field>
        <x-atlas::label for="country">Country</x-atlas::label>
        <x-atlas::select id="country" name="country">
            <x-atlas::select.option value="nl">Netherlands</x-atlas::select.option>
            <x-atlas::select.option value="be">Belgium</x-atlas::select.option>
            <x-atlas::select.option value="de">Germany</x-atlas::select.option>
        </x-atlas::select>
    </x-atlas::field>

    <x-atlas::button type="submit">Save address</x-atlas::button>
</x-atlas::fieldset>
Preview follows the site's light/dark mode. Open standalone →

Reference

<x-atlas::field>

  • Name
    variant
    Type
    string
    Default
    default: (none)
    Description
    Appended as an <code>atlas-field--{variant}</code> modifier class. <code>inline</code> is the only variant Atlas ships styles for; it lays the label out beside the control and stacks again under 768px.

Slots

  • Name
    default
    Type
    slot
    Description
    The label, the control and — when the value is rejected — the error, in that order.