纯HTML+CSS组件库需具备明确边界、命名空间、设计令牌、响应式降级、语义化标签及无障碍支持;类名须带前缀如.c-button,结构自闭合,CSS用var(--c-space-md)等变量,禁用px和!important,模板用<template>或JS加载,按钮必须用<button>标签并处理焦点与表单提交。
纯 HTML + CSS 的组件库不是“写完就能用”的静态片段集合,而是需要明确边界、可预测行为、能被稳定引用的界面单元。它不靠框架运行时兜底,所以结构松散、样式泄漏、响应式断裂、语义缺失,是默认状态。
没有 Shadow DOM 时,CSS 泄漏是头号风险。所有组件级类名必须带前缀,比如 .c-button、.c-card__header、.c-modal--small,不能出现 .header 或 .content 这类泛化名。
每个组件的 HTML 结构需自闭合、可独立存在:
<div class="c-card"> <div class="c-card__header"><h3>标题</h3></div> <div class="c-card__body"><p>正文内容</p></div> <div class="c-card__footer"><button class="c-button">操作</button></div></div>
<div class="card"> —— 缺少命名空间,易与其他项目冲突<section> 单独包裹组件 —— 语义不准确,且无法通过类名定位样式作用域!important —— 它会破坏下游覆盖能力,让主题切换失效颜色、间距、圆角这些值不能硬编码在选择器里,得抽成 CSS 自定义属性,统一挂载在 :root 下:
立即学习“前端免费学习笔记(深入)”;
:root { --c-space-xs: 0.25rem; --c-space-sm: 0.5rem; --c-space-md: 1rem; --c-color-primary: #0066cc; --c-radius: 0.375rem;}
这样改主题只需覆盖变量,无需重写整套规则。同时,所有组件内距、字体大小必须用 rem 或 clamp(),禁用 px 固定值:
padding: var(--c-space-md); ✅font-size: clamp(1rem, 4vw, 1.25rem); ✅margin-left: 8px; ❌ —— 移动端缩放失效,DPR 不适配媒体查询也得收敛:只在组件自身文件里写断点,不要在全局 responsive.css 里批量干预组件表现 —— 否则某天删掉这个文件,所有组件就崩了。
纯静态环境(如 GitHub Pages、Netlify)不支持 PHP 的 include 或 Node 的模板引擎。常见错误是把 nav.html 当作可直接嵌入的片段,却忘了浏览器根本不解析 @@include 或 require()。
可行路径只有两条:
index.html 底部引入 js/nav-loader.js,里面用 fetch('components/nav.html') + insertAdjacentHTML 注入,但要注意 CSP 和首次渲染空白问题<template> 预置结构:每个组件写成 <template id="c-modal">...</template>,再由工厂函数 createModal({ title, content }) 克隆填充 —— 兼容性好,无网络请求,但需手动绑定事件别碰 document.write,它会清空整个页面;也别依赖构建工具生成 HTML —— 那就不是“轻量级 HTML 库”,而是“轻量级构建流程”的包装壳。
一个按钮组件如果用 <div class="c-button" onclick="..."> 实现,它就不是组件,是视觉模拟器。真实组件必须:
<button> 标签,支持空格/回车触发、焦点管理、disabled 属性原生生效<label for="id">,不能靠视觉对齐“假装有关联”role="dialog"、aria-modal="true"、焦点锁和 aria-labelledby 指向标题<nav> 包裹,内部链接用 <a href>,不要全用 <button> 冒充跳转这些不是“加个属性就完事”,它们决定了键盘用户能否完成任务、屏幕阅读器能否正确播报、搜索引擎如何理解交互意图。漏掉任意一条,组件在真实场景中就会失效。
最常被忽略的,是组件的“收口”动作:每个 <template> 是否清理了占位符?每个 fetch 加载是否处理了 404?每个 button 是否写了 type="button" 防止意外提交表单?这些细节不显眼,但决定了库能不能离手即用。