标签云必须用<ul>包裹,每个标签为<li>子元素,内含带data-weight属性的<a>或<span>,URL需encodeURIComponent编码。

标签云必须用 <ul> 包裹,不是 <div> 或一堆独立 <a>
标签云本质是“一组无序关键词”,语义上属于列表。用 <ul> 能让屏幕阅读器识别为可遍历列表,SEO 也能抓取每个 <li> 中的链接文本和权重属性;而 <div class="tag-cloud"> 套一堆 <a>,辅助技术读不出顺序,爬虫也当普通文本忽略。
常见错误现象:
- NVDA 或 VoiceOver 报 “no landmarks, no list found”
- Lighthouse 的 “Semantic HTML” 项扣分,尤其 “List elements” 条目失败
- W3C Validator 提示 “Element a not allowed as child of element div”(当
<a>直接塞进<div>)
data-weight 是标记权重的唯一合规方式,别用 class 或 style
权重信息必须通过 data-weight 属性声明,比如 <a href="/tag/js" data-weight="3">JavaScript</a>。这样 JS 可读取做归一化,CSS 可用属性选择器动态控制字号(如 a[data-weight="4"] { font-size: 1.6em; }),且不污染语义或样式逻辑。
为什么不能用 class:
立即学习“前端免费学习笔记(深入)”;
-
class="tag-large"是表现层描述,无法表达“这个词出现频次高”的业务含义 - 归一化时需重映射(比如把 0–100 的原始频次缩放到 1–4),class 名无法动态生成
- 后续想加权重排序、过滤或导出数据时,
data-属性天然支持 JS 获取,class 需正则解析
每个标签必须是 <li> 子元素,且内部只能是 <a> 或 <span>
<ul> 的直接子元素只能是 <li>,这是 HTML5 规范强制要求。每个 <li> 内推荐只放一个 <a>(带跳转)或 <span>(仅展示,如已选中的筛选项)。
典型结构示例:
<ul class="tag-cloud"> <li><a href="/tag/html" data-weight="4">HTML</a></li> <li><a href="/tag/css" data-weight="3">CSS</a></li> <li><span data-weight="2">JavaScript</span></li> </ul>
注意点:
- 不要在
<li>里套<div>或嵌套其他块级元素 - 禁用
float布局——用display: inline-flex或inline-block+vertical-align控制对齐 - 响应式字号优先用
clamp(0.8rem, 4vw, 1.6rem)或em,避免写死px
URL 参数必须 encodeURIComponent() 编码,否则空格和中文会出错
如果标签文字含空格、中文或特殊符号(如 C++),直接拼进 URL 会导致路由失败或 400 错误。必须用 JavaScript 对 href 值做编码:
const tag = "C++";
const encoded = encodeURIComponent(tag); // → "C%2B%2B"
const link = `/tag/${encoded}`;
服务端接收时也要对应解码(如 Node.js 用 decodeURIComponent())。漏掉这步,用户点击“人工智能”标签可能跳转成 /tag/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD 后被后端拒收,或前端路由匹配失败。
容易被忽略的地方:开发时用英文测试一切正常,上线后中文标签全 404——问题往往就卡在这行编码没做。



















