展示类

卡片

常规的卡片容器,可以承载标题、段落、图片、列表等内容。

代码演示

如何引入

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

CardMeta 即 Card.Meta,两种写法等价。

基础卡片

基础卡片包含标题、内容等部分。

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

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

简洁卡片

卡片可以只设置内容区域。

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

Card meta img
Semi Doc
代码
<script lang="ts">
    import { IconInfoCircle } from '@fibrae/semi-icons-svelte';
    import { Avatar, Card, CardMeta, Popover } from '@fibrae/semi-ui-svelte';

    const bodyStyle = 'display: flex; align-items: center; justify-content: space-between';
</script>

{#snippet avatar()}
    <Avatar alt="Card meta img" size="default" src="/assets/placeholder/logo.svg" />
{/snippet}
{#snippet content()}
    <article style="padding: 6px">这是一个 Card</article>
{/snippet}

<Card style="max-width: 360px">Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。</Card>
<br />
<Card {bodyStyle} style="max-width: 360px">
    <CardMeta {avatar} title="Semi Doc" />
    <Popover {content} position="top" showArrow>
        <IconInfoCircle aria-label="信息" style="color: var(--semi-color-primary)" />
    </Popover>
</Card>

封面

可以使用 cover snippet 设置封面。

example
卡片封面
代码
<script lang="ts">
    import { Card, CardMeta } from '@fibrae/semi-ui-svelte';
</script>

{#snippet cover()}
    <img alt="example" src="/assets/root-web-sites/card-cover-docs-demo2.jpeg" />
{/snippet}

<Card {cover} style="max-width: 300px">
    <CardMeta title="卡片封面" />
</Card>

边线和外边框

可以使用 bordered 设置卡片是否有外边框,默认为 true 。同时,也可以使用 headerLine 设置内容区和标题区是否有边线, footerLine 设置内容区和页尾区是否有边线。

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

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

阴影

可以使用 shadows 设置显示阴影的时机,可选值为: hover(hover 时显示阴影)、always(始终显示阴影),如果不设置该属性则没有阴影。

Card meta img
Semi Doc

Card meta img
Semi Doc
代码
<script lang="ts">
    import { IconInfoCircle } from '@fibrae/semi-icons-svelte';
    import { Avatar, Card, CardMeta, Popover } from '@fibrae/semi-ui-svelte';

    const bodyStyle = 'display: flex; align-items: center; justify-content: space-between';
</script>

{#snippet avatar()}
    <Avatar alt="Card meta img" size="default" src="/assets/placeholder/logo.svg" />
{/snippet}
{#snippet content()}
    <article style="padding: 6px">这是一个 Card</article>
{/snippet}

<div>
    <Card {bodyStyle} shadows="hover" style="max-width: 360px">
        <CardMeta {avatar} title="Semi Doc" />
        <Popover {content} position="top" showArrow>
            <IconInfoCircle aria-label="信息" style="color: var(--semi-color-primary)" />
        </Popover>
    </Card>
    <br />
    <Card {bodyStyle} shadows="always" style="max-width: 360px">
        <CardMeta {avatar} title="Semi Doc" />
        <Popover {content} position="top" showArrow>
            <IconInfoCircle aria-label="信息" style="color: var(--semi-color-primary)" />
        </Popover>
    </Card>
</div>

更灵活的内容展示

可以利用 CardMeta 支持更灵活的内容,允许设置 title、avatar、description,后两者是 snippet,title 可以是字符串或 snippet。

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

{#snippet title()}
    <CardMeta title="Semi Doc">
        {#snippet description()}全面、易用、优质{/snippet}
        {#snippet avatar()}
            <Avatar alt="Card meta img" size="default" src="/assets/placeholder/logo.svg" />
        {/snippet}
    </CardMeta>
{/snippet}
{#snippet headerExtraContent()}
    <TypographyText link>More</TypographyText>
{/snippet}
{#snippet cover()}
    <img alt="example" src="/assets/root-web-sites/card-cover-docs-demo.jpeg" />
{/snippet}
{#snippet footer()}
    <Space>
        <Button theme="borderless" type="primary">精选案例</Button>
        <Button theme="solid" type="primary">开始使用</Button>
    </Space>
{/snippet}

<Card {cover} {footer} footerLine footerStyle="display: flex; justify-content: flex-end" {headerExtraContent} style="max-width: 340px" {title}>Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。</Card>

内部卡片

卡片内部可以嵌套其他卡片。

Card title
Inner Card title
Inner Card content
Inner Card title
Inner Card content
代码
<script lang="ts">
    import { Card, TypographyText } from '@fibrae/semi-ui-svelte';
</script>

<Card title="Card title">
    <Card style="margin-bottom: 20px" title="Inner Card title">
        {#snippet headerExtraContent()}
            <TypographyText link>More</TypographyText>
        {/snippet}
        Inner Card content
    </Card>
    <Card title="Inner Card title">
        {#snippet headerExtraContent()}
            <TypographyText link>More</TypographyText>
        {/snippet}
        Inner Card content
    </Card>
</Card>

栅格卡片

在系统概览页面常常和栅格进行配合。

Card Title
Card Content
Card Title
Card Content
Card Title
Card Content
Card Title
Card Content
Card Title
Card Content
代码
<script lang="ts">
    import { Card, Col, Row } from '@fibrae/semi-ui-svelte';

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

<div style="background-color: var(--semi-color-fill-0); padding: 20px">
    {#each rows as spans, rowIndex (rowIndex)}
        <Row gutter={[16, 16]}>
            {#each spans as span, colIndex (colIndex)}
                <Col {span}>
                    <Card bordered={false} title="Card Title">Card Content</Card>
                </Col>
            {/each}
        </Row>
    {/each}
</div>

内置预加载

可以使用 Card 的 loading 属性来设置卡片内容区是否显示占位元素,当它为 true 时将显示占位元素,反之则不显示。




代码
<script lang="ts">
    import { Card, CardMeta, Switch } from '@fibrae/semi-ui-svelte';

    let loading = $state(true);
</script>

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

更丰富的预加载效果

Card 自带的 loading 属性只能设置内容区的预加载效果,如果你想要设置其他部分的预加载,或者自定义更丰富的预加载效果,你可以结合 Skeleton 组件来实现。



代码
<script lang="ts">
    import { Avatar, Card, CardMeta, Skeleton, SkeletonAvatar, SkeletonImage, SkeletonParagraph, SkeletonTitle, Switch, TypographyText, TypographyTitle } from '@fibrae/semi-ui-svelte';

    let loading = $state(true);
</script>

{#snippet title()}
    <CardMeta>
        {#snippet title()}
            <Skeleton {loading} style="width: 80px">
                {#snippet placeholder()}<SkeletonTitle />{/snippet}
                <TypographyTitle heading={5}>Semi Doc</TypographyTitle>
            </Skeleton>
        {/snippet}
        {#snippet description()}
            <Skeleton {loading} style="width: 150px; margin-top: 12px">
                {#snippet placeholder()}<SkeletonParagraph rows={1} />{/snippet}
                <TypographyText>全面、易用、优质</TypographyText>
            </Skeleton>
        {/snippet}
        {#snippet avatar()}
            <Skeleton {loading}>
                {#snippet placeholder()}<SkeletonAvatar />{/snippet}
                <Avatar alt="Card meta img" size="default" src="/assets/placeholder/logo.svg" />
            </Skeleton>
        {/snippet}
    </CardMeta>
{/snippet}
{#snippet headerExtraContent()}
    <Skeleton {loading} style="width: 50px">
        {#snippet placeholder()}<SkeletonParagraph rows={1} />{/snippet}
        <TypographyText link>More</TypographyText>
    </Skeleton>
{/snippet}
{#snippet cover()}
    <Skeleton {loading} style="max-width: 100%; height: 220px">
        {#snippet placeholder()}<SkeletonImage />{/snippet}
        <img alt="example" src="/assets/root-web-sites/card-cover-docs-demo.jpeg" />
    </Skeleton>
{/snippet}

<Switch aria-label="显示内容" onChange={(v) => (loading = !v)} />
<br />
<br />
<Card {cover} {headerExtraContent} style="max-width: 300px" {title} />

带页签的卡片

可以结合 Tabs 组件,实现带页签的卡片。

Card title

content1

content1

content1

代码
<script lang="ts">
    import { Card, Tabs } from '@fibrae/semi-ui-svelte';

    const tabList = [
        { itemKey: '1', tab: 'Tab 1' },
        { itemKey: '2', tab: 'Tab 2' },
    ];
</script>

<Card title="Card title">
    <Tabs style="margin-top: -20px; margin-bottom: -20px" {tabList} type="line">
        {#snippet panel({ itemKey })}
            <p>content{itemKey}</p>
            <p>content{itemKey}</p>
            <p>content{itemKey}</p>
        {/snippet}
    </Tabs>
</Card>

卡片操作区

actions 接收 snippet 数组,每个 snippet 是一个操作,元素间将以 12px 的水平间距展示于内容区底部。

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

{#snippet cover()}
    <img alt="example" src="/assets/root-web-sites/card-cover-docs-demo.jpeg" />
{/snippet}
{#snippet rating()}
    <Rating size="small" value={4} />
{/snippet}

<Card actions={[rating]} {cover} headerLine={false} style="max-width: 300px">
    <CardMeta title="Semi Doc">
        {#snippet description()}全面、易用、优质{/snippet}
    </CardMeta>
</Card>

卡片组

CardGroup 中的卡片将呈现为等间距排列,利用 spacing 属性可以设置卡片间距大小。

滑动调节 Card 间距
10 40

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
代码
<script lang="ts">
    import { Card, CardGroup, Slider, TypographyText } from '@fibrae/semi-ui-svelte';

    let spacing = $state(12);
    const items = [1, 2, 3, 4, 5, 6, 7, 8];

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

<TypographyText id="card-group-spacing">滑动调节 Card 间距</TypographyText>
<Slider aria-labelledby="card-group-spacing" max={40} min={10} onChange={onSpacingChange} style="width: 360px" value={12} />
<br />
<CardGroup {spacing}>
    {#each items as idx (idx)}
        <Card headerLine={false} shadows="hover" style="width: 260px" title="Card title">
            {#snippet headerExtraContent()}
                <TypographyText link>More</TypographyText>
            {/snippet}
            <TypographyText>Card content</TypographyText>
        </Card>
    {/each}
</CardGroup>

网格型卡片组

使用 CardGroup 的 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
代码
<script lang="ts">
    import { Card, CardGroup, TypographyText } from '@fibrae/semi-ui-svelte';

    const items = [1, 2, 3, 4, 5, 6, 7];
</script>

<CardGroup type="grid">
    {#each items as idx (idx)}
        <Card headerLine={false} shadows="hover" style="width: 260px" title="Card title">
            {#snippet headerExtraContent()}
                <TypographyText link>More</TypographyText>
            {/snippet}
            <TypographyText>Card content</TypographyText>
        </Card>
    {/each}
</CardGroup>

API 参考

Card

Props

属性说明类型默认值
actions操作区,每个 snippet 作为一个操作,位于内容区底部,间距 12px。Snippet[]-
bodyStyle内容区的内联样式。string-
bordered是否显示卡片外边框。booleantrue
children卡片内容。Snippet-
cover卡片封面。Snippet-
footer自定义页脚。Snippet-
footerLine页脚区与内容区之间是否有边线。booleanfalse
footerStyle页脚区的内联样式。string-
header自定义整个标题区,会取代 title 和 headerExtraContent。Snippet-
headerExtraContent标题右侧的额外内容。Snippet-
headerLine标题区与内容区之间是否有边线。booleantrue
headerStyle标题区的内联样式。string-
loading是否在内容区显示加载占位,开启时根元素的 aria-busy 为 true。booleanfalse
shadows显示阴影的时机,可选 hover 或 always;不设置则没有阴影。Shadows-
title标题。字符串按 6 号标题的样式渲染为 div,超长时省略并显示提示;snippet 原样渲染。string | Snippet-

class、style 与原生属性和事件(如 id、aria-*、onclick)落在卡片的根元素(div)上。

CardGroup

Props

属性说明类型默认值
align子项的交叉轴对齐方式,传给 Space,可选 start、center、end、baseline。Align-
children要排列的卡片。Snippet-
spacing卡片间距,数值或 [水平间距, 垂直间距];type 为 grid 时不生效。number | [number, number]16
type设为 grid 时呈现为网格型,覆盖 spacing。CardGroupType-
vertical是否纵向排列,传给 Space。booleanfalse
wrap是否换行,传给 Space;纵向排列时不生效。booleantrue

class、style 与原生属性和事件同样落在内部 Space 的根元素上。

Card.Meta

Props

属性说明类型默认值
avatar头像。Snippet-
description描述。Snippet-
title标题,字符串或 snippet。string | Snippet-

class、style 与原生属性和事件(如 id、aria-*、onclick)落在根元素(div)上。

Accessibility

  • Card 支持传入 aria-label 或 aria-labelledby 来表示该 Card 作用,传入后根元素带 role="group"(传入的 role 优先)
  • Card loading 时,将开启 aria-busy
  • 字符串 title 按 h6 的样式渲染,但元素是 div,不带标题语义,不会打乱页面的标题层级;需要标题语义时,传入自己的标题元素作为 title(Vue 中写在 #title 插槽里)
  • Card 为容器型组件,卡片内部的任何元素需要遵循各自的可访问性指南

文案规范

  • 卡片标题
    • 卡片标题应具有信息描述性,聚焦最重要的信息
    • 尽量将标题限制在 1 个短语或句段中
    • 卡片标题应句子大小写书写
    • 不要以标点符号结尾(除了问号)
  • 正文
    • 可操作的:使用祈使句而不是“你可以”来描述正文,可以更好的告诉用户可以做什么
✅ 推荐用法❌ 不推荐用法
Get order progress for detailsYou can get order progress for details
  • 总是优先说最重要的信息
  • 使用 “Need to”而不是”must“

设计变量

下表是组件内部的 Sass 变量,不能覆写。定制样式请覆写 --semi-* CSS 变量(见 Design Token 页),或写不分层的 CSS 规则。
Sass 变量值用法
$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