Checkbox
Thymeleaf source
<sl:label><sl:checkbox th:field="*{terms}"/>Accept the terms and conditions</sl:label>Rendered HTML
<label class="label"> <span class="checkbox-wrapper"> <input type="checkbox" class="checkbox" name="terms"> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M20 6 9 17l-5-5"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indeterminate-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M5 12h14"></path> </svg> </span> Accept the terms and conditions</label>Binding to a form field
Section titled “Binding to a form field”th:field on a boolean field sets checked and adds the hidden _terms input Spring uses to see an unchecked box.
For a collection field, give each checkbox a value (or th:value), as with a plain checkbox.
<form th:object="${signup}" th:action="@{/signup}" method="post"> <sl:label><sl:checkbox th:field="*{terms}"/>Accept the terms and conditions</sl:label></form>Labelling it
Section titled “Labelling it”Put the checkbox inside its label: clicking the text toggles it, and it needs no id. Spring numbers the
id of a checkbox (terms1), so a label with for="terms" would miss it. For a label beside the checkbox, give the
checkbox an explicit id, which wins over the numbered one:
Thymeleaf source
<sl:checkbox id="checkbox-notify" name="notify"/><sl:label for="checkbox-notify">Notify me by email</sl:label>Rendered HTML
<span class="checkbox-wrapper"> <input type="checkbox" class="checkbox" id="checkbox-notify" name="notify"> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M20 6 9 17l-5-5"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indeterminate-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M5 12h14"></path> </svg></span><label class="label" for="checkbox-notify">Notify me by email</label>In a field with th:field, the checkbox gets the field’s name as its id (terms), and the field’s
label points at it. The field also shows the error message.
Checked
Section titled “Checked”Thymeleaf source
<sl:label><sl:checkbox name="newsletter" checked/>Send me the newsletter</sl:label>Rendered HTML
<label class="label"> <span class="checkbox-wrapper"> <input type="checkbox" class="checkbox" name="newsletter" checked> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M20 6 9 17l-5-5"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indeterminate-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M5 12h14"></path> </svg> </span> Send me the newsletter</label>Indeterminate
Section titled “Indeterminate”Neither checked nor unchecked: some of a group is selected. HTML has no attribute for it, only the DOM property
indeterminate. indeterminate on <sl:checkbox> renders data-indeterminate="true", from which Shadleaf’s script
sets the property when the page loads or htmx swaps the checkbox in; the box then shows a minus, and a screen reader
says “mixed”. A click clears it and checks the box, as with any checkbox. A script of yours can set the property on
any checkbox at any time; the minus follows it (the CSS reads :indeterminate). The script is not an Alpine
component, so it also runs with shadleaf.assets.alpine=external; without JavaScript the checkbox is unchecked.
Thymeleaf source
<sl:label><sl:checkbox name="toppings-all" indeterminate/>All toppings</sl:label>Rendered HTML
<label class="label"> <span class="checkbox-wrapper"> <input type="checkbox" class="checkbox" data-indeterminate="true" name="toppings-all"> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M20 6 9 17l-5-5"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indeterminate-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M5 12h14"></path> </svg> </span> All toppings</label>Select-all in a table is the common case, and sets the state itself.
Invalid
Section titled “Invalid”A field with errors marks the checkbox aria-invalid="true", as with the input.
Thymeleaf source
<sl:label><sl:checkbox th:field="*{terms}"/>Accept the terms and conditions</sl:label>Rendered HTML
<label class="label"> <span class="checkbox-wrapper"> <input type="checkbox" class="checkbox" name="terms" aria-invalid="true"> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M20 6 9 17l-5-5"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indeterminate-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M5 12h14"></path> </svg> </span> Accept the terms and conditions</label>Disabled
Section titled “Disabled”A disabled checkbox fades with its check mark, and a label fades with the disabled checkbox it holds, or sits next
to. In Windows’ high-contrast mode the browser draws its own disabled checkbox. HTML has no read-only checkbox:
readonly does nothing on one.
Thymeleaf source
<sl:label><sl:checkbox name="archived" checked disabled/>Archived</sl:label><sl:label><sl:checkbox name="deleted" disabled/>Deleted</sl:label>Rendered HTML
<label class="label"> <span class="checkbox-wrapper"> <input type="checkbox" class="checkbox" name="archived" checked disabled> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M20 6 9 17l-5-5"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indeterminate-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M5 12h14"></path> </svg> </span> Archived</label><label class="label"> <span class="checkbox-wrapper"> <input type="checkbox" class="checkbox" name="deleted" disabled> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M20 6 9 17l-5-5"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" class="icon checkbox-indeterminate-indicator" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M5 12h14"></path> </svg> </span> Deleted</label>How it is drawn
Section titled “How it is drawn”The check mark and the minus are icons inside a wrapper around the <input>, not CSS background images, so the checkbox renders
under a strict img-src policy. class goes to that wrapper; every other attribute to the <input>. In Windows’
high-contrast mode the browser draws its own checkbox, with its own dash when it is indeterminate.
Attributes
Section titled “Attributes”| Attribute | Values | Default | Description |
|---|---|---|---|
indeterminate | boolean | — | Start in the indeterminate state. HTML has no attribute for it, only the DOM property indeterminate: this renders data-indeterminate, from which Shadleaf's script sets the property when the page loads (or htmx swaps the checkbox in). A click clears it, as it does on every checkbox. A script can set the property on any checkbox; the minus follows it. |
Every prop can also be set from an expression: th:indeterminate="${...}". Any other attribute passes through to the rendered element, and class is appended.