Card
Thymeleaf source
<sl:card> <sl:card-header> <sl:card-title level="3">Order #1042</sl:card-title> <sl:card-description>Placed on 12 September</sl:card-description> <sl:card-action><sl:badge variant="secondary">Shipped</sl:badge></sl:card-action> </sl:card-header> <sl:card-content> <p>Three items, delivered to the Antwerp warehouse.</p> </sl:card-content> <sl:card-footer> <sl:button as="a" href="/orders/1042" variant="outline">View order</sl:button> </sl:card-footer></sl:card>Rendered HTML
<div class="card"> <div class="card-header"> <div class="card-title" role="heading" aria-level="3">Order #1042</div> <div class="card-description">Placed on 12 September</div> <div class="card-action"> <span class="badge" data-variant="secondary">Shipped</span> </div> </div> <div class="card-content"> <p>Three items, delivered to the Antwerp warehouse.</p> </div> <div class="card-footer"> <a class="button" data-variant="outline" href="/orders/1042">View order</a> </div></div>Built from parts
Section titled “Built from parts”A card is <sl:card> plus the parts you need, as in shadcn/ui: <sl:card-header> (holding <sl:card-title>,
<sl:card-description> and <sl:card-action>), <sl:card-content> and <sl:card-footer>. Use any of them, in any
order. Each part is its own component, so it has its own attributes and IDE completion, and passes every other
attribute through.
A card takes the width of its container; set it from your layout.
Thymeleaf source
<sl:card> <sl:card-content><p>A card needs none of its parts but one.</p></sl:card-content></sl:card>Rendered HTML
<div class="card"> <div class="card-content"> <p>A card needs none of its parts but one.</p> </div></div>A title that is a heading
Section titled “A title that is a heading”<sl:card-title> is plain text unless you give it a level. With one, it is announced as a heading of that level, so
screen reader users can jump between cards. Pick the level that fits the page: a card under an <h2> gets
level="3".
size="sm" tightens the spacing inside the card and between its parts.
Thymeleaf source
<sl:card size="sm"> <sl:card-header> <sl:card-title level="3">Late orders</sl:card-title> <sl:card-description>Past their delivery date</sl:card-description> </sl:card-header> <sl:card-content><p>3</p></sl:card-content></sl:card>Rendered HTML
<div class="card" data-size="sm"> <div class="card-header"> <div class="card-title" role="heading" aria-level="3">Late orders</div> <div class="card-description">Past their delivery date</div> </div> <div class="card-content"> <p>3</p> </div></div>Dividing lines
Section titled “Dividing lines”border on the header or the footer draws a line between it and the content, with matching spacing. It works without
utility classes, so also with the standalone stylesheet.
Thymeleaf source
<sl:card> <sl:card-header border> <sl:card-title level="3">Notifications</sl:card-title> <sl:card-description>What we email you about</sl:card-description> </sl:card-header> <sl:card-content><p>Order updates and weekly summaries.</p></sl:card-content> <sl:card-footer border> <sl:button>Save</sl:button> <sl:button variant="ghost">Cancel</sl:button> </sl:card-footer></sl:card>Rendered HTML
<div class="card"> <div class="card-header" data-border="bottom"> <div class="card-title" role="heading" aria-level="3">Notifications</div> <div class="card-description">What we email you about</div> </div> <div class="card-content"> <p>Order updates and weekly summaries.</p> </div> <div class="card-footer" data-border="top"> <button class="button" type="button">Save</button> <button class="button" type="button" data-variant="ghost">Cancel</button> </div></div>Attributes
Section titled “Attributes”sl:card
Section titled “sl:card”| Attribute | Values | Default | Description |
|---|---|---|---|
size | default sm | default | Spacing inside the card and between its parts. |
Every prop can also be set from an expression: th:size="${...}". Any other attribute passes through to the rendered element, and class is appended.
sl:card-header
Section titled “sl:card-header”| Attribute | Values | Default | Description |
|---|---|---|---|
border | boolean | — | A dividing line below the header, with matching spacing. |
Every prop can also be set from an expression: th:border="${...}". Any other attribute passes through to the rendered element, and class is appended.
sl:card-title
Section titled “sl:card-title”| Attribute | Values | Default | Description |
|---|---|---|---|
level | 1 2 3 4 5 6 | — | Heading level. With it the title is a heading (role="heading" and aria-level) that screen reader users can jump to; without it, plain text. Pick the level that fits the page's outline. |
Every prop can also be set from an expression: th:level="${...}". Any other attribute passes through to the rendered element, and class is appended.
sl:card-description
Section titled “sl:card-description”sl:card-description declares no props; every attribute passes through.
sl:card-action
Section titled “sl:card-action”sl:card-action declares no props; every attribute passes through.
sl:card-content
Section titled “sl:card-content”sl:card-content declares no props; every attribute passes through.
sl:card-footer
Section titled “sl:card-footer”| Attribute | Values | Default | Description |
|---|---|---|---|
border | boolean | — | A dividing line above the footer, with matching spacing. |
Every prop can also be set from an expression: th:border="${...}". Any other attribute passes through to the rendered element, and class is appended.