Design System
Cerne v0.1

一个从零构建、零外部依赖的完整设计系统

Cerne 是一个自包含的 CSS + JS 框架 —— 没有 CDN,没有 jQuery,生产环境中 不需要强制构建。它的设计目标是用同一套 令牌与组件系统服务多个领域:管理仪表盘、 学习环境、管理系统、教室预约和博客。

ITCSS + CUBE CSS 工具优先 + 组件 原生深色模式 默认无障碍 零依赖
为什么会有 Cerne

为现代 Web 开发时代打造的强大工具

Cerne 目前是 0.1 版本 —— 一个从零构建的完整设计系统, 目的很简单:为每个人提供一个快速、稳健且免费的基础, 把系统从图纸变成上线产品,不依赖 CDN,不需要许可证,没有供应商锁定, 也没有付费墙。开源,人人可用,永远如此。

v0.1 已经具备的能力

  • 40 多个生产级组件 —— 应用外壳、数据表、日历、图表、聊天、视频播放器、模态框、高级表单等等。
  • 43 个完整示例,可直接复制使用:仪表盘、电商、流媒体、网页邮箱、社交网络、新闻门户、LLM 聊天、智能电视……
  • 零外部依赖 —— 没有 jQuery,没有 CDN,生产环境不需要强制构建。双击 HTML 文件即可打开。
  • 原生深色模式,自动遵循 prefers-reduced-motion/prefers-color-scheme
  • 真正的 RTL 支持,基于逻辑属性实现 —— 不是镜像 hack。
  • 每个交互组件默认遵循 WCAG 2.1 AA 无障碍标准
  • 真正的国际化 —— 168 个示例页面翻译为中日韩文、阿拉伯语、印地语和俄语,不只是界面文案。
  • 真正的现代 CSS —— 容器查询、层叠层、color-mix()clamp(),以及通过 data-density 配置的密度。

标注为 v0.1 是一种选择,而非局限:核心部分已经足够稳固,并且已在上方 43 个示例中真实使用,但项目仍在公开持续演进 —— 每个 新版本都会增加更多基础能力、更多语言、更多组件,同时不破坏已有内容。

RV
Ricardo Cezar Volert 巴西 巴拉那州 库里蒂巴

Cerne 的创建者与维护者。整个框架 —— 令牌、组件、43 个示例以及 地区变体 —— 由 Ricardo 设计,并与 AI(Anthropic 的 Claude)协作构建,目标是为正在构建下一代 Web 系统的人们留下一个优秀、开放、免费的工具。

安装

dist/ 中已编译的文件复制到你的项目中并直接引用即可。使用该框架不需要任何构建步骤。

<link rel="stylesheet" href="dist/css/cerne.css">

<!-- 放在 body 末尾:经典脚本(不要用 type="module"),用于暴露 window.Cerne -->
<script src="dist/js/cerne.js"></script>

为避免 JS 加载前出现主题闪烁,请在 <head> 中、CSS 之前 加入以下代码:

<script>
  var t = localStorage.getItem('cerne-theme');
  if (t) document.documentElement.setAttribute('data-theme', t);
</script>

颜色

11 个色阶的基础调色板 + 语义层(--cerne-color-primary-hover-active-subtle……),会在浅色和深色 主题之间自动切换取值。下方数值都 实时读取自已编译的 CSS —— 永远不会与本文档脱节。

间距

以 4px 为基准的比例,通过 --cerne-space-* 以及 p-*m-*gap-* 工具类暴露。

排版

约 1.25 的模块化比例,默认字体为系统字体栈(零网络请求)。覆盖 --cerne-font-sans 即可使用自托管的自定义字体。

圆角与阴影

浅色/深色主题使用不同的层级配方 —— 深色阴影不会在深色背景上消失。

Radius

阴影

栅格

基于 CSS Grid 的经典 .row/.col-* API,加上带响应式前缀 md:lg:.grid-cols-* / .col-span-* 工具类。

<div class="row">
  <div class="col-12 col-md-4">...</div>
  <div class="col-12 col-md-4">...</div>
  <div class="col-12 col-md-4">...</div>
</div>

应用外壳

面向仪表盘的核心基础组件:通过 grid-template-areas 实现侧边栏 + 顶部栏 + 主内容区,在 lg 断点以下折叠为离屏面板。本页面本身就使用 .app-shell

<div class="app-shell" id="app-shell">
  <div class="app-shell__backdrop"></div>
  <aside class="app-shell__sidebar">...</aside>
  <header class="app-shell__topbar">...</header>
  <main class="app-shell__main">...</main>
</div>

按钮

每种语义颜色都有实心、描边和幽灵三种变体,另有尺寸和加载状态。

<button class="btn btn-primary">主要</button>
<button class="btn btn-outline-primary">描边</button>
<button class="btn btn-ghost-primary">幽灵</button>

表单

样式化的原生控件,通过 data-cerne-validate(Constraint Validation API)实现校验,并可通过属性自定义错误信息。

<form data-cerne-validate novalidate>
  <div class="form-group">
    <label class="form-label" for="email">电子邮箱</label>
    <input class="form-control" type="email" id="email" required
      data-error-required="请填写电子邮箱。">
    <span class="form-error"></span>
  </div>
</form>

更多表单

浮动标签、带强度提示和可见性切换的密码输入、OTP 验证码、可清除的搜索框、滑块、标签输入、组合框、可选卡片、分段选择器、拖拽上传和字符计数器 —— 覆盖从登录到结账的任何流程。

强度:
方向键导航,回车选择,Esc 关闭。搜索词会以 <mark> 高亮显示。
0/140
将文件拖到此处,或点击选择
<div class="form-floating">
  <input class="form-control" placeholder=" " id="name">
  <label for="name">姓名</label>
</div>

<div class="otp-input" data-cerne-otp>
  <input class="otp-digit"> <input class="otp-digit"> ...
</div>

<div class="tags-input" data-cerne-tags-input>
  <input type="text" placeholder="输入标签...">
</div>

<div class="segmented" role="tablist" data-cerne-segmented>
  <button type="button" class="segmented-item is-active" role="tab">30 天</button>
  <!-- ... -->
</div>

<div class="file-drop" data-cerne-file-upload data-cerne-file-list="#file-list">
  <input type="file" multiple>
  <span>将文件拖到此处,或点击选择</span>
</div>
<div class="file-list" id="file-list"></div>

卡片

今日预约 24 较昨日 +12%
卡片标题
卡片内容,示例文本。

媒体

.carousel(每次一张幻灯片,带圆点和可选自动播放)和 .shelf(支持横向滚动、RTL 友好的一行卡片)——分别用于机构门户主视觉区域和流媒体风格的目录。

轮播(data-cerne-carousel-autoplay

货架(悬停鼠标显示箭头)

日落山景插画
抽象人像插画
黑白日落山景插画
抽象人像插画
日落山景插画
<div class="carousel" data-cerne-carousel data-cerne-carousel-autoplay="5000">
  <div class="carousel-track">
    <div class="carousel-slide">...</div>
  </div>
  <button data-cerne-carousel-prev>‹</button>
  <button data-cerne-carousel-next>›</button>
  <div class="carousel-dots"></div>
</div>

<div class="shelf" data-cerne-shelf>
  <button data-cerne-shelf-prev>‹</button>
  <div class="shelf-track">
    <div class="shelf-item"><img src="poster.jpg" alt="..." /></div>
  </div>
  <button data-cerne-shelf-next>›</button>
</div>

视频

Cerne.VideoPlayer —— 在现有视频标记之上做渐进增强 (不强制使用自己的 HTML):播放/暂停、点击跳转、音量、速度控制。在没有真实 <video> 元素时(如下方示例)以"模拟时钟"运行,当你传入 [data-video-element] 时则镜像原生 <video>(MP4、通过 hls.js 的 HLS……)—— 真正的自适应流媒体分发由实现方自行负责, 超出了 CSS/JS 框架的职责范围。

0:00 / 0:00
<div class="player" id="player" data-duration="196">
  <button data-video-toggle>▶</button>
  <div class="player-controls">
    <div class="progress" data-video-seek><div class="progress-bar" data-video-fill></div></div>
    <button data-video-mute-toggle>🔊</button>
    <input type="range" data-video-volume min="0" max="1" step="0.05" value="1">
    <span data-video-time>0:00 / 0:00</span>
    <button data-video-speed="1.5">1.5x</button>
  </div>
</div>

<script>
  new Cerne.VideoPlayer(document.getElementById("player"), { duration: 196 });
</script>

完整示例:带 WebVTT 字幕的视频带"下一集"的流媒体live: true 直播, 以及带方向键导航的智能电视

表格与数据表

.table 用于静态表格;[data-cerne-datatable] 在完全无依赖的情况下添加客户端排序、搜索和分页。

姓名 课程 进度
Marina Silva计算机网络92%
Diego Souza数据库78%
Ana Beatriz算法65%
Lucas Pereira计算机网络40%
Juliana Melo操作系统88%
Rafael Costa数据库55%

编辑内容

分栏、重点提示框、带解释性注释的文字高亮标记,以及阅读进度条 —— 用于博客、新闻门户或 .prose 内的任何长文本。顺便看一下屏幕顶部:菜单上方那条彩色细线就是 .reading-progress,正在追踪这个文档页面本身的滚动进度。

提示框(.callout

另请阅读
指向另一篇相关文章的链接。
正文中间突出显示的提醒或更正说明。
对上方段落中用 <mark> 标记的术语的解释性说明 —— 类似新闻门户"术语解释"/"AI 解读"的风格。

文字高亮标记(<mark data-cerne-reveal="mark">)+ 术语解释框 —— 当术语进入视口时,高亮颜色会 从左到右"染上"(在 dir="rtl" 下则相反),而不是直接完整显示。

报告人强调,新的监管框架改变了全体会议的审批流程。

监管框架是指通过法律或法令制定或修改的、管理特定行业的一整套规则。

文字分栏(.columns-2 / .columns-3,位于 .prose 内)

第一栏:文字竖直流动,并换到下一栏。

第二栏:适合放置简短的要点列表、术语表或引文 —— 在 md 断点以下会折叠为单栏。

<p>新的 <mark data-cerne-reveal="mark">监管框架</mark> 改变了审批流程。</p>
<div class="callout callout-glossary">
  <svg class="callout-icon"><use href="sprite.svg#icon-search"></use></svg>
  <div class="callout-body"><strong>监管框架</strong> 是……</div>
</div>

<div class="columns-2"><p>...</p><p>...</p></div>

<div class="reading-progress"><div class="reading-progress-bar"></div></div>

完整的实际应用示例请见博客文章新闻门户文章

模态框与离屏面板

侧边面板

用于筛选、购物车或快速查看详情,无需离开当前页面。

提示与轻提示

成功
您的预约已确认。
注意
该时段名额即将约满。

日历与预约

用于教室预约的每周时间表网格 —— 完整示例见教室预约

已确认 待确认 我的预约

图表

无依赖的迷你 SVG 图表(Cerne.Chart.bar/line/donut)。

更多组件

列表组、加载指示器、评分和定价卡片 —— 用于商店、机构门户、营销页面和目录。

概览 设置 通知
4.2 (128)
<div class="rating">
  <svg class="is-filled"><use href="sprite.svg#icon-star"></use></svg>
  <!-- ... -->
  <span class="rating-count">4.2 (128)</span>
</div>

图片

裁切(object-fit/aspect-ratio)、CSS 滤镜 (grayscaleblur-*brightness-*……),以及 处理配方(悬停缩放、图片说明遮罩、双色调、有机裁切)—— 全部为纯 CSS,无需图像处理库。本页面中的照片 均为自制 SVG 插画,以保证本文档 100% 自包含。

裁切与比例

.aspect-video/.aspect-square/.aspect-portrait 固定容器比例;.object-cover 在不变形的情况下填满容器。

日落山景插画 aspect-video
抽象人像插画 aspect-square
日落山景插画 aspect-portrait
<img class="aspect-video object-cover rounded-md" src="foto.jpg" alt="..." />

滤镜

原子化、可组合的类(class="grayscale contrast-125")—— 每个类 控制单一的 filter 属性。

无滤镜 无滤镜
灰度滤镜 grayscale
棕褐色滤镜 sepia
blur-sm 滤镜 blur-sm
brightness-50 滤镜 brightness-50
brightness-150 滤镜 brightness-150
contrast-150 滤镜 contrast-150
saturate-0 滤镜 saturate-0
saturate-200 滤镜 saturate-200
hue-rotate-90 滤镜 hue-rotate-90
反色滤镜 invert
灰度与 contrast-125 组合滤镜 grayscale contrast-125
<img class="grayscale" src="foto.jpg" alt="..." />
<img class="sepia" src="foto.jpg" alt="..." />
<img class="blur-sm" src="foto.jpg" alt="..." />
<img class="brightness-150 contrast-125" src="foto.jpg" alt="..." />

处理效果

配方类(每个类包含多个属性,如 .bg-aurora),用于 常见的带图卡片样式。

日落山景插画
.img-hover-zoom — 悬停鼠标查看
日落山景插画
山谷步道
.img-scrim — 照片上清晰可读的说明文字
抽象人像插画
.img-duotone
抽象人像插画
.img-blob — 有机裁切
<div class="img-hover-zoom rounded-lg aspect-video">
  <img src="foto.jpg" alt="..." />
</div>

<div class="img-scrim rounded-lg aspect-video">
  <img src="foto.jpg" alt="..." />
  <div class="img-scrim-caption"><strong>山谷步道</strong></div>
</div>

<div class="img-duotone aspect-square"><img src="foto.jpg" alt="..." /></div>
<div class="img-blob aspect-square"><img src="foto.jpg" alt="..." /></div>

现代趋势

便当格布局、聚光灯卡片、渐变边框、辉光、颗粒/噪点、极光、跑马灯、悬浮操作按钮和阅读进度条 —— 当下流行的视觉技巧,可直接用于任何应用。

便当格布局 苹果风格的非对称网格,悬停时带聚光灯效果。
普通项目
渐变边框
带渐变边框的卡片

跑马灯(悬停暂停)

Design System 无障碍 Dark mode RTL Design System 无障碍 Dark mode RTL
这个区块使用了 data-cerne-reveal —— 滚动页面即可看到动画效果。
<div class="bento-grid">
  <div class="bento-item bento-span-2 card-spotlight">...</div>
  <div class="bento-item">...</div>
</div>

<div data-cerne-reveal="up">滚动页面时出现</div>
<span data-cerne-count-up="1284" data-cerne-count-up-format>0</span>

工具类变体与地区适配

在任何颜色/阴影/透明度工具类前加上 hover:focus:focus-visible:active:disabled:focus-within:dark:,还有纯 CSS 实现的 group-hover:/peer-checked: (无需 JS —— .group/.peer 只是标记)、容器查询(.cq + cq-md:),以及让 框架适配任何地区 UI 风格的基础能力 —— 不只是西方风格。

把鼠标悬停在这张卡片上

旁边的按钮使用了 group-hover:opacity-100 —— 只有当父元素.group)处于悬停状态时才会出现。

<html> 上设置 data-density="compact",一次性成倍调整整个间距比例 —— 更接近 东亚门户网站/电商常见的高信息密度模式。.break-keep.write-vertical 分别处理 CJK 文本的换行和竖排;--cerne-line-height-base:lang(ar|he|hi|bn|ta|te|th) 下会自动变得更宽松。9 个示例页面(商店/新闻/仪表盘 × CJK/RTL/南亚)请见 查看示例

<div class="group card">
  <button class="opacity-25 group-hover:opacity-100 hover:bg-primary">...</button>
</div>

<div class="cq">
  <div class="flex-col cq-md:flex-row">...</div> <!-- reage ao espaço do .cq, não do viewport -->
</div>

<html data-density="compact"> <!-- ou "spacious" -->

图标

87 个自制图标,收录在单个 SVG 精灵图(dist/icons/sprite.svg)中,通过 <use> 引用。

无障碍

目标是达到 WCAG 2.1 AA 级 —— 这是国际通用标准,与国家或语言无关 —— 而不是某个司法辖区专属的工具或认证标志。

  • 每个交互组件都有可见的 :focus-visible 状态和键盘导航(标签页/菜单中的方向键、Esc 关闭、模态框中锁定 Tab、标签页中的漫游 tabindex)。
  • prefers-reduced-motionprefers-color-scheme 会自动生效,无需任何额外配置。
  • 实心背景上的文字颜色都是按 AA 标准挑选的 —— 特别是 warning/info,因为白色文字对比度不足,所以改用深色文字。
  • 表单将标签(for/id)、错误信息与 aria-invalid 关联起来;错误状态从不仅依赖颜色来表达。
  • 当前激活的导航链接会带有 aria-current="page";地标元素(mainnavaside)和每页唯一的 <h1> 为屏幕阅读器构建了清晰的文档结构。
  • 图片/图表的描述性替代文本由使用该框架的人负责编写 —— Cerne 无法替你自动生成。 巴西的 #PraCegoVer 惯例(在图片说明/alt 中描述图片本身)是一个好习惯,但真正重要的是 写出真正描述图片内容、而不是重复显而易见信息的 alt 文本 —— 这一点适用于任何语言。
  • 关于 VLibras 和手语翻译工具:它们被有意排除在框架之外,因为它们依赖 外部脚本(第三方 CDN),且只适用于特定语言/国家 —— 这既违背"零外部依赖",也违背"国际化 框架"的原则。正确且通用的基础是做好语义化 HTML + ARIA,全世界任何辅助技术都已经能够解读它; 具体的翻译组件可以在有意义的情况下,按项目单独叠加上去。
  • 真正的 RTL 支持:组件使用逻辑属性(inset-inline-startmargin-inline-endtext-align: start……)而不是固定的 left/right,因此只需在 <html> 上设置 dir="rtl",即可镜像侧边栏、下拉菜单、标签页、表单和导航 —— 无需额外 CSS。实时查看:
带侧边强调线的卡片

边框跟随文字起始方向,而不是固定的一侧。

<html lang="ar" dir="rtl">
  <!-- 侧边栏、下拉菜单、标签页、表单……全部自动镜像 -->

隐私与同意

通用的 Cookie/同意横幅 —— 与 GDPR(欧盟)、LGPD(巴西)和 CCPA (加利福尼亚州)相同的"必要 / 分析 / 营销"模式,不依赖任何第三方同意管理平台。

<div class="consent-banner" data-cerne-consent hidden role="region" aria-label="Cookie 提示">
  <p class="consent-banner-text">我们使用必要的 Cookie……</p>
  <div class="consent-banner-actions">
    <button data-cerne-consent-customize
      data-cerne-toggle="modal" data-cerne-target="#consent-preferences">自定义</button>
    <button data-cerne-consent-reject>拒绝非必要项</button>
    <button data-cerne-consent-accept>全部接受</button>
  </div>
</div>

<!-- Cerne.Consent.get() / .set({analytics, marketing}) / .reset() -->

选择结果保存在 localStorage 中(键名为 cerne-consent),从不写入第三方 Cookie,也从不发送到任何 地方 —— 你的后端如何处理 Cerne.Consent.get() 的结果,由你自己决定。只有当页面中 包含 [data-cerne-consent] 元素时,横幅才会自动出现;本文档为了不打扰阅读体验,故意省略了它 —— 完整 示例请见博客商店机构门户

完整示例

42 个完全用 Cerne 构建的页面,涵盖管理仪表盘、教学、管理、预约、内容、新闻门户、电商、机构网站、视频、社交网络、流媒体、对话式助手和作品集 —— 每一个都有各自的 CJK、RTL、南亚和俄罗斯变体,界面全部翻译完整(168 个地区页面,共约 210 个页面),可通过任意示例顶部的"地区变体"栏访问。

地区变体(CJK、RTL、南亚、俄罗斯)

上面每个示例的每个页面都有 CJK、RTL、南亚和俄罗斯这四个变体 —— 共 168 个 地区页面 —— 打开任意一个,使用顶部的"地区变体"栏即可在它们之间切换。CJK、RTL 和南亚 变体使用变体与地区化中描述的基础能力 —— data-density.break-keep/.write-verticaldir="rtl" 以及 按语言调整的 --cerne-line-height-base;俄罗斯变体在与原示例相同的从左到右结构上使用 lang="ru" 呈现俄语文本(不需要额外的逻辑属性,因为俄语在这方面 与葡萄牙语表现一致)。这 168 个页面都有完整翻译 —— 不仅是界面 (导航、按钮、表单、标签、空状态),还包括动态内容:产品名称与描述、 示例邮件(主题和正文)、搜索结果、视频/剧集标题与简介、 助手的示例对话,以及长文章/帖子正文,每个领域都为每种语言准备了 独立的示例数据副本(例如 store-data.cjk.browser.js / store-data.ru.browser.js)。 Cookie 横幅也已翻译;只有描述变体本身的少量页脚说明(以及人物的 专有名称)仍保留葡萄牙语,因为这些是给阅读 源码的人看的文档性文字,而非应用内容。

示例 CJK RTL 南亚 俄罗斯
管理仪表盘打开打开打开打开
学习环境打开打开打开打开
教师页面打开打开打开打开
管理 / CRUD打开打开打开打开
教室预约打开打开打开打开
博客打开打开打开打开
博客 — 文章打开打开打开打开
新闻门户打开打开打开打开
新闻门户 — 文章打开打开打开打开
电商商店打开打开打开打开
电商商店 — 商品打开打开打开打开
实验室网站打开打开打开打开
机构门户打开打开打开打开
研究小组网站打开打开打开打开
身份验证 — 登录打开打开打开打开
身份验证 — 注册打开打开打开打开
身份验证 — OTP 验证打开打开打开打开
404 错误打开打开打开打开
500 错误打开打开打开打开
视频平台打开打开打开打开
视频 — 观看打开打开打开打开
视频 — 播放列表打开打开打开打开
社交网络(信息流)打开打开打开打开
社交网络(个人主页)打开打开打开打开
流媒体 — 登录打开打开打开打开
流媒体 — 用户配置打开打开打开打开
视频流媒体打开打开打开打开
流媒体 — 详情页打开打开打开打开
流媒体 — 观看打开打开打开打开
流媒体 — 浏览打开打开打开打开
流媒体 — 直播打开打开打开打开
对话式助手(LLM)打开打开打开打开
作品集(便当格布局)打开打开打开打开
数据分析仪表盘打开打开打开打开
网页邮箱(Gmail 风格)打开打开打开打开
网页邮箱(Outlook 风格)打开打开打开打开
搜索引擎(极简)打开打开打开打开
搜索引擎(极简)— 结果打开打开打开打开
搜索引擎(密集门户)打开打开打开打开
搜索引擎(密集门户)— 结果打开打开打开打开
智能电视界面打开打开打开打开
智能电视 — 播放器打开打开打开打开
国际自适应注册表单 (已通过 JS 按国家自适应 —— 没有静态变体)