Input
Thymeleaf source
<sl:label for="email">Email</sl:label><sl:input type="email" th:field="*{email}" placeholder="you@example.com"/>Rendered HTML
<label class="label" for="email">Email</label><input class="input" type="email" id="email" name="email" placeholder="you@example.com">Binding to a form field
Section titled “Binding to a form field”Inside a form with th:object, write th:field as on a plain <input>. Spring sets the input’s id, name and
value, so a label with for set to the field name points at it:
<form th:object="${profile}" th:action="@{/profile}" method="post"> <sl:label for="email">Email</sl:label> <sl:input type="email" th:field="*{email}"/></form>An explicit id wins over the one th:field gives. In a field, put th:field on the field instead: it
adds the label, description and error messages and wires them to the input.
type defaults to text and takes the text-like input types. Checkboxes, radio buttons and switches get components of
their own.
Thymeleaf source
<sl:label for="input-password">Password</sl:label><sl:input type="password" id="input-password" name="password"/><sl:label for="input-date">Delivery date</sl:label><sl:input type="date" id="input-date" name="deliveryDate"/><sl:label for="input-file">Invoice</sl:label><sl:input type="file" id="input-file" name="invoice"/>Rendered HTML
<label class="label" for="input-password">Password</label><input class="input" type="password" id="input-password" name="password"><label class="label" for="input-date">Delivery date</label><input class="input" type="date" id="input-date" name="deliveryDate"><label class="label" for="input-file">Invoice</label><input class="input" type="file" id="input-file" name="invoice">Invalid
Section titled “Invalid”When the field has errors after a @Valid submit, the input marks itself aria-invalid="true", which the skins draw
in the destructive colour. A field shows the error message and links it with aria-describedby; outside
one, an aria-describedby you write passes through.
Thymeleaf source
<sl:label for="email">Email</sl:label><sl:input type="email" th:field="*{email}"/>Rendered HTML
<label class="label" for="input-invalid">Email</label><input class="input" type="email" id="input-invalid" name="email" value="wim@" aria-invalid="true">Without th:field, write aria-invalid="true" yourself.
Disabled
Section titled “Disabled”A disabled input fades and cannot be focused, as in shadcn; the lyra skin also gives it a grey background. Its value is not submitted, and its label fades with it. In Windows’ high-contrast mode it turns the system’s grey text colour instead of fading.
Thymeleaf source
<sl:label for="input-disabled">Customer number</sl:label><sl:input id="input-disabled" name="customerNumber" value="C-1042" disabled/>Rendered HTML
<label class="label" for="input-disabled">Customer number</label><input class="input" type="text" id="input-disabled" name="customerNumber" value="C-1042" disabled>Read-only
Section titled “Read-only”readonly keeps the value but stops the user from changing it. Unlike a disabled input, a read-only one still takes
focus, its value can be selected and copied, and it is submitted with the form: use it for a value the user needs to
see or quote, such as a reference number. It gets a muted background and loses its shadow, but keeps its full text
colour, so it reads differently from a disabled input and its text keeps its contrast (a read-only input is not
exempt from WCAG’s contrast minimum, a disabled one is). Errors still show: the destructive border and ring win over
the read-only look. shadcn has no read-only style.
Thymeleaf source
<sl:label for="input-reference">Order reference</sl:label><sl:input id="input-reference" name="reference" value="ORD-2026-0042" readonly/>Rendered HTML
<label class="label" for="input-reference">Order reference</label><input class="input" type="text" id="input-reference" name="reference" value="ORD-2026-0042" readonly>With htmx
Section titled “With htmx”Every attribute that is not a prop lands on the <input>:
Thymeleaf source
<sl:input type="search" name="q" aria-label="Search orders" th:hx-get="@{/orders}" hx-trigger="input changed delay:300ms" hx-target="#orders"/>Rendered HTML
<input class="input" type="search" name="q" aria-label="Search orders" hx-get="/orders" hx-trigger="input changed delay:300ms" hx-target="#orders">Attributes
Section titled “Attributes”| Attribute | Values | Default | Description |
|---|---|---|---|
type | text email password number search tel url date datetime-local month week time file | text | Type of the input. Checkboxes and radio buttons have components of their own. |
Every prop can also be set from an expression: th:type="${...}". Any other attribute passes through to the rendered element, and class is appended.