开发预览 更新于 2026-05-10

纯 HTML / JS 用法

没有构建工具、没有 Vue、没有 React 的传统 HTML+JS 项目,也能直接套用础件的 CSS 类拿到 90% 的视觉。

础件的设计是 CSS 优先:所有视觉表现都来自一份 stylesheet 和 cf-* 类名,组件源码只是把这些 class 拼好的薄壳。框架是可选的——你可以只引入一份 CSS 文件,在传统 jQuery / Bootstrap 时代的 HTML 项目里用 <button class="cf-btn cf-btn--primary"> 直接拿到所有样式。

引入 CSS

只需要两个文件:

<!doctype html>
<html lang="zh-CN" data-theme="light">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <!-- 1. design tokens(颜色、间距、字号、阴影、密度) -->
    <link rel="stylesheet" href="https://unpkg.com/@chufix-design/tokens/src/tokens.css" />
    <!-- 2. 所有组件的 class 样式(聚合包) -->
    <link rel="stylesheet" href="https://unpkg.com/@chufix-design/vue/dist/style.css" />
    <title>础件 demo</title>
  </head>
  <body>

  </body>
</html>

没发布 npm 之前,你也可以把 @chufix-design/tokens/src/tokens.css@chufix-design/vue/dist/style.css(构建后的)拷到自己项目里直接 link。

切主题:把 <html> 上的 data-theme 改成 dark-cool / dark-warm / light 任意一个就行。 切密度:再加 data-density="compact"

直接能用的组件(CSS-only · 不需要 JS)

下面这些组件不带交互逻辑,纯靠 class 描述外观,写好 HTML 就有效果:

Button 按钮

<button class="cf-btn cf-btn--primary">主要</button>
<button class="cf-btn cf-btn--secondary">次要</button>
<button class="cf-btn cf-btn--tertiary">三级</button>
<button class="cf-btn cf-btn--ghost">幽灵</button>
<button class="cf-btn cf-btn--danger">危险</button>
<button class="cf-btn cf-btn--primary cf-btn--lg">大号</button>
<button class="cf-btn cf-btn--primary" disabled>禁用</button>
<button class="cf-btn cf-btn--primary is-loading">加载中</button>

Input 输入框

cf-input 是包裹 label,cf-input__native 是真正的 <input>

<label class="cf-input cf-input--outline cf-input--md">
  <input class="cf-input__native" type="text" placeholder="请输入" />
</label>

<label class="cf-input cf-input--filled cf-input--md">
  <span class="cf-input__prefix">@</span>
  <input class="cf-input__native" type="email" placeholder="邮箱" />
</label>

Card 卡片

<article class="cf-card cf-card--elevated">
  <div class="cf-card__header">标题</div>
  <div class="cf-card__body">这里是卡片正文。</div>
  <div class="cf-card__footer">
    <button class="cf-btn cf-btn--primary cf-btn--sm">确认</button>
  </div>
</article>

cf-card--outlined / cf-card--elevated / cf-card--filled 三种变体。

Tag / Badge / Avatar

<span class="cf-tag cf-tag--soft cf-tag--primary">标签</span>
<span class="cf-tag cf-tag--solid cf-tag--success">成功</span>
<span class="cf-tag cf-tag--outline cf-tag--danger">危险</span>

<span class="cf-badge cf-badge--danger">5</span>
<span class="cf-badge cf-badge--dot cf-badge--success"></span>

<span class="cf-avatar cf-avatar--md">CQ</span>
<span class="cf-avatar cf-avatar--lg cf-avatar--circle">
  <img src="/me.jpg" alt="" />
</span>

Alert 警示

<div class="cf-alert cf-alert--info cf-alert--soft">
  <div class="cf-alert__body">
    <div class="cf-alert__title">一条信息</div>
    <div class="cf-alert__content">这是一段补充说明。</div>
  </div>
</div>

<div class="cf-alert cf-alert--success cf-alert--solid">
  <div class="cf-alert__body">保存成功</div>
</div>

Skeleton 骨架屏

<span class="cf-skeleton cf-skeleton--text" style="width: 200px;"></span>
<span class="cf-skeleton cf-skeleton--circle"></span>
<span class="cf-skeleton cf-skeleton--rect" style="width: 100%; height: 80px;"></span>

Checkbox / Radio / Switch(HTML 原生 + class)

<label class="cf-checkbox cf-checkbox--md">
  <input type="checkbox" class="cf-checkbox__input" />
  <span class="cf-checkbox__box"></span>
  <span class="cf-checkbox__label">同意条款</span>
</label>

<label class="cf-radio cf-radio--md">
  <input type="radio" name="r" class="cf-radio__input" />
  <span class="cf-radio__dot"></span>
  <span class="cf-radio__label">选项 A</span>
</label>

<label class="cf-switch cf-switch--md">
  <input type="checkbox" class="cf-switch__input" />
  <span class="cf-switch__track"></span>
</label>

需要 JS 的组件

下面这些组件包含状态切换或位置计算,纯 CSS 不够用。两条路

路径 A:用 Vue 3 的 ESM CDN 引一下

如果项目本身没构建工具但你又能接受加一行 <script type="module">,用 importmap 引 Vue 3 + @chufix-design/vue,跟用 jQuery 没区别:

<script type="importmap">
{
  "imports": {
    "vue": "https://esm.sh/vue@3",
    "@chufix-design/vue": "https://esm.sh/@chufix-design/vue@latest"
  }
}
</script>

<div id="app">
  <cf-button @click="show">点击</cf-button>
  <cf-modal v-model:open="open" title="Hello"><p>来自础件</p></cf-modal>
</div>

<script type="module">
  import { createApp, ref } from 'vue';
  import { CfButton, CfModal } from '@chufix-design/vue';

  createApp({
    components: { CkButton: Button, CkModal: Modal },
    setup() {
      const open = ref(false);
      return { open, show: () => (open.value = true) };
    },
  }).mount('#app');
</script>

注意:@chufix-design/vue 包发布到 npm 后这条 esm.sh 链接才能用,未发布前先把 dist/index.js 自己 host 一份。

路径 B:自己写一段最小 vanilla JS 兜底

Modal / Tooltip / Toast 这种组件的 CSS 已经把视觉做好,行为只需要几行 JS 控制 class 切换:

<button id="open" class="cf-btn cf-btn--primary">打开</button>
<div id="modal" class="cf-modal" data-state="closed">
  <div class="cf-modal__backdrop"></div>
  <div class="cf-modal__panel cf-modal__panel--md">
    <header class="cf-modal__header">
      <h2 class="cf-modal__title">标题</h2>
      <button class="cf-modal__close" data-close>×</button>
    </header>
    <div class="cf-modal__body">正文。</div>
  </div>
</div>

<script>
  const m = document.getElementById('modal');
  document.getElementById('open').onclick = () => m.dataset.state = 'open';
  m.querySelectorAll('[data-close], .cf-modal__backdrop').forEach((el) =>
    el.addEventListener('click', () => (m.dataset.state = 'closed'))
  );
</script>

CSS 里 .cf-modal[data-state='open'] 已经处理了显示/隐藏与动画,只要把 data-state'open''closed' 之间切换就行。Tooltip 同理:JS 控制 display: block,位置可以用 getBoundingClientRect() 算。

不带 build 工具的最小可运行示例

把上面的全部组合到一个 index.html,浏览器双击就能开:

<!doctype html>
<html lang="zh-CN" data-theme="dark-cool">
  <head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="https://unpkg.com/@chufix-design/tokens/src/tokens.css" />
    <link rel="stylesheet" href="https://unpkg.com/@chufix-design/vue/dist/style.css" />
    <title>础件 vanilla demo</title>
    <style>
      body { padding: 32px; max-width: 720px; margin: 0 auto; }
      .row { display: flex; gap: 8px; margin: 16px 0; flex-wrap: wrap; }
    </style>
  </head>
  <body>
    <h1>础件 · 纯 HTML 演示</h1>

    <h2>按钮</h2>
    <div class="row">
      <button class="cf-btn cf-btn--primary">主要</button>
      <button class="cf-btn cf-btn--secondary">次要</button>
      <button class="cf-btn cf-btn--tertiary">三级</button>
      <button class="cf-btn cf-btn--ghost">幽灵</button>
      <button class="cf-btn cf-btn--danger">危险</button>
    </div>

    <h2>表单</h2>
    <label class="cf-input cf-input--outline">
      <input class="cf-input__native" type="text" placeholder="昵称" />
    </label>

    <h2>卡片</h2>
    <article class="cf-card cf-card--elevated">
      <div class="cf-card__header">项目设置</div>
      <div class="cf-card__body">础件可以零依赖跑在传统 HTML 项目里。</div>
      <div class="cf-card__footer">
        <button class="cf-btn cf-btn--primary cf-btn--sm">保存</button>
      </div>
    </article>

    <h2>状态条</h2>
    <div class="cf-alert cf-alert--success cf-alert--soft">
      <div class="cf-alert__body">
        <div class="cf-alert__title">已就绪</div>
        <div class="cf-alert__content">不需要 npm,不需要 webpack。</div>
      </div>
    </div>
  </body>
</html>

class 速查表

组件容器 class关键修饰
Buttoncf-btn--primary / --secondary / --tertiary / --ghost / --danger--sm / --lg--pill / --square
Inputcf-input + 内部 cf-input__native--outline / --filled / --ghost--sm / --lg
Textareacf-textarea + 内部 cf-textarea__native同上
Cardcf-card--outlined / --elevated / --filled
Tagcf-tag--solid / --soft / --outline × --primary/success/warning/danger/info/neutral
Badgecf-badge--danger/--success 等 tone;--dot
Avatarcf-avatar--sm/md/lg/xl--circle/--square
Alertcf-alert--info/success/warning/error × --soft/outline/solid
Skeletoncf-skeleton--text/circle/rect
Checkboxcf-checkbox + 内部 cf-checkbox__input + cf-checkbox__box--sm/md/lg
Radiocf-radio + 内部 cf-radio__input + cf-radio__dot--sm/md/lg
Switchcf-switch + 内部 cf-switch__input + cf-switch__track--sm/md/lg
Tabscf-tabs + cf-tabs__list + cf-tabs__tab--line/segmented/pill;激活项加 is-active

反馈与讨论

纯 HTML / JS 用法 的讨论

0
0 / 600
一键发送
正在加载评论...