Skip to content

Import#

import { Card } from '@dnb/eufemia'

Description#

Card is a block section element showing the white box with rounded gray borders, adding spacing automatically.

It uses Flex.Item under the hood. When one of these properties were given, stack, direction or spacing – the Flex.Container will be used.

Relevant links#

import { Card } from '@dnb/eufemia'
import { Form, Field } from '@dnb/eufemia/extensions/forms'
render(
<Form.Handler data={existingData} onSubmit={submitHandler}>
<Card>
<Field.Email path="/dataPath" />
<Form.ButtonRow>
<Form.SubmitButton />
</Form.ButtonRow>
</Card>
</Form.Handler>
)

Accessibility#

It uses a section element. Which allows you to add an aria-label or aria-labelledby to provide screen readers with landmarks.

<Card aria-labelledby="unique-id">
  <Form.SubHeading id="unique-id" space={0}>
    Heading
  </Form.SubHeading>
  <P>Content inside a landmark ...</P>
</Card>

Card.List and Card.ListItem#

Use Card.List and Card.ListItem to render a semantic <ul> / <li> list of cards. Card.List provides a responsive flex layout with wrapping. Card.ListItem supports a center prop to center content vertically — set it to true to always center, or "when-small" to center only on small screens.

Related components#

Card is part of the Content category. Other components for similar needs:

  • Accordion — to let people open and close sections of related content.
  • Avatar — to make a person, company, or profile easier to recognize.
  • CountryFlag — to show a country by its flag from an ISO country code.
  • DateFormat — to show dates in the correct DNB format.
  • Heading — to create accessible page headings with the correct level.
  • Icon — to render and size an icon in line with Eufemia styling.

See all in Content →

Demos#

Default border#

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi cursus pharetra elit in bibendum.

<Card>
  <P>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi cursus
    pharetra elit in bibendum.
  </P>
</Card>

Stack#

When stack is set to true, the Card will add a gap between its children and stretch them to the full.

For form components, you should use Form.Card instead of the original Card component.

When stack is set to true, the Card will add a gap between its children and stretch them to the full.

Stacked content

Stacked content

<Card stack>
  <P>Stacked content</P>
  <P>Stacked content</P>
</Card>

With form fields#

When using Eufemia Forms, you may want to use Form.Card instead of the original Card component.

<Form.Card>
  <Field.String label="Label" value="Value" />
  <Field.String label="Label" value="Value" />
</Form.Card>

Nested Cards#

Nested cards have responsive={false} by default and will not behave responsive.

First Card

Second Card

Third Card (edge case)

<Card stack>
  <P>First Card</P>
  <Card stack>
    <P>Second Card</P>
    <Card stack>
      <P>Third Card (edge case)</P>
    </Card>
  </Card>
</Card>

With drop shadow#

Card 1

Card 2

Card 3 (edge case)

<Card stack dropShadow>
  <Lead>Card 1</Lead>
  <Card stack top="2.5rem">
    <Lead size="basis">Card 2</Lead>
    <Card
      stack
      top="1.5rem"
      innerSpace={{
        top: true,
        block: '3rem',
        inline: true,
      }}
    >
      <Lead size="small">Card 3 (edge case)</Lead>
    </Card>
  </Card>
</Card>

With outset#

When using outset, the Card will break out of the layout container. On small screens (mobile) the outset is removed.

I'm left aligned

Card content

Nested card

<Flex.Vertical>
  <Form.MainHeading>I'm left aligned</Form.MainHeading>
  <Card stack outset>
    <P>Card content</P>
    <Card>
      <P>Nested card</P>
    </Card>
  </Card>
  <Form.SubmitButton text="I'm also left aligned" />
</Flex.Vertical>

Without padding#

no inner space

<Card innerSpace={false} align="stretch">
  <P>no inner space</P>
</Card>

With nested Section#

Card components need to have stack={true} or align="stretch" in order to stretch its children components.

Card with a nested Section

no inner space

no inner space

<Flex.Stack>
  <Card gap="x-small" align="stretch">
    <Form.SubHeading>Card with a nested Section</Form.SubHeading>
    <Section
      variant="information"
      innerSpace={{
        top: 'small',
        bottom: 'medium',
      }}
    >
      <Field.String width="medium" label="In nested Section" />
    </Section>
  </Card>

  <Card innerSpace="x-large" stack>
    <Section
      variant="information"
      innerSpace={{
        top: 'small',
        bottom: 'medium',
      }}
    >
      <Field.String
        width="medium"
        label="Card with a 'x-large' inner space"
      />
    </Section>
  </Card>

  <Card innerSpace={false} align="stretch">
    <P>no inner space</P>
    <Section innerSpace backgroundColor="var(--color-lavender)">
      <Field.String width="medium" label="Card with no inner space" />
    </Section>
    <P>no inner space</P>
  </Card>
</Flex.Stack>

With Table#

Card title
Column 1Column 2Column 3
Row 1Row 1Row 1
Row 3Row 3Row 3
const MyTable = () => (
  <Table.ScrollView>
    <Table border outline size="medium">
      <thead>
        <Tr noWrap>
          <Th>Column 1</Th>
          <Th>Column 2</Th>
          <Th>Column 3</Th>
        </Tr>
      </thead>
      <tbody>
        <Tr>
          <Td>Row 1</Td>
          <Td>Row 1</Td>
          <Td>Row 1</Td>
        </Tr>
        <Tr>
          <Td colSpan={3} align="right">
            <Button>Button</Button>
          </Td>
        </Tr>
        <Tr>
          <Td>Row 3</Td>
          <Td>Row 3</Td>
          <Td>Row 3</Td>
        </Tr>
      </tbody>
    </Table>
  </Table.ScrollView>
)
render(
  <Card title="Card title" responsive={false} innerSpace={0} filled>
    <MyTable />
  </Card>
)

With Grid#

Grid wraps the Cards nicely on smaller screens.

Heading

Text

Heading

Pariatur officia sit adipisicing pariatur commodo enim do quis

Heading

Text

<Grid.Container
  columns={{
    small: 1,
    medium: 3,
    large: 3,
  }}
  columnGap="small"
>
  <Card stack>
    <H2>Heading</H2>
    <P>Text</P>
  </Card>
  <Card stack>
    <H2>Heading</H2>
    <P>Pariatur officia sit adipisicing pariatur commodo enim do quis</P>
  </Card>
  <Card stack>
    <H2>Heading</H2>
    <P>Text</P>
  </Card>
</Grid.Container>

With Flex#

While Flex has the horizontal direction, it uses rowGap when wrapping. So it's the container spacing the Cards then. This is not ideal, because the Cards should ideally have no gap, like in the Grid example above.

Heading

Text

Heading

Pariatur officia sit adipisicing pariatur commodo enim do quis

Heading

Text

<Flex.Container>
  <Card
    span={{
      small: 'auto',
      medium: 4,
      large: 4,
    }}
    stack
  >
    <H2>Heading</H2>
    <P>Text</P>
  </Card>
  <Card
    span={{
      small: 'auto',
      medium: 4,
      large: 4,
    }}
    stack
  >
    <H2>Heading</H2>
    <P>Pariatur officia sit adipisicing pariatur commodo enim do quis</P>
  </Card>
  <Card
    span={{
      small: 'auto',
      medium: 4,
      large: 4,
    }}
    stack
  >
    <H2>Heading</H2>
    <P>Text</P>
  </Card>
</Flex.Container>

With backgroundColor and outline#

I'm left aligned

Card content

Nested card

<Flex.Vertical>
  <Form.MainHeading>I'm left aligned</Form.MainHeading>
  <Card
    stack
    backgroundColor="var(--token-color-background-neutral-subtle)"
    outline="var(--token-color-stroke-neutral)"
  >
    <P>Card content</P>
    <Card outline="transparent">
      <P>Nested card</P>
    </Card>
  </Card>
</Flex.Vertical>

Interactive Cards#

Use Card.Action to make a Card clickable or a link. Pass onClick for a button-like card, or href/to for a link card. Both variants get hover, focus, and keyboard styles automatically.

For custom routing (e.g. react-router), pass a router Link via the element prop on Card.Action.

<Card.List
  style={{
    maxWidth: '640px',
    margin: '0 auto',
  }}
>
  <Card.ListItem center="when-small">
    <Card.Action
      onClick={() => console.log('Card clicked')}
      stack
      gap="x-small"
    >
      <Lead>Clickable card</Lead>
      <P>Click this card. It has hover, focus, and keyboard support.</P>
      <Button
        variant="tertiary"
        icon="chevron_right"
        text="Read more"
        element="span"
      />
    </Card.Action>
  </Card.ListItem>

  <Card.ListItem center="when-small">
    <Card.Action href="/" stack gap="x-small">
      <Lead>Link card</Lead>
      <P>This card navigates with an anchor element.</P>
      <Button
        variant="tertiary"
        icon="chevron_right"
        text="Read more"
        element="span"
      />
    </Card.Action>
  </Card.ListItem>
</Card.List>
Suggest an edit