语义化面包屑必须用 nav + ol 结构,nav 需 aria-label="Breadcrumb",ol 内每个层级为 li,当前页用 aria-current="page";JSON-LD 需 @context 为 "https://schema.org",itemListElement 为含 position、name、item 的 ListItem 数组,URL 必须绝对且与 canonical 一致。
用 nav + ol 写语义化面包屑,不是 div 堆span
搜索引擎和屏幕阅读器靠 html 结构识别面包屑,只加 css 类名或 aria 属性没用。必须用符合规范的嵌套结构。
常见错误是写成:<div class="breadcrumb"><span>首页</span> > <span>分类</span>> <span>详情</span></div>——这在结构化数据里等于不存在。
- 根容器必须是
nav,并加上aria-label="Breadcrumb" - 内部必须用
ol(有序列表),每个层级是li,因为路径有明确先后顺序 - 当前页用
aria-current="page"标记,不能只靠样式变灰或加粗
正确示例:
<nav aria-label="Breadcrumb">
<ol>
<li><a href="/">首页</a></li>
<li><a href="/blog/">博客</a></li>
<li><a href="/blog/css/">CSS 技巧</a></li>
<li aria-current="page">HTML 面包屑</li>
</ol>
</nav>
JSON-LD 结构化数据怎么配才被 Google 识别
光有语义 HTML 不够,Google 更倾向用 JSON-LD 补充路径信息。但很多人把 @context 写错、URL 拼错,或者漏掉 itemListElement 数组结构,导致富摘要不出现。
-
@context必须是"https://schema.org",不能少https或拼成schmea -
itemListElement是数组,每个元素必须含@type: "ListItem"、position(从 1 开始)、name和item(完整 URL) - URL 必须绝对路径,且与页面实际
<link rel="canonical">一致,否则被判定为误导
简短 JSON-LD 示例(放在 <head> 里):
立即学习“前端免费学习笔记(深入)”;
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [{
"@type": "ListItem",
"position": 1,
"name": "首页",
"item": "https://example.com/"
},{
"@type": "ListItem",
"position": 2,
"name": "博客",
"item": "https://example.com/blog/"
},{
"@type": "ListItem",
"position": 3,
"name": "HTML 面包屑",
"item": "https://example.com/blog/breadcrumb-html/"
}]
}</script>
为什么面包屑在搜索结果里不显示富摘要
结构对了、JSON-LD 也贴了,但 Google Search Console 的「富摘要测试工具」仍报错或不渲染——大概率是这三个点卡住了。
- 页面未被 Google 爬取过新版本:改完后要等下次抓取,或手动在 Search Console 提交 URL
- JSON-LD 中某个
itemURL 返回 404 或重定向链过长(超过 5 跳) - 面包屑层级超过 10 级:Google 明确建议最多 10 层,超出部分会被截断,甚至整条忽略
检查时优先用 Google 的 Rich Results Test,别只信第三方结构化数据校验器。
动态页面怎么生成面包屑(React/Vue 场景)
静态路径好写,但 React Router 或 Vue Router 的动态路由(比如 /user/:id)需要运行时拼接,容易漏掉参数解析或 fallback 处理。
- 不要硬编码中文名,用路由元信息(如
route.meta.breadcrumb)或根据params.id异步查名称 - 当前页 name 不能为空字符串,否则 JSON-LD 会因
name缺失而失效 - 服务端渲染(SSR)时,确保 JSON-LD 在首屏 HTML 中已存在,而不是 JS 运行后才注入
Vue Router 示例(beforeEach 中):
// 路由定义里带 meta
{ path: '/user/:id', component: User, meta: { breadcrumb: '用户详情' } }
// 导航守卫中生成结构化数据
router.beforeEach((to, from, next) => {
const breadcrumb = to.matched.map(m => m.meta.breadcrumb || '首页')
// → 后续注入 JSON-LD 或更新 DOM
面包屑看着简单,但结构、数据、渲染三处任一出错,就等于白做。最常被跳过的其实是 URL 的绝对性和爬虫可见性——人眼看到的路径,和机器读到的,经常不是一回事。











