纯 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 | 关键修饰 |
|---|---|---|
| Button | cf-btn | --primary / --secondary / --tertiary / --ghost / --danger;--sm / --lg;--pill / --square |
| Input | cf-input + 内部 cf-input__native | --outline / --filled / --ghost;--sm / --lg |
| Textarea | cf-textarea + 内部 cf-textarea__native | 同上 |
| Card | cf-card | --outlined / --elevated / --filled |
| Tag | cf-tag | --solid / --soft / --outline × --primary/success/warning/danger/info/neutral |
| Badge | cf-badge | --danger/--success 等 tone;--dot |
| Avatar | cf-avatar | --sm/md/lg/xl;--circle/--square |
| Alert | cf-alert | --info/success/warning/error × --soft/outline/solid |
| Skeleton | cf-skeleton | --text/circle/rect |
| Checkbox | cf-checkbox + 内部 cf-checkbox__input + cf-checkbox__box | --sm/md/lg |
| Radio | cf-radio + 内部 cf-radio__input + cf-radio__dot | --sm/md/lg |
| Switch | cf-switch + 内部 cf-switch__input + cf-switch__track | --sm/md/lg |
| Tabs | cf-tabs + cf-tabs__list + cf-tabs__tab | --line/segmented/pill;激活项加 is-active |
反馈与讨论
纯 HTML / JS 用法 的讨论