---
title: 课程卡 CourseCard
url: https://ui.zhaozimin.cn/components/course-card/
markdown: https://ui.zhaozimin.cn/components/course-card.md
group: 组件
origin: 设计系统源码（src/system），本仓库是唯一源头
source:
  - src/system/components/v4/CourseCard.jsx  # https://ui.zhaozimin.cn/src/system/components/v4/CourseCard.jsx
version: v0.2.0  # 设计系统版本，发布于 2026-09-23
scope: .zzm-v4   # 根节点必须带这个类，否则样式不生效
css: https://ui.zhaozimin.cn/v/0.2.0/zzm.css   # 锁版本地址，本仓库再改也不影响你
---

# 课程卡 CourseCard

> 综合首页与落地页共用的课程卡：16:9 暗底头图（封面或星座线稿）+ 名称、简介、适合人群、元数据与脚注动作。

登录后的综合首页卡就是基准形态；落地页不再维护变体，只换脚注文案与颜色。

### 样张 · 综合首页

脚注「进入课程 →」墨色；悬停上浮

React：

```jsx
import { CourseCard } from './components/v4/CourseCard.jsx'

const DEMO = {
  num: '01',
  name: 'Obsidian 知识管理',
  intro: '从零搭建一套以你为中心、能用十年的知识管理系统。',
  aud: '刚开始整理数字笔记的知识工作者',
  cover: null,
  art: {
    pl: [{ pts: '28,78 84,30 132,62 186,22 214,52', c: 'rgba(255,255,255,.28)', w: '1.2' }],
    dt: [
      { x: 28, y: 78, r: 2.4, f: '#FFFFFF' }, { x: 84, y: 30, r: 2.4, f: '#FFFFFF' },
      { x: 132, y: 62, r: 3.2, f: '@' }, { x: 186, y: 22, r: 2.4, f: '#FFFFFF' }, { x: 214, y: 52, r: 2.4, f: '#FFFFFF' },
    ],
  },
}

export function Hub() {
  return (
    <div style={{ width: 300 }}>
      <CourseCard course={DEMO} meta="6 系列 · 67 节" />
    </div>
  )
}
```

HTML（构建时由上面的 React 渲染得到，可直接粘贴）：

```html
<div style="width: 300px">
  <div
    class="zzm-hovercard"
    style="
      border: 1px solid rgba(0, 0, 0, 0.09);
      border-radius: 16px;
      background: #ffffff;
      overflow: hidden;
      cursor: pointer;
    "
  >
    <div style="aspect-ratio: 16/9; background: #131316; position: relative; overflow: hidden">
      <svg
        viewBox="0 0 240 135"
        preserveAspectRatio="xMidYMid slice"
        style="position: absolute; inset: 0; width: 100%; height: 100%"
      >
        <polyline
          points="28,78 84,30 132,62 186,22 214,52"
          fill="none"
          stroke="rgba(255,255,255,.28)"
          stroke-width="1.2"
          stroke-linecap="round"
          stroke-linejoin="round"
        ></polyline>
        <circle cx="28" cy="78" r="2.4" fill="#FFFFFF"></circle>
        <circle cx="84" cy="30" r="2.4" fill="#FFFFFF"></circle>
        <circle cx="132" cy="62" r="3.2" fill="var(--zzm-accent,#A6402F)"></circle>
        <circle cx="186" cy="22" r="2.4" fill="#FFFFFF"></circle>
        <circle cx="214" cy="52" r="2.4" fill="#FFFFFF"></circle>
      </svg>
      <div
        style="
          position: absolute;
          top: 10px;
          left: 11px;
          font-family: var(--zzm-mono);
          font-size: 10px;
          letter-spacing: 2px;
          padding: 3px 7px;
          border-radius: 4px;
          background: rgba(0, 0, 0, 0.55);
          color: rgba(255, 255, 255, 0.82);
        "
      >
        01
      </div>
    </div>
    <div style="padding: 16px 18px 17px">
      <div style="font-size: 16px; font-weight: 650">Obsidian 知识管理</div>
      <div style="margin-top: 6px; font-size: 13px; line-height: 1.65; color: #72726e">
        从零搭建一套以你为中心、能用十年的知识管理系统。
      </div>
      <div style="margin-top: 10px; font-size: 11.5px; color: #a2a29c">
        适合 · 刚开始整理数字笔记的知识工作者
      </div>
      <div style="margin-top: 13px; display: flex; align-items: center; gap: 8px">
        <span style="font-family: var(--zzm-mono); font-size: 10.5px; color: #8b8b85">
          6 系列 · 67 节
        </span>
        <span style="flex: 1"></span>
        <span style="font-size: 12px; font-weight: 600; color: #161616; white-space: nowrap">
          进入课程 →
        </span>
      </div>
    </div>
  </div>
</div>
```

### 样张 · 落地页

脚注换成朱色的下一步

React：

```jsx
import { CourseCard } from './components/v4/CourseCard.jsx'

const DEMO = {
  num: '01',
  name: 'Obsidian 知识管理',
  intro: '从零搭建一套以你为中心、能用十年的知识管理系统。',
  aud: '刚开始整理数字笔记的知识工作者',
  cover: null,
  art: {
    pl: [{ pts: '28,78 84,30 132,62 186,22 214,52', c: 'rgba(255,255,255,.28)', w: '1.2' }],
    dt: [
      { x: 28, y: 78, r: 2.4, f: '#FFFFFF' }, { x: 84, y: 30, r: 2.4, f: '#FFFFFF' },
      { x: 132, y: 62, r: 3.2, f: '@' }, { x: 186, y: 22, r: 2.4, f: '#FFFFFF' }, { x: 214, y: 52, r: 2.4, f: '#FFFFFF' },
    ],
  },
}

export function Landing() {
  return (
    <div style={{ width: 300 }}>
      <CourseCard course={DEMO} meta="6 系列 · 67 节" cta="免费试 3 节 →" ctaColor="var(--zzm-accent,#A6402F)" />
    </div>
  )
}
```

HTML（构建时由上面的 React 渲染得到，可直接粘贴）：

```html
<div style="width: 300px">
  <div
    class="zzm-hovercard"
    style="
      border: 1px solid rgba(0, 0, 0, 0.09);
      border-radius: 16px;
      background: #ffffff;
      overflow: hidden;
      cursor: pointer;
    "
  >
    <div style="aspect-ratio: 16/9; background: #131316; position: relative; overflow: hidden">
      <svg
        viewBox="0 0 240 135"
        preserveAspectRatio="xMidYMid slice"
        style="position: absolute; inset: 0; width: 100%; height: 100%"
      >
        <polyline
          points="28,78 84,30 132,62 186,22 214,52"
          fill="none"
          stroke="rgba(255,255,255,.28)"
          stroke-width="1.2"
          stroke-linecap="round"
          stroke-linejoin="round"
        ></polyline>
        <circle cx="28" cy="78" r="2.4" fill="#FFFFFF"></circle>
        <circle cx="84" cy="30" r="2.4" fill="#FFFFFF"></circle>
        <circle cx="132" cy="62" r="3.2" fill="var(--zzm-accent,#A6402F)"></circle>
        <circle cx="186" cy="22" r="2.4" fill="#FFFFFF"></circle>
        <circle cx="214" cy="52" r="2.4" fill="#FFFFFF"></circle>
      </svg>
      <div
        style="
          position: absolute;
          top: 10px;
          left: 11px;
          font-family: var(--zzm-mono);
          font-size: 10px;
          letter-spacing: 2px;
          padding: 3px 7px;
          border-radius: 4px;
          background: rgba(0, 0, 0, 0.55);
          color: rgba(255, 255, 255, 0.82);
        "
      >
        01
      </div>
    </div>
    <div style="padding: 16px 18px 17px">
      <div style="font-size: 16px; font-weight: 650">Obsidian 知识管理</div>
      <div style="margin-top: 6px; font-size: 13px; line-height: 1.65; color: #72726e">
        从零搭建一套以你为中心、能用十年的知识管理系统。
      </div>
      <div style="margin-top: 10px; font-size: 11.5px; color: #a2a29c">
        适合 · 刚开始整理数字笔记的知识工作者
      </div>
      <div style="margin-top: 13px; display: flex; align-items: center; gap: 8px">
        <span style="font-family: var(--zzm-mono); font-size: 10.5px; color: #8b8b85">
          6 系列 · 67 节
        </span>
        <span style="flex: 1"></span>
        <span
          style="
            font-size: 12px;
            font-weight: 600;
            color: var(--zzm-accent, #a6402f);
            white-space: nowrap;
          "
        >
          免费试 3 节 →
        </span>
      </div>
    </div>
  </div>
</div>
```

### 样张 · 骨架态

React：

```jsx
import { CourseCard } from './components/v4/CourseCard.jsx'

export function Loading() {
  return (
    <div style={{ width: 300 }}>
      <CourseCard loading />
    </div>
  )
}
```

HTML（构建时由上面的 React 渲染得到，可直接粘贴）：

```html
<div style="width: 300px">
  <div
    style="
      border: 1px solid rgba(0, 0, 0, 0.09);
      border-radius: 16px;
      background: #ffffff;
      overflow: hidden;
    "
  >
    <div
      style="aspect-ratio: 16/9; background: #131316; position: relative; overflow: hidden"
    ></div>
    <div style="padding: 16px 18px 17px">
      <div class="zzm-skel" style="width: 62%; height: 16px; border-radius: 8px"></div>
      <div
        class="zzm-skel"
        style="width: 92%; height: 13px; border-radius: 8px; margin-top: 6px"
      ></div>
      <div
        class="zzm-skel"
        style="width: 40%; height: 11.5px; border-radius: 8px; margin-top: 10px"
      ></div>
      <div style="margin-top: 13px; display: flex; align-items: center; gap: 8px">
        <div class="zzm-skel" style="width: 86px; height: 10.5px; border-radius: 8px"></div>
        <span style="flex: 1"></span>
        <div class="zzm-skel" style="width: 58px; height: 12px; border-radius: 8px"></div>
      </div>
    </div>
  </div>
</div>
```

## 属性

| 属性 | 取值 | 默认 | 说明 |
|---|---|---|---|
| `course` | { num, name, intro, aud, cover?, art: { pl, dt } } | — | art 是星座线稿：pl 折线、dt 圆点；颜色 "@" 表示品牌朱 |
| `meta` | string | — | 左下 mono 元数据，如「6 系列 · 67 节」 |
| `cta` | string | '进入课程 →' | 右下动作文案 |
| `ctaColor` | string | '#161616' | 动作文案颜色 |
| `onClick` | () => void | — | 整卡点击 |
| `loading` | boolean | false | 骨架态（同一段布局） |

## 铁律

- ✓ 要：封面按上传原图呈现，不叠蒙层
- ✗ 不要：为了一行小字压暗整幅封面
- ✓ 要：编号用深色小底自持可读性
- ✗ 不要：用 textShadow 救浅字——白底海报上一样糊

## 本页用到的 CSS

按样张里出现的类名，从源文件原样裁出（完整版见 zzm.css）：

```css
/* tokens.css · 用到的令牌 */
:root {
  --zzm-accent: #A6402F;
  --zzm-mono: ui-monospace, "SF Mono", Menlo, monospace;
}

/* base.css */

.zzm-v4 .zzm-hovercard { transition: all .16s ease; }

.zzm-v4 .zzm-hovercard:hover {
  transform: translateY(-3px);
  border-color: rgba(0, 0, 0, .3) !important;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .07);
}

.zzm-v4 .zzm-skel {
  position: relative;
  overflow: hidden;
  background: #EFEFEC;
  border-radius: 8px;
}

.zzm-v4 .zzm-skel::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .65), transparent);
  animation: zzmShimmer 1.4s ease infinite;
}

/* keyframes */
@keyframes zzmShimmer { 100% { transform: translateX(100%) } }
```

---

上一页：[卡片与卡链](https://ui.zhaozimin.cn/components/card.md) · 下一页：[系列卡](https://ui.zhaozimin.cn/components/series-card.md) · 全站目录：https://ui.zhaozimin.cn/llms.txt
