展示类

卡片

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

代码演示

如何引入

import { Card, CardGroup } from '@fibrous/semi-ui-solid';

基础卡片

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

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

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

简洁卡片

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

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

Card meta img
Semi Doc
代码
import { IconInfoCircle } from '@fibrous/semi-icons-solid';
import { Avatar, Card, Popover } from '@fibrous/semi-ui-solid';

const avatarSrc = '/assets/placeholder/logo.svg';
const bodyStyle = { display: 'flex', 'align-items': 'center', 'justify-content': 'space-between' };

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

封面

可以使用 cover 属性设置封面。

example
卡片封面
代码
import { Card } from '@fibrous/semi-ui-solid';

const coverSrc = '/assets/root-web-sites/card-cover-docs-demo2.jpeg';

export default function CardDemo() {
    return (
        <Card style={{ 'max-width': '300px' }} cover={<img alt="example" src={coverSrc} />}>
            <Card.Meta title="卡片封面" />
        </Card>
    );
}

边线和外边框

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

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

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

阴影

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

Card meta img
Semi Doc

Card meta img
Semi Doc
代码
import { IconInfoCircle } from '@fibrous/semi-icons-solid';
import { Avatar, Card, Popover } from '@fibrous/semi-ui-solid';

const avatarSrc = '/assets/placeholder/logo.svg';
const bodyStyle = { display: 'flex', 'align-items': 'center', 'justify-content': 'space-between' };

export default function CardDemo() {
    return (
        <div>
            <Card shadows="hover" style={{ 'max-width': '360px' }} bodyStyle={bodyStyle}>
                <Card.Meta title="Semi Doc" avatar={<Avatar alt="Card meta img" size="default" src={avatarSrc} />} />
                <Popover position="top" showArrow content={<article style={{ padding: '6px' }}>这是一个 Card</article>}>
                    <IconInfoCircle aria-label="信息" style={{ color: 'var(--semi-color-primary)' }} />
                </Popover>
            </Card>
            <br />
            <Card shadows="always" style={{ 'max-width': '360px' }} bodyStyle={bodyStyle}>
                <Card.Meta title="Semi Doc" avatar={<Avatar alt="Card meta img" size="default" src={avatarSrc} />} />
                <Popover position="top" showArrow content={<article style={{ padding: '6px' }}>这是一个 Card</article>}>
                    <IconInfoCircle aria-label="信息" style={{ color: 'var(--semi-color-primary)' }} />
                </Popover>
            </Card>
        </div>
    );
}

更灵活的内容展示

可以利用 Card.Meta 支持更灵活的内容,允许设置 title、avatar、description。

Card meta img
Semi Doc
全面、易用、优质
example
Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。
代码
import { Avatar, Button, Card, Space, Typography } from '@fibrous/semi-ui-solid';

const avatarSrc = '/assets/placeholder/logo.svg';
const coverSrc = '/assets/root-web-sites/card-cover-docs-demo.jpeg';

export default function CardDemo() {
    return (
        <Card
            style={{ 'max-width': '340px' }}
            title={<Card.Meta title="Semi Doc" description="全面、易用、优质" avatar={<Avatar alt="Card meta img" size="default" src={avatarSrc} />} />}
            headerExtraContent={<Typography.Text link>More</Typography.Text>}
            cover={<img alt="example" src={coverSrc} />}
            footerLine
            footerStyle={{ display: 'flex', 'justify-content': 'flex-end' }}
            footer={
                <Space>
                    <Button theme="borderless" type="primary">
                        精选案例
                    </Button>
                    <Button theme="solid" type="primary">
                        开始使用
                    </Button>
                </Space>
            }
        >
            Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。
        </Card>
    );
}

内部卡片

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

Card title
Inner Card title
Inner Card content
Inner Card title
Inner Card content
代码
import { Card, Typography } from '@fibrous/semi-ui-solid';

export default function CardDemo() {
    return (
        <Card title="Card title">
            <Card title="Inner Card title" style={{ 'margin-bottom': '20px' }} headerExtraContent={<Typography.Text link>More</Typography.Text>}>
                Inner Card content
            </Card>
            <Card title="Inner Card title" headerExtraContent={<Typography.Text link>More</Typography.Text>}>
                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
代码
import { Card, Col, Row } from '@fibrous/semi-ui-solid';

export default function CardDemo() {
    return (
        <div style={{ 'background-color': 'var(--semi-color-fill-0)', padding: '20px' }}>
            <Row gutter={[16, 16]}>
                <Col span={8}>
                    <Card title="Card Title" bordered={false}>
                        Card Content
                    </Card>
                </Col>
                <Col span={8}>
                    <Card title="Card Title" bordered={false}>
                        Card Content
                    </Card>
                </Col>
                <Col span={8}>
                    <Card title="Card Title" bordered={false}>
                        Card Content
                    </Card>
                </Col>
            </Row>
            <Row gutter={[16, 16]}>
                <Col span={16}>
                    <Card title="Card Title" bordered={false}>
                        Card Content
                    </Card>
                </Col>
                <Col span={8}>
                    <Card title="Card Title" bordered={false}>
                        Card Content
                    </Card>
                </Col>
            </Row>
        </div>
    );
}

内置预加载

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




代码
import { createSignal } from 'solid-js';
import { Card, Switch } from '@fibrous/semi-ui-solid';

export default function CardDemo() {
    const [loading, setLoading] = createSignal(true);

    return (
        <>
            <Switch aria-label="显示内容" onChange={(checked) => setLoading(!checked)} />
            <br />
            <br />
            <Card style={{ 'max-width': '360px' }} loading={loading()}>
                <Card.Meta title="Semi Doc" description="全面、易用、优质" />
            </Card>
        </>
    );
}

更丰富的预加载效果

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



代码
import { createSignal } from 'solid-js';
import { Avatar, Card, Skeleton, Switch, Typography } from '@fibrous/semi-ui-solid';

const avatarSrc = '/assets/placeholder/logo.svg';
const coverSrc = '/assets/root-web-sites/card-cover-docs-demo.jpeg';

export default function CardDemo() {
    const [loading, setLoading] = createSignal(true);

    return (
        <>
            <Switch aria-label="显示内容" onChange={(checked) => setLoading(!checked)} />
            <br />
            <br />
            <Card
                style={{ 'max-width': '300px' }}
                title={
                    <Card.Meta
                        title={
                            <Skeleton style={{ width: '80px' }} placeholder={<Skeleton.Title />} loading={loading()}>
                                <Typography.Title heading={5}>Semi Doc</Typography.Title>
                            </Skeleton>
                        }
                        description={
                            <Skeleton style={{ width: '150px', 'margin-top': '12px' }} placeholder={<Skeleton.Paragraph rows={1} />} loading={loading()}>
                                <Typography.Text>全面、易用、优质</Typography.Text>
                            </Skeleton>
                        }
                        avatar={
                            <Skeleton placeholder={<Skeleton.Avatar />} loading={loading()}>
                                <Avatar alt="Card meta img" size="default" src={avatarSrc} />
                            </Skeleton>
                        }
                    />
                }
                headerExtraContent={
                    <Skeleton style={{ width: '50px' }} placeholder={<Skeleton.Paragraph rows={1} />} loading={loading()}>
                        <Typography.Text link>More</Typography.Text>
                    </Skeleton>
                }
                cover={
                    <Skeleton style={{ 'max-width': '100%', height: '220px' }} placeholder={<Skeleton.Image />} loading={loading()}>
                        <img alt="example" src={coverSrc} />
                    </Skeleton>
                }
            />
        </>
    );
}

带页签的卡片

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

Card title

content1

content1

content1

代码
import { Card, TabPane, Tabs } from '@fibrous/semi-ui-solid';

export default function CardDemo() {
    return (
        <Card title="Card title">
            <Tabs type="line" style={{ 'margin-top': '-20px', 'margin-bottom': '-20px' }}>
                <TabPane tab="Tab 1" itemKey="1">
                    <p>content1</p>
                    <p>content1</p>
                    <p>content1</p>
                </TabPane>
                <TabPane tab="Tab 2" itemKey="2">
                    <p>content2</p>
                    <p>content2</p>
                    <p>content2</p>
                </TabPane>
            </Tabs>
        </Card>
    );
}

卡片操作区

actions 接收 JSX 元素数组,元素间将以 12px 的水平间距展示于内容区底部。

example
Semi Doc
全面、易用、优质
代码
import { Card, Rating } from '@fibrous/semi-ui-solid';

const coverSrc = '/assets/root-web-sites/card-cover-docs-demo.jpeg';

export default function CardDemo() {
    return (
        <Card style={{ 'max-width': '300px' }} actions={[<Rating size="small" defaultValue={4} />]} headerLine={false} cover={<img alt="example" src={coverSrc} />}>
            <Card.Meta title="Semi Doc" description="全面、易用、优质" />
        </Card>
    );
}

卡片组

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

滑动调节 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
代码
import { For, createSignal } from 'solid-js';
import { Card, CardGroup, Slider, Typography } from '@fibrous/semi-ui-solid';

const cardIndexes = Array.from({ length: 8 }, (_, index) => index);

export default function CardDemo() {
    const [spacing, setSpacing] = createSignal(12);

    return (
        <>
            <Typography.Text id="card-group-spacing">滑动调节 Card 间距</Typography.Text>
            <Slider
                aria-labelledby="card-group-spacing"
                defaultValue={12}
                max={40}
                min={10}
                style={{ width: '360px' }}
                onChange={(value) => {
                    if (typeof value === 'number') setSpacing(value);
                }}
            />
            <br />
            <CardGroup spacing={spacing()}>
                <For each={cardIndexes}>
                    {() => (
                        <Card shadows="hover" title="Card title" headerLine={false} style={{ width: '260px' }} headerExtraContent={<Typography.Text link>More</Typography.Text>}>
                            <Typography.Text>Card content</Typography.Text>
                        </Card>
                    )}
                </For>
            </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
代码
import { For } from 'solid-js';
import { Card, CardGroup, Typography } from '@fibrous/semi-ui-solid';

const cardIndexes = Array.from({ length: 7 }, (_, index) => index);

export default function CardDemo() {
    return (
        <CardGroup type="grid">
            <For each={cardIndexes}>
                {() => (
                    <Card shadows="hover" title="Card title" headerLine={false} style={{ width: '260px' }} headerExtraContent={<Typography.Text link>More</Typography.Text>}>
                        <Typography.Text>Card content</Typography.Text>
                    </Card>
                )}
            </For>
        </CardGroup>
    );
}

API 参考

Card

Props

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

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

CardGroup

Props

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

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

Card.Meta

Props

属性说明类型默认值
avatar头像,位于标题与描述的左侧。JSX.Element-
description描述内容,位于标题之下。JSX.Element-
title标题内容。JSX.Element-

class、style、ref 与原生属性和事件落在根元素(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