☰
Oat UI 面包屑组件(Breadcrumb)完整指南:基于语义化 `<nav>` 与有序列表的零依赖导航层级
2026/10/12 1:45:32 网站建设 项目流程

【免费下载链接】oat

Ultra-lightweight, zero dependency, semantic HTML, CSS, JS UI library. ~10KB min+gz.

项目地址:https://gitcode.com/gh_mirrors/oat5/oat
点击查看免费下载

面包屑(Breadcrumb)是 Web 应用中帮助用户理解页面层级、快速回溯上级路径的基础导航组件。在 Oat UI 中,面包屑不依赖任何专用 CSS 类或 JavaScript,仅凭语义化<nav>、有序列表<ol>与aria-current="page"即可获得完整的样式与无障碍支持。读完本文你将掌握 Oat 面包屑的完整标记结构、与 Oat 布局工具类的组合方式,以及如何基于 Oat 的主题变量与源码机制进行样式定制与行为扩展。

一、组件概述:为什么面包屑不需要专用样式

Oat UI 是一款极简、零依赖、以语义化 HTML 为核心的 UI 库(README 将其定位为 "Ultra-lightweight, zero dependency, semantic HTML, CSS, JS UI library",整体约 10KB min+gz)。它的设计哲学是:语义标签与属性在默认情况下即被上下文感知地样式化,无需类名,从而减少标记中的类污染(见 README.md)。

面包屑组件正是这一理念的典型体现。在 breadcrumb.md 中,官方给出的完整用法是:

使用语义化的面包屑<nav>,配合有序列表,并用aria-current="page"标记当前激活项。

值得注意的是,仓库中并不存在src/css/breadcrumb.css这一专用样式文件。从 Makefile 中列出的 CSS 文件清单可以看出,Oat 没有为面包屑单独编写组件 CSS——面包屑的外观完全由基础层(00-base.css)与工具类层(utilities.css)组合呈现。这保证了组件以“零额外体积”的方式融入整体库,也正是“约 10KB”体积得以维持的原因之一。

二、基础用法:完整的标记结构

Oat 面包屑的标准标记如下(原样取自官方文档示例):

<nav aria-label="Breadcrumb"> <ol class="unstyled hstack" style="font-size: var(--text-7)"> <li><a href="#breadcrumbs" class="unstyled">Home</a></li> <li aria-hidden="true">/</li> <li><a href="#breadcrumbs" class="unstyled">Projects</a></li> <li aria-hidden="true">/</li> <li><a href="#breadcrumbs" class="unstyled">Oat Docs</a></li> <li aria-hidden="true">/</li> <li><a href="#breadcrumbs" class="unstyled" aria-current="page"><strong>Breadcrumb</strong></a></li> </ol> </nav>

拆解这段标记,可以提炼出四个核心要素:

元素 / 属性作用说明
<nav aria-label="Breadcrumb">语义容器用aria-label为辅助技术(屏幕阅读器)提供导航区标识,符合 WAI-ARIA 面包屑导航惯例
<ol>层级列表面包屑是“有序”的导航层级,使用有序列表从语义上表达祖先到当前页的顺序关系
<li aria-hidden="true">/</li>视觉分隔符分隔符对辅助技术隐藏,避免屏幕阅读器逐字朗读 “/”
aria-current="page"当前页标记告诉辅助技术与样式系统“这是当前所在页面”,是面包屑无障碍的核心属性

2.1 关键属性与可访问性细节

  • aria-current="page":这是面包屑可访问性的灵魂。它向屏幕阅读器宣告当前项对应的正是用户此刻所在的页面,避免用户被多层导航误导。原文档将其列为核心要求,实际项目中应只在一个面包屑中标记一项。
  • aria-hidden="true"分隔符:分隔符/是纯视觉装饰。若不隐藏,屏幕阅读器会将其作为文本朗读,产生“Home 斜杠 Projects 斜杠”式的噪音。
  • <strong>强调当前项:示例中用<strong>包裹当前项文本,从视觉与语义两个层面强化“当前所在位置”的提示,这是对aria-current的视觉补充。

三、样式原理:工具类与基础层的组合

面包屑的样式并非凭空而来,而是由 Oat 的工具类层与基础层协同完成。逐层拆解如下:

3.1.hstack——水平堆叠布局

.hstack定义在 utilities.css 中:

.hstack { display: flex; align-items: center; gap: var(--space-3); /* 0.75rem,元素间统一间距 */ flex-wrap: wrap; /* 窄屏自动换行,避免溢出 */ align-content: flex-start; height: auto; > * { margin: 0; /* 清除子元素默认外边距 */ } }

它让面包屑的每一项与分隔符沿水平方向排列,gap: var(--space-3)提供统一间隔,flex-wrap: wrap则保证在窄容器中面包屑可以折行而不破坏布局——这一特性在移动端尤其重要。--space-3的值定义在 01-theme.css 中,为0.75rem。

3.2.unstyled——去除默认列表与链接样式

.unstyled同样位于 utilities.css:

:is(ul, ol).unstyled { list-style: none; /* 去掉有序列表的默认序号(1. 2. 3.) */ padding: 0; /* 去掉列表默认左内边距 */ } a.unstyled { color: inherit; /* 继承父级文本颜色 */ text-decoration: none; /* 去掉下划线 */ &:hover { color: var(--primary); /* 悬停时变为主色 */ } }
  • 对<ol>使用class="unstyled",面包屑就不会显示默认的数字序号,padding: 0同时消除了浏览器为<ol>注入的左侧缩进(基础层 00-base.css 为列表设置了padding-inline-start: var(--space-6))。
  • 对每个链接使用class="unstyled",链接继承面包屑父级的文本颜色并去掉下划线,悬停时变为--primary主色,保持导航条式的低调观感。

3.3var(--text-7)——字号令牌

示例中通过内联样式style="font-size: var(--text-7)"设置字号。--text-7定义在 01-theme.css 中,值为0.875rem(14px),属于 Oat 字号刻度中偏小的档位,适合用作导航辅助信息。Oat 提供从--text-1到--text-8的完整字号刻度,面包屑通常选用--text-7或--text-6(1rem)。

3.4 为什么不直接写color: gray之类

Oat 全库以 CSS 变量驱动(见 customizing.md 中“几乎所有属性都定义为可覆写的 CSS 变量”)。因此示例使用var(--text-7)而非硬编码字号、悬停颜色引用var(--primary)而非写死色值——这保证了面包屑能自动适配主题与暗色模式(01-theme.css 通过color-scheme: light dark与light-dark()自动跟随系统明暗偏好)。

四、集成方式:把面包屑放进你的项目

面包屑组件纯由 HTML + 既有 CSS 构成,不需要引入任何额外的 JS(对比之下,Oat 的 tabs、dropdown、tooltip 等属于 WebComponent 型动态组件,才需要 src/js/index.js 打包的运行时)。这意味着你只需按 usage.md 的方式引入基础资源即可:

<link rel="stylesheet" href="oat.min.css"> <script src="oat.min.js" defer></script>

提示:纯静态的面包屑甚至可以不引入oat.min.js,但考虑到页面中通常还有其他交互组件,建议按需决定。若希望最小化体积,也可以依据 customizing.md 的“选择性引入”方案,只保留00-base.css、01-theme.css与utilities.css三个文件即可让面包屑完整工作。

面包屑同样可以直接放进官方文档站点的<demo>shortcode(demo.html)中实时预览,配合本地开发流程(cd docs && zola serve,见 usage.md)即可边改边看。

五、实战扩展:更多面包屑形态

5.1 带首页图标的面包屑

将分隔符换为 SVG 箭头、首页项换成图标,视觉上更贴近主流后台系统:

<nav aria-label="Breadcrumb"> <ol class="unstyled hstack" style="font-size: var(--text-7)"> <li><a href="#home" class="unstyled" aria-label="Home"> <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg> </a></li> <li aria-hidden="true">/</li> <li><a href="#projects" class="unstyled">Projects</a></li> <li aria-hidden="true">/</li> <li><a href="#docs" class="unstyled">Oat Docs</a></li> <li aria-hidden="true">/</li> <li><a href="#breadcrumb" class="unstyled" aria-current="page"><strong>Breadcrumb</strong></a></li> </ol> </nav>

注意:图标仅用于视觉提示,需通过aria-label提供等价文本、aria-hidden="true"屏蔽装饰性 SVG,确保辅助技术用户获得与视觉用户一致的信息。

5.2 深层级与可折叠

面包屑层级增多时,可以结合 Oat 的<details>/<summary>原生折叠能力(基础层未对其特殊处理,浏览器原生支持)做“中间层折叠”,或直接截断中间项、只保留“首页 / … / 当前页”的模式:

<nav aria-label="Breadcrumb"> <ol class="unstyled hstack" style="font-size: var(--text-7)"> <li><a href="#home" class="unstyled">Home</a></li> <li aria-hidden="true">/</li> <li aria-hidden="true"><a href="#ancestors" class="unstyled">…</a></li> <li aria-hidden="true">/</li> <li><a href="#breadcrumb" class="unstyled" aria-current="page"><strong>Breadcrumb</strong></a></li> </ol> </nav>

折行处理:当容器宽度不足时,.hstack的flex-wrap: wrap会自动将项换行;若希望单行省略,可在容器上覆写flex-wrap: nowrap并配合overflow: hidden、text-overflow: ellipsis。

5.3 面包屑内的表单或搜索上下文

面包屑通常配合页头使用。Oat 的 grid 与.hstack/.justify-between等布局工具(见 utilities.css)可以方便地把面包屑与操作按钮排在同一行:

<div class="hstack justify-between" style="font-size: var(--text-7)"> <nav aria-label="Breadcrumb">…面包屑…</nav> <a href="#back" class="unstyled">← 返回列表</a> </div>

六、无障碍检查清单

面包屑作为导航组件,无障碍是其价值的一半。基于本组件的语义设计与 WAI-ARIA 惯例,落地时请核对:

  1. <nav>必须带aria-label:页面可能同时存在多个<nav>(主导航、面包屑、页脚导航),没有aria-label会让辅助技术无法区分。
  2. 当前项必须有aria-current="page":缺失时屏幕阅读器无法告知用户当前位置。
  3. 分隔符一律aria-hidden="true":无论是文本/、>还是 SVG 箭头。
  4. 链接文本自解释:当前项即使视觉上用<strong>强调,其文本也应独立可读(避免“点击返回”之类无上下文的文案)。
  5. 键盘可达性:面包屑全部为原生<a>链接,天然支持 Tab 聚焦;00-base.css 提供统一的:focus-visible焦点环(outline: 2px solid var(--ring)),无需额外处理。

七、源码级扩展指引

面包屑的样式可完全通过覆写 Oat 主题变量定制,而无需改动组件标记:

定制目标覆写变量定义位置
面包屑悬停链接颜色--primary01-theme.css
项间距--space-301-theme.css
字号--text-7或整体字号刻度01-theme.css
焦点环颜色--ring01-theme.css

覆写方式遵循 customizing.md 的通用规则:在自己的 CSS 文件中重定义同名变量,并在 Oat 的 CSS 之后引入。例如:

:root { --primary: #2563eb; /* 悬停与主色改为蓝色 */ }

若希望深色模式下面包屑有独立配色,可按 customizing.md 的方式,在[data-theme="dark"]作用域内重定义变量。

八、小结

Oat 的面包屑组件浓缩了整座仓库的设计哲学:用语义化标记(<nav>+<ol>+aria-current)表达结构,用基础层与工具类(.hstack、.unstyled、--text-7)完成呈现,用 CSS 变量承接主题扩展。它不需要专属 CSS 文件、不需要一行 JavaScript,即可在零依赖的前提下提供完整、无障碍、可主题化的导航层级——这也是“约 10KB”库体积下组件应有的形态。将其接入项目时,只需牢记两条:<nav>带aria-label、当前项标aria-current="page",其余交给 Oat 的变量体系即可。

【免费下载链接】oat

Ultra-lightweight, zero dependency, semantic HTML, CSS, JS UI library. ~10KB min+gz.

项目地址:https://gitcode.com/gh_mirrors/oat5/oat
点击查看免费下载
上一篇:Moby 依赖库 go-sockaddr 全解析:用运行时启发式规则精确选择 IP 地址
下一篇:离线音频转录终极指南:用Buzz轻松实现语音转文字

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询