Show · Card

Card

Card container can consist of titles, paragraphs, pictures, lists, and other content.

Demos

How to import

<script setup lang="ts">
    import { Card, CardGroup, CardMeta } from '@fibrous/semi-ui-vue';
</script>

CardMeta is the same component as Card.Meta; either form works.

Basic card

The basic card contains the title, content and other parts.

Semi Design
Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。
Code
<script setup lang="ts">
    import { Card, TypographyText } from '@fibrous/semi-ui-vue';
</script>

<template>
    <Card :style="{ maxWidth: '360px' }" title="Semi Design">
        <template #headerExtraContent>
            <TypographyText link>更多</TypographyText>
        </template>
        Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。
    </Card>
</template>

Simple card

The card can only set the content area.

Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。

Card meta img
Semi Doc
Code
<script setup lang="ts">
    import { IconInfoCircle } from '@fibrous/semi-icons-vue';
    import { Avatar, Card, CardMeta, Popover } from '@fibrous/semi-ui-vue';

    const bodyStyle = { display: 'flex', alignItems: 'center', justifyContent: 'space-between' };
</script>

<template>
    <Card :style="{ maxWidth: '360px' }"> Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。 </Card>
    <br />
    <Card :bodyStyle="bodyStyle" :style="{ maxWidth: '360px' }">
        <CardMeta title="Semi Doc">
            <template #avatar>
                <Avatar alt="Card meta img" size="default" src="/assets/placeholder/logo.svg" />
            </template>
        </CardMeta>
        <Popover position="top" showArrow>
            <template #content>
                <article :style="{ padding: '6px' }">这是一个 Card</article>
            </template>
            <IconInfoCircle aria-label="信息" :style="{ color: 'var(--semi-color-primary)' }" />
        </Popover>
    </Card>
</template>

Cover

You can use the #cover slot to set the cover.

example
卡片封面
Code
<script setup lang="ts">
    import { Card, CardMeta } from '@fibrous/semi-ui-vue';
</script>

<template>
    <Card :style="{ maxWidth: '300px' }">
        <template #cover>
            <img alt="example" src="/assets/root-web-sites/card-cover-docs-demo2.jpeg" />
        </template>
        <CardMeta title="卡片封面" />
    </Card>
</template>

Border and line

You can use bordered to set whether the card has an outer border, the default is true. At the same time, you can also use headerLine to set whether the content area and title area have borders, and footerLine to set whether the content area and footer area have borders.

Semi Design
Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。
Code
<script setup lang="ts">
    import { Card } from '@fibrous/semi-ui-vue';
</script>

<template>
    <div :style="{ display: 'inline-block', padding: '20px', backgroundColor: 'var(--semi-color-fill-0)' }">
        <Card :bordered="false" headerLine :style="{ maxWidth: '360px' }" title="Semi Design"> Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。 </Card>
    </div>
</template>

Shadows

You can use shadows to set the timing of the shadow display. Optional: hover (show shadow when hover), always (show shadow always), if this property is not set, there will be no shadow.

Card meta img
Semi Doc

Card meta img
Semi Doc
Code
<script setup lang="ts">
    import { IconInfoCircle } from '@fibrous/semi-icons-vue';
    import { Avatar, Card, CardMeta, Popover } from '@fibrous/semi-ui-vue';

    const bodyStyle = { display: 'flex', alignItems: 'center', justifyContent: 'space-between' };
</script>

<template>
    <div>
        <Card :bodyStyle="bodyStyle" shadows="hover" :style="{ maxWidth: '360px' }">
            <CardMeta title="Semi Doc">
                <template #avatar>
                    <Avatar alt="Card meta img" size="default" src="/assets/placeholder/logo.svg" />
                </template>
            </CardMeta>
            <Popover position="top" showArrow>
                <template #content>
                    <article :style="{ padding: '6px' }">这是一个 Card</article>
                </template>
                <IconInfoCircle aria-label="信息" :style="{ color: 'var(--semi-color-primary)' }" />
            </Popover>
        </Card>
        <br />
        <Card :bodyStyle="bodyStyle" shadows="always" :style="{ maxWidth: '360px' }">
            <CardMeta title="Semi Doc">
                <template #avatar>
                    <Avatar alt="Card meta img" size="default" src="/assets/placeholder/logo.svg" />
                </template>
            </CardMeta>
            <Popover position="top" showArrow>
                <template #content>
                    <article :style="{ padding: '6px' }">这是一个 Card</article>
                </template>
                <IconInfoCircle aria-label="信息" :style="{ color: 'var(--semi-color-primary)' }" />
            </Popover>
        </Card>
    </div>
</template>

Customized content

You can use CardMeta to support more flexible content, set through the #title slot (or the title property), #avatar and #description.

Card meta img
Semi Doc
全面、易用、优质
example
Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。
Code
<script setup lang="ts">
    import { Avatar, Button, Card, CardMeta, Space, TypographyText } from '@fibrous/semi-ui-vue';
</script>

<template>
    <Card :footerStyle="{ display: 'flex', justifyContent: 'flex-end' }" footerLine :style="{ maxWidth: '340px' }">
        <template #title>
            <CardMeta title="Semi Doc">
                <template #description>全面、易用、优质</template>
                <template #avatar>
                    <Avatar alt="Card meta img" size="default" src="/assets/placeholder/logo.svg" />
                </template>
            </CardMeta>
        </template>
        <template #headerExtraContent>
            <TypographyText link>More</TypographyText>
        </template>
        <template #cover>
            <img alt="example" src="/assets/root-web-sites/card-cover-docs-demo.jpeg" />
        </template>
        <template #footer>
            <Space>
                <Button theme="borderless" type="primary">精选案例</Button>
                <Button theme="solid" type="primary">开始使用</Button>
            </Space>
        </template>
        Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。
    </Card>
</template>

Inner card

Other cards can be nested inside the card.

Card title
Inner Card title
Inner Card content
Inner Card title
Inner Card content
Code
<script setup lang="ts">
    import { Card, TypographyText } from '@fibrous/semi-ui-vue';
</script>

<template>
    <Card title="Card title">
        <Card :style="{ marginBottom: '20px' }" title="Inner Card title">
            <template #headerExtraContent>
                <TypographyText link>More</TypographyText>
            </template>
            Inner Card content
        </Card>
        <Card title="Inner Card title">
            <template #headerExtraContent>
                <TypographyText link>More</TypographyText>
            </template>
            Inner Card content
        </Card>
    </Card>
</template>

Card in column

The system overview page is often combined with the grid.

Card Title
Card Content
Card Title
Card Content
Card Title
Card Content
Card Title
Card Content
Card Title
Card Content
Code
<script setup lang="ts">
    import { Card, Col, Row } from '@fibrous/semi-ui-vue';

    const rows = [
        [8, 8, 8],
        [16, 8],
    ];
</script>

<template>
    <div :style="{ backgroundColor: 'var(--semi-color-fill-0)', padding: '20px' }">
        <Row v-for="(spans, rowIndex) in rows" :key="rowIndex" :gutter="[16, 16]">
            <Col v-for="(span, colIndex) in spans" :key="colIndex" :span="span">
                <Card :bordered="false" title="Card Title">Card Content</Card>
            </Col>
        </Row>
    </div>
</template>

loading

You can use the loading property of Card to set whether to display placeholder elements in the card content area. When it is true, the placeholder elements will be displayed, and vice versa.




Code
<script setup lang="ts">
    import { ref } from 'vue';
    import { Card, CardMeta, Switch } from '@fibrous/semi-ui-vue';

    const loading = ref(true);
</script>

<template>
    <Switch aria-label="显示内容" @change="(v) => (loading = !v)" />
    <br />
    <br />
    <Card :loading="loading" :style="{ maxWidth: '360px' }">
        <CardMeta title="Semi Doc">
            <template #description>全面、易用、优质</template>
        </CardMeta>
    </Card>
</template>

With Skeleton

The loading property of Card can only set the preloading effect of the content area. If you want to set the preloading of other parts, or customize a richer preloading effect, you can combine it with the Skeleton component.



Code
<script setup lang="ts">
    import { ref } from 'vue';
    import { Avatar, Card, CardMeta, Skeleton, SkeletonAvatar, SkeletonImage, SkeletonParagraph, SkeletonTitle, Switch, TypographyText, TypographyTitle } from '@fibrous/semi-ui-vue';

    const loading = ref(true);
</script>

<template>
    <Switch aria-label="显示内容" @change="(v) => (loading = !v)" />
    <br />
    <br />
    <Card :style="{ maxWidth: '300px' }">
        <template #title>
            <CardMeta>
                <template #title>
                    <Skeleton :loading="loading" :style="{ width: '80px' }">
                        <template #placeholder>
                            <SkeletonTitle />
                        </template>
                        <TypographyTitle :heading="5">Semi Doc</TypographyTitle>
                    </Skeleton>
                </template>
                <template #description>
                    <Skeleton :loading="loading" :style="{ width: '150px', marginTop: '12px' }">
                        <template #placeholder>
                            <SkeletonParagraph :rows="1" />
                        </template>
                        <TypographyText>全面、易用、优质</TypographyText>
                    </Skeleton>
                </template>
                <template #avatar>
                    <Skeleton :loading="loading">
                        <template #placeholder>
                            <SkeletonAvatar />
                        </template>
                        <Avatar alt="Card meta img" size="default" src="/assets/placeholder/logo.svg" />
                    </Skeleton>
                </template>
            </CardMeta>
        </template>
        <template #headerExtraContent>
            <Skeleton :loading="loading" :style="{ width: '50px' }">
                <template #placeholder>
                    <SkeletonParagraph :rows="1" />
                </template>
                <TypographyText link>More</TypographyText>
            </Skeleton>
        </template>
        <template #cover>
            <Skeleton :loading="loading" :style="{ maxWidth: '100%', height: '220px' }">
                <template #placeholder>
                    <SkeletonImage />
                </template>
                <img alt="example" src="/assets/root-web-sites/card-cover-docs-demo.jpeg" />
            </Skeleton>
        </template>
    </Card>
</template>

With tabs

You can use the Tabs component in the card component.

Card title

content1

content1

content1

Code
<script setup lang="ts">
    import { Card, TabPane, Tabs } from '@fibrous/semi-ui-vue';
</script>

<template>
    <Card title="Card title">
        <Tabs :style="{ marginTop: '-20px', marginBottom: '-20px' }" type="line">
            <TabPane itemKey="1">
                <template #tab>Tab 1</template>
                <p>content1</p>
                <p>content1</p>
                <p>content1</p>
            </TabPane>
            <TabPane itemKey="2">
                <template #tab>Tab 2</template>
                <p>content2</p>
                <p>content2</p>
                <p>content2</p>
            </TabPane>
        </Tabs>
    </Card>
</template>

Actions

Every direct child in the #actions slot is one action, displayed at the bottom of the content area with a horizontal spacing of 12px.

example
Semi Doc
全面、易用、优质
Code
<script setup lang="ts">
    import { Card, CardMeta, Rating } from '@fibrous/semi-ui-vue';
</script>

<template>
    <Card :headerLine="false" :style="{ maxWidth: '300px' }">
        <template #cover>
            <img alt="example" src="/assets/root-web-sites/card-cover-docs-demo.jpeg" />
        </template>
        <template #actions>
            <Rating :defaultValue="4" size="small" />
        </template>
        <CardMeta title="Semi Doc">
            <template #description>全面、易用、优质</template>
        </CardMeta>
    </Card>
</template>

Card group

Use CardGroup to present the cards in an evenly spaced arrangement.

滑动调节 Card 间距
1040

Card title
Card content
Card title
Card content
Card title
Card content
Card title
Card content
Card title
Card content
Card title
Card content
Card title
Card content
Card title
Card content
Code
<script setup lang="ts">
    import { ref } from 'vue';
    import { Card, CardGroup, Slider, TypographyText } from '@fibrous/semi-ui-vue';

    const spacing = ref(12);

    const onSpacingChange = (value: number | number[]) => {
        if (typeof value === 'number') spacing.value = value;
    };
</script>

<template>
    <TypographyText id="card-group-spacing">滑动调节 Card 间距</TypographyText>
    <Slider aria-labelledby="card-group-spacing" :defaultValue="12" :max="40" :min="10" :style="{ width: '360px' }" @change="onSpacingChange" />
    <br />
    <CardGroup :spacing="spacing">
        <Card v-for="idx in 8" :key="idx" :headerLine="false" shadows="hover" :style="{ width: '260px' }" title="Card title">
            <template #headerExtraContent>
                <TypographyText link>More</TypographyText>
            </template>
            <TypographyText>Card content</TypographyText>
        </Card>
    </CardGroup>
</template>

Grid card

You can use the type property of CardGroup to set the card group to a grid type.

Card title
Card content
Card title
Card content
Card title
Card content
Card title
Card content
Card title
Card content
Card title
Card content
Card title
Card content
Code
<script setup lang="ts">
    import { Card, CardGroup, TypographyText } from '@fibrous/semi-ui-vue';
</script>

<template>
    <CardGroup type="grid">
        <Card v-for="idx in 7" :key="idx" :headerLine="false" shadows="hover" :style="{ width: '260px' }" title="Card title">
            <template #headerExtraContent>
                <TypographyText link>More</TypographyText>
            </template>
            <TypographyText>Card content</TypographyText>
        </Card>
    </CardGroup>
</template>

API reference

Card

Props

PropertyDescriptionTypeDefault
bodyStyleInline style of the content area.StyleValuesemiGlobalDefault("Card", "bodyStyle")
borderedWhether the card has an outer border.booleansemiDefault("Card", "bordered", true)
footerLineWhether there is a border between the footer and the content area.booleansemiDefault("Card", "footerLine", false)
footerStyleInline style of the footer area.StyleValuesemiGlobalDefault("Card", "footerStyle")
headerLineWhether there is a border between the header and the content area.booleansemiDefault("Card", "headerLine", true)
headerStyleInline style of the header area.StyleValuesemiGlobalDefault("Card", "headerStyle")
loadingWhether the content area shows a loading placeholder; the root element's aria-busy is true while on.booleansemiDefault("Card", "loading", false)
shadowsWhen to show the shadow: hover or always. No shadow when unset.ShadowssemiGlobalDefault("Card", "shadows")
titleTitle text, rendered as a div styled like a level-6 heading and truncated with a tooltip when too long; equivalent to the title slot, which wins when both are given.stringundefined

Events

EventDescriptionCallback parameters
None

Slots

SlotDescriptionScope parameters
defaultCard content.any
titleCard title. A single text renders like the title prop; other content renders as is.any
headerExtraContentExtra content to the right of the title.any
headerCustom header that replaces title and headerExtraContent.any
coverCard cover.any
actionsActions at the bottom of the content area, spaced 12px apart; every direct child becomes one action.any
footerCustom footer.any

Exposes

NameDescriptionType
None

class, style and other undeclared attributes land on the root element.

CardGroup

Props

PropertyDescriptionTypeDefault
spacingSpacing between cards, a number or [horizontal, vertical]; ignored when type is grid.number | [number, number]semiDefault("CardGroup", "spacing", 16)
typeSet to grid for a grid layout, which overrides spacing."grid"semiGlobalDefault("CardGroup", "type")
wrapWhether to wrap, passed to Space; ignored when vertical.booleansemiDefault("CardGroup", "wrap", true)
alignCross-axis alignment of the children, passed to Space: start, center, end or baseline.AlignsemiGlobalDefault("CardGroup", "align")
verticalWhether to lay out vertically, passed to Space.booleansemiDefault("CardGroup", "vertical", false)

Events

EventDescriptionCallback parameters
None

Slots

SlotDescriptionScope parameters
defaultThe cards to arrange.any

Exposes

NameDescriptionType
None

Undeclared attributes land on the root element of the inner Space.

Card.Meta

Props

PropertyDescriptionTypeDefault
titleTitle text, equivalent to the title slot, which wins when both are given.stringundefined

Events

EventDescriptionCallback parameters
None

Slots

SlotDescriptionScope parameters
avatarAvatar.any
titleTitle.any
descriptionDescription.any

Exposes

NameDescriptionType
None

Undeclared attributes land on the root element.

Accessibility

  • Card supports the input of aria-label or aria-labelledby to indicate the function of the Card; the root element then gets role="group" (an explicit role wins)
  • When Card loading, aria-busy will be turned on
  • A string title is styled as an h6 but rendered as a div without heading semantics, so it does not disturb the page's heading levels; pass your own heading element as title when you need one (in Vue, put it in the #title slot)
  • Card is a container-type component, and any elements inside the card need to follow their respective accessibility guidelines

Content Guidelines

  • Card title
    • Card titles should be informative and focus on the most important information
    • try to limit the title to 1 phrase or segment
    • Card titles should be written in sentence case
    • do not end with punctuation marks (except question marks)
  • Text
    • Actionable: Use imperative sentences instead of "you can" to describe the body, which better tells the user what can be done
✅ Recommended usage❌ Deprecated usage
Get order progress for detailsYou can get order progress for details
  • Always say the most important information first
  • Use "Need to" instead of "must"

Design Tokens

These are the component's internal Sass variables and cannot be overridden. To customize styles, override the --semi-* CSS variables (see the Design Token page) or write unlayered CSS rules.
Sass variableValueUsage
$color-card-bg-defaultvar(--semi-color-bg-0)卡片背景颜色
$color-card-bordervar(--semi-color-border)卡片描边颜色
$color-card_title-textvar(--semi-color-text-0)卡片标题文字颜色
$color-card_description-textvar(--semi-color-text-2)卡片描述文字颜色
$color-card_extra-textvar(--semi-color-text-0)卡片附加文字颜色
$color-card_body-textvar(--semi-color-text-1)卡片正文文字颜色
$font-card_default-fontWeight$font-weight-regular卡片文字字重 - 默认
$font-card_extra-fontWeight700卡片文字字重 - 附加文字
$font-card_title-fontWeight700卡片文字字重 - 标题
$font-card_default-lineHeight20px卡片文字行高 - 默认
$font-card_title-lineHeight22px卡片文字行高 - 标题
$font-card_default-fontSize$font-size-regular卡片文字大小 - 默认
$font-card_extra-fontSize$font-size-header-6卡片文字大小 - 附加文字
$font-card_title-fontSize$font-size-header-6卡片文字大小 - 标题
$radius-cardvar(--semi-border-radius-medium)卡片圆角
$motion-card-transition_duration300ms卡片悬浮动画时长
$width-card-border$border-thickness-control卡片描边宽度
$shadow-cardvar(--semi-shadow-elevated)卡片阴影
$spacing-card-padding$spacing-base-loose卡片内边距
$spacing-card-margin$spacing-base-loose卡片外边距
$spacing-card_avatar-marginRight$spacing-base-tight卡片头像右侧外边距
$spacing-cardGroup_card-margin-1px卡片组外边距
$z-card_hover1悬浮后卡片 zindex