Card
A Card is a preview that serves as an entry point to more detailed information.
Component Type
Container
Platform
Web
Component
Sana Canvas
Delivery Channels
Web
Version
16.1.7Experience Surfaces
Page Body Inline
Anatomy

- Card Container: This rectangular container is the fundamental part of this component. It is styled with Sana Canvas Tokens to ensure the background color, corner radius, depth, and outline stroke are coherent as a basis with cards within workday. This can be used as the basis for creating more tailored card types.
- Title (Optional): The title explained
- Paragraph (Optional): The Paragraph explained
Usage Guidance
- Cards hold a variety of content types, such as a combination of text, icons, imagery and actions related to a single topic.
- Cards should be easy to digest, providing relevant information and available actions.
- Text and visual elements should be placed in a way that clearly indicates hierarchy.
- Cards should be placed inside a layout grid to help with alignment and sizing.
- Most cards are created and maintained by specific product teams. The Sana Canvas card is a generic container which you can leverage when creating new cards. Check out the Sana Canvas Kit card container to see what’s available in Sana Canvas now.
When to Use
- Use Cards when you need to group information in a digestible form.
- Use Cards when you need to offer a short entry point that is linked to more detailed content or a complex task.
- Use Cards to lay out single or multiple sets of related information in the same region of the page. Cards may include an image, a text summary, pills, and actions. Cards typically have similar widths, but heights should accommodate varying content.
When to Use Something Else
- When you need to show unrelated content types or actions in a single container.
- When you need to show content in multiple columns.
- When you need to display content in a table format.
Examples
Basic Example
Card includes a container component and Card.Body and Card.Heading subcomponents.
Canvas Supreme
import React from 'react';
import {Card} from '@workday/canvas-kit-react/card';
export default () => {
return (
<Card>
<Card.Heading>Canvas Supreme</Card.Heading>
<Card.Body>
Our house special supreme pizza includes pepperoni, sausage, bell peppers, mushrooms,
onions, and oregano.
</Card.Body>
</Card>
);
};
Alt Example
The alt variant is designed for use on alternative page backgrounds (system.color.bg.alt.default). Use this variant to maintain proper visual hierarchy when placing components on colored backgrounds. While the default variant should be used on system.color.bg.default backgrounds, the alt variant ensures the component remains visually elevated on system.color.bg.alt.default backgrounds.
Canvas Supreme
import React from 'react';
import {Card} from '@workday/canvas-kit-react/card';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
const styles = createStyles({
background: system.color.bg.alt.default,
padding: system.padding.md,
});
export default () => {
return (
<div className={styles}>
<Card variant="alt">
<Card.Heading>Canvas Supreme</Card.Heading>
<Card.Body>
Our house special supreme pizza includes pepperoni, sausage, bell peppers, mushrooms,
onions, and oregano.
</Card.Body>
</Card>
</div>
);
};
Tonal Example
The tonal variant adds a background color to the Card, creating a more prominent appearance while
maintaining the same internal spacing and structure. Use this variant when you need a card with a
grayish background to create visual separation from the page background.
Canvas Supreme
import {Card} from '@workday/canvas-kit-react/card';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
const styles = createStyles({
background: system.color.bg.default,
padding: system.padding.md,
});
export default () => {
return (
<div className={styles}>
<Card variant="tonal">
<Card.Heading>Canvas Supreme</Card.Heading>
<Card.Body>
Our house special supreme pizza includes pepperoni, sausage, bell peppers, mushrooms,
onions, and oregano.
</Card.Body>
</Card>
</div>
);
};
Custom Styles
Card and its subcomponents support custom styling via the cs prop. For more information, check our
“How To Customize Styles” .
Note: The card uses the background css property to style the background color. If you want to override the background, you can use the [cardStencil.vars.background] css variable.
Canvas Supreme
import {Card, cardStencil} from '@workday/canvas-kit-react/card';
import {createStyles, px2rem} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
const customCardStyles = createStyles({
boxShadow: system.depth[2],
maxWidth: px2rem(320),
padding: system.padding.sm,
color: system.color.fg.default,
[cardStencil.vars.background]: system.color.surface.info.default,
});
export default () => (
<Card cs={customCardStyles}>
<Card.Heading>Canvas Supreme</Card.Heading>
<Card.Body>
Our house special supreme pizza includes pepperoni, sausage, bell peppers, mushrooms, onions,
and oregano.
</Card.Body>
</Card>
);
Stencils
You can also use Card stencils to extend styles for your own custom components. This allows you to
compose styles without using components directly. In the example below, we’re extending Card
stencils to create a custom MenuCard component.
Here’s an example of a Card with a reduced padding of x3 (0.75rem or 12px).
Sausage Pizza
Red sauce, homemade seasoned sausage, mushrooms, red bell peppers, rosemary, cheese.
import {cardBodyStencil, cardHeadingStencil, cardStencil} from '@workday/canvas-kit-react/card';
import {createComponent} from '@workday/canvas-kit-react/common';
import {CSProps, createStencil, handleCsProp, px2rem} from '@workday/canvas-kit-styling';
import {brand, system} from '@workday/canvas-tokens-web';
const menuCardStencil = createStencil({
extends: cardStencil,
base: {
display: 'flex',
flexDirection: 'column',
padding: '0',
maxWidth: px2rem(320),
boxShadow: system.depth[1],
overflow: 'hidden',
},
});
const menuCardHeroStencil = createStencil({
base: {
display: 'flex',
alignItems: 'flex-end',
background: brand.gradient.primary,
aspectRatio: '1',
maxHeight: px2rem(80),
padding: system.padding.xs,
},
});
const MenuCardHero = createComponent('div')({
displayName: 'MenuCard.Hero',
Component: (elemProps: CSProps, ref, Element) => {
return <Element ref={ref} {...handleCsProp(elemProps, menuCardHeroStencil())} />;
},
});
const menuCardContentStencil = createStencil({
base: {
display: 'flex',
flexDirection: 'column',
gap: system.gap.sm,
padding: system.padding.xs,
},
});
const MenuCardContent = createComponent('div')({
displayName: 'MenuCard.Content',
Component: (elemProps: CSProps, ref, Element) => {
return <Element ref={ref} {...handleCsProp(elemProps, menuCardContentStencil())} />;
},
});
const menuCardHeadingStencil = createStencil({
extends: cardHeadingStencil,
base: {
color: system.color.fg.inverse,
margin: '0',
},
});
const MenuCardHeading = createComponent('h3')({
displayName: 'MenuCard.Heading',
Component: (elemProps: CSProps, ref, Element) => {
return <Element ref={ref} {...handleCsProp(elemProps, menuCardHeadingStencil())} />;
},
});
const menuCardTextStencil = createStencil({
extends: cardBodyStencil,
base: {
margin: 0,
},
});
const MenuCardText = createComponent('p')({
displayName: 'MenuCard.Text',
Component: (elemProps: CSProps, ref, Element) => {
return <Element ref={ref} {...handleCsProp(elemProps, menuCardTextStencil())} />;
},
});
const MenuCard = createComponent('div')({
displayName: 'MenuCard',
Component: (elemProps: CSProps, ref, Element) => {
return <Element ref={ref} {...handleCsProp(elemProps, menuCardStencil())} />;
},
subComponents: {
Content: MenuCardContent,
Heading: MenuCardHeading,
Hero: MenuCardHero,
Text: MenuCardText,
},
});
export default () => (
<MenuCard>
<MenuCard.Hero>
<MenuCard.Heading>Sausage Pizza</MenuCard.Heading>
</MenuCard.Hero>
<MenuCard.Content>
<MenuCard.Text>
Red sauce, homemade seasoned sausage, mushrooms, red bell peppers, rosemary, cheese.
</MenuCard.Text>
<MenuCard.Text></MenuCard.Text>
</MenuCard.Content>
</MenuCard>
);
Component API
Card
Card is a container component that holds a and an optional
. Card wraps a non-semantic div element. The element can be
replaced using the as prop, or a role or other aria-* attributes can be added to give
Card semantic meaning.
Note: Changing the Card container to certain semantic elements will put accessibility at
risk. For example, using the as prop to change the cards to buttons will flatten the content in
the card. Headings, calls to action, etc. will not function as expected for users with
disabilities. Semantic container elements like <section>, or using <li> grouped together in a
common <ul> can be a useful way to elevate the accessibility of your design.
Layout Component
Card supports all props from thelayout component.
Props
Props extend from div. Changing the as prop will change the element interface.
| Name | Type | Description | Default |
|---|---|---|---|
children | ReactNode | Children of the Card. Should contain a | |
variant | 'alt' | 'tonal' | The variant of the Card. Can be | 'default' |
cs | | The | |
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | div |
ref | React.Ref<R = div> | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If |
Card.Heading
Card.Heading is an optional subcomponent that is meant to describe the Card. Since Card
is a non-semantic presentational component, Card.Heading does not automatically have any
semantic meaning. If your use case requires the Heading to label the Card, you must do so
manually.
For example, (which uses a Card) adds an aria-labelledby and a role to
the Card, as well as an id to the Card.Heading.
<Card role="dialog" aria-labelledby="card-heading">
<Card.Heading id="card-heading">Card Title</Card.Heading>
<Card.Body>Card Contents</Card.Body>
</Card>
Card.Heading defaults to an <h3> element, but it can be changed using the as prop.
Layout Component
Card.Heading supports all props from thelayout component.
Props
Props extend from h3. Changing the as prop will change the element interface.
| Name | Type | Description | Default |
|---|---|---|---|
id | string | The id of the Card heading. Tie this to an | |
children | ReactNode | ||
cs | | The | |
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | h3 |
ref | React.Ref<R = h3> | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If |
Card.Body
Card.Body is a non-semantic subcomponent that contains the body of the card. Attributes may
be added to give Card.Body semantic meaning. If Card.Body is brief (like in a short
dialog), it may be helpful to add an aria-describedby referencing the id of the
Card.Body to the Card container.
Layout Component
Card.Body supports all props from thelayout component.
Props
Props extend from div. Changing the as prop will change the element interface.
| Name | Type | Description | Default |
|---|---|---|---|
cs | | The | |
children | ReactNode | ||
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | div |
ref | React.Ref<R = div> | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If |
Accessibility Guidelines
Keyboard Interaction
Any interactive elements in the Card must have a focus indicator that is highly visible against the background and against the non-focused state. Refer to Accessible Colors for more information.
Cards must support the following keyboard interactions:
Tab: Focuses interactive elements included in the card (e.g. buttons, links, inputs, selects, etc.)
Screen Reader Interaction
Cards must communicate the following to users:
- The title (heading) of a Card represents the beginning of the content in a card.
- Calls to action in a Card are uniquely distinguishable from other cards on the screen.
Design Annotations Needed
- Decide heading level for the Card title in context of the page.
- Write accessible name for icon-only button variants.
- Write unique accessible names for generic call to action buttons.
- Write text alternatives for images and illustrations, unless they are for decorative purposes only.
Implementation Markup Needed
- Cards must begin with a heading element
<h2>-<h6>. - When using multiple cards together in a group, use
<ul>and<li>elements to build card containers as list items in an unordered list. - An
aria-labelstring is required for icon-only buttons and accessible tooltips can show the icon’s name for everyone. - Images, illustrations, and icons that may be considered decorative or redundant can be hidden from
screen readers by setting a null
alt=””attribute for<img>elements. - [Included in component] Decorative
<svg>icons are hidden from assistive technology withrole=”presentation”andfocusable=”false”.
Content Guidelines
- When writing content for Cards, refer to our Content Style Guide