On this page
Cards group related content or controls into a distinct, bounded section.
- Overview
- Rules and guidance
- Properties
- Styles
- Accessibility
When to use
- To visually separate a self-contained piece of content from the surrounding page
- To group related fields, details, or controls that belong to the same subject
- As the structural container for more complex components such as AccordionGroup or banners
- When you need a clearly bounded section within a page that does not warrant a full page region
When not to use
- For tabular data - use Data Table instead, which provides sorting, alignment, and header semantics that a Card cannot.
- For key-value pairs - use Summary List instead, which is designed for displaying labelled data.
- As a clickable navigation element - card has no interactive semantics. If the whole card should be clickable, use a CTA Link or CTA Button as the primary action, and keep the card itself non-interactive.
- For brief status information attached to an object - use Badge instead.
Anatomy
- Container (the bordered, rounded surface that holds the card's content)
- Content area (the padded inner region; accepts any child components)
Basic usage
Edit live code
<Card> <Heading2>Plastic Recycling</Heading2> <P> Nearly all types of plastics can be recycled. However, the extent to which they are recycled depends upon technical, economic and logistic factors. </P> </Card>
Variants and features
Other HTML elements
By default, Card renders as a div. Use the as prop (from styled-components) to render as a different semantic element when the content warrants it.
- Use as="section" when the card represents a landmark region with a heading
- Use as="article" when the card's content is independently distributable
- Use as="fieldset" when the card groups related form fields (pair with a legend)
A card as a landmark region, with its heading naming the region:
Edit live code
<Card as="section" aria-labelledby="usage-heading"> <Heading2 id="usage-heading">Your usage</Heading2> <P>You used 212 kWh of electricity last month.</P> </Card>
A card as a fieldset, grouping related form fields. The legend must be the first element inside it:
Edit live code
<Card as="fieldset"> <Heading3 as="legend">Supply address</Heading3> <FormFields> <TextField id="address-line-1" label="Address line 1" /> <TextField id="address-town" label="Town or city" /> <TextField id="address-postcode" label="Postcode" characters={8} /> </FormFields> </Card>
The inline prop is deprecated and must not be used.
Composition
Card is a general-purpose container. There are no restrictions on what it can contain, but some patterns work better than others.
Keep each card focused on a single subject. A card that covers too many topics forces users to read everything to find what they need. If you find yourself splitting a card with internal headings into many sub-sections, consider whether the content should be broken into multiple cards or moved to its own page.
Limit the number of actions in a card. A single primary action is appropriate. If you need more, use one primary and one secondary action at most.
usage
- Card should group content that relates to a single subject or taskA card that spans multiple unrelated subjects forces users to read everything rather than scanning. Multiple focused cards are easier to navigate.Copy rule ID for card.single-subject
- Card must not be used to present tabular data in place of a Data TableData Table provides sorting, alignment, and semantic table structure that a Card cannot replicate.Copy rule ID for card.no-table-replacement
- Card inline prop must not be usedThe inline prop is deprecated and has no effect on the component's behaviour.Copy rule ID for card.inline-deprecated
interaction
- Card must not be made entirely clickable as a navigation elementCard has no interactive semantics. Making the whole surface clickable is inaccessible and ambiguous to keyboard and screen reader users.Copy rule ID for card.not-interactive
composition
- If rendered as a fieldsetCard must include a legend element as the first childA fieldset without a legend is invalid HTML and provides no group label to assistive technology.Copy rule ID for card.fieldset-legend
- Card should use the as prop to render the appropriate semantic HTML element for its contentThe default div has no semantic meaning. Where the card represents a section with a heading, an article, or a group of form fields, a more specific element improves accessibility.Copy rule ID for card.semantic-element
- If rendered as a section or article elementCard should include a heading that describes its contentLandmark elements without a heading cannot be distinguished from one another by screen reader users navigating by region.Copy rule ID for card.section-heading
- Card should not contain more than one primary actionMultiple primary actions compete for attention and make it unclear what the most important next step is.Copy rule ID for card.primary-action-limit
- Card should not contain so much content that it requires internal sub-headings to organiseIf a card needs its own heading hierarchy, the content likely belongs on its own page or split across multiple cards.Copy rule ID for card.no-overloaded-content
Card
Also accepts all props from HTMLAttributes.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
inline | boolean | — | No | Has no effect. |
as | ElementType | — | No | Renders the component as a different element or component, e.g. `as="section"`. |
forwardedAs | ElementType | — | No | Like `as`, but passed on to the component being wrapped, for when a styled wrapper should keep its own element and change the one beneath it. |
Styles
card
background: ${colors.canvas};
border-radius: ${radii.standard};
border: ${borderWidths.standard} solid ${colors.borderMuted};
box-shadow: 'none';
padding: ${space[3]};
${mediaQueries.smallAndUp} {
padding: ${space.cardPadding};
}
In brief
Card is a styled div with no role and no name. A screen reader announces what is inside it and nothing else, so the structure comes from the content you put in.
What Nebula provides
- A bordered, padded container that never takes focus and adds nothing to the accessibility tree.
- The as prop changes the element it renders, for example to a fieldset.
Accessible design
Start each card with a heading that names it
A card is only a visual boundary, so a screen reader user cannot find or skip one except through its heading. Open every card with a heading that says what it holds.
WCAG: 1.3.1 Info and Relationships 2.4.6 Headings and Labels
Accessible development
Choose the heading level for the card's place in the outline
The card does not set a level. A card on the page takes the level below the page title, and a card nested inside another takes the next level down.
WCAG: 1.3.1 Info and Relationships
If a card groups form controls, render it as a fieldset with a legend
A fieldset and its legend name the group for a screen reader user. Pass as="fieldset" to the card and render its heading as a legend.
WCAG: 1.3.1 Info and Relationships 3.3.2 Labels or Instructions
Accessibility testing status
Reviewed on 9 October 2026 against v17.0.1.
| Test | Status | Tested with |
|---|---|---|
| Default state | Tested | axe-core via the Storybook test runner (CI) |
| Advanced states | Partially tested | axe-core via the Storybook test runner (CI) |
| Keyboard navigation | Manually tested | keyboard (reported by the owner) |
| Screen reader | Partially tested | VoiceOver with Chrome (reported by the owner) |
What these tests and statuses mean
The table records which checks were run on this component on its own. It is not a statement of WCAG conformance, and it does not cover how the component is used.
The tests
- Default state: The component as it first appears, before anything is clicked or changed.
- Advanced states: Every other state and variant: error, open, selected, each size and style, and hovering.
- Keyboard navigation: Whether every function can be reached and used with the keyboard alone, with a visible focus ring.
- Screen reader: Whether a screen reader announces what is on screen correctly: the name, the role and any state.
The statuses
- Tested: Every check in this row passed in an automated run that repeats on every pull request.
- Manually tested: Every check in this row was run once, by a person or with a tool they started, and all of them passed. It is not re-run on every change.
- Partially tested: Some checks in this row were run once and passed; the rest are still to do.
- Issue found: A check in this row failed. The ticket is shown beside the status.
- Not tested: No check in this row has been run yet.
- Not applicable: This row does not apply to the component, for the reason given beside it.