简要介绍如何构建便于用户浏览您网站的自适应面包屑导航组件。
在这篇博文中,我想分享一下构建面包屑导航组件的想法。 试用演示版。
<ph type="x-smartling-placeholder">如果你更喜欢视频,可以参阅此博文的 YouTube 版本:
概览
面包屑导航组件会显示 用户在网站层次结构中的位置这个名字来自 Hansel 和 Gretel 在黑暗的森林里,面包屑导航,找到了回家的路 向后追踪面包屑导航
此博文中的面包屑导航不标准
面包屑导航,
它们都是面包屑导航它们通过将同级广告单元放置在其他网址上
使用 <select>
将页面直接插入到导航中,实现多层级访问
后台用户体验
在上面的组件演示视频中,占位符类别是
视频游戏此小路是通过浏览以下路径创建的:home »
rpg » indie » on sale
(如下所示)。
此面包屑导航组件应该可让用户浏览此路径 信息层次结构;跳跃分支并快速选择网页 准确率。
信息架构
我认为从合集和作品的角度考虑问题很有帮助。
集合
集合是一系列可供选择的选项。来自以下网站的首页: 这篇博文的面包屑导航原型,集合是 FPS、RPG、Brawler 地牢爬行者、运动和益智游戏。
商品
视频游戏是一种商品,如果特定集合也属于商品, 代表另一个集合。例如,角色扮演游戏是 。如果是项,则用户位于该集合页面上。例如: 你位于 RPG 页面上,该页面显示了一系列 RPG 游戏,其中包括 “AAA”“独立”和“自行发布”的其他子类别。
在计算机科学术语中,这个面包屑导航组件表示 多维 数组:
const rawBreadcrumbData = {
"FPS": {...},
"RPG": {
"AAA": {...},
"indie": {
"new": {...},
"on sale": {...},
"under 5": {...},
},
"self published": {...},
},
"brawler": {...},
"dungeon crawler": {...},
"sports": {...},
"puzzle": {...},
}
您的应用或网站将采用自定义的信息架构 (IA), 但我希望将集合登陆概念 页面和层次结构遍历也可将其放入面包屑导航中。
布局
Markup
好的组件以适当的 HTML 开头。在下一部分,我将介绍 标记选择及其对整体组件的影响。
深色和浅色方案
<meta name="color-scheme" content="dark light">
上文中的 color-scheme
元标记
代码段通知浏览器,此页面希望使用浅色和深色浏览器
样式。示例面包屑导航不包含任何适用于这些配色方案的 CSS,
因此,面包屑导航将使用浏览器提供的默认颜色。
导航元素
<nav class="breadcrumbs" role="navigation"></nav>
您可以使用
<nav>
元素
用于网站导航,具有隐式 ARIA 角色
导航。
在测试中,我注意到 role
属性改变了
屏幕阅读器与元素进行了交互,实际上该事件被读出为
因此我选择添加它
图标
当某个图标在网页上重复出现时,SVG
<use>
元素
这意味着您可以定义一次 path
,并将其用于
图标。这样可以防止重复出现相同的路径信息,
大型文档,还可能会造成路径不一致。
若要使用此方法,请向页面添加隐藏的 SVG 元素并封装图标
在具有唯一 ID 的 <symbol>
元素中:
<svg style="display: none;">
<symbol id="icon-home">
<title>A home icon</title>
<path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
</symbol>
<symbol id="icon-dropdown-arrow">
<title>A down arrow</title>
<path d="M19 9l-7 7-7-7"/>
</symbol>
</svg>
浏览器读取 SVG HTML,将图标信息存储到内存中, 接着是网页的其余部分引用该 ID, 图标,如下所示:
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<use href="#icon-home" />
</svg>
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<use href="#icon-dropdown-arrow" />
</svg>
仅定义一次,任意多次使用,对网页性能影响极小
和灵活的样式设置请注意,SVG 元素中添加了 aria-hidden="true"
。
那些只听到内容的用户浏览时,这些图标会隐藏起来,没有用处。
避免这些用户造成不必要的干扰
拆分链接 .crumb
这就是传统面包屑导航与此组件中的面包屑导航的区别。
通常,这只是一个 <a>
链接,但我添加了具有
伪装了一下。.crumb
类负责布置链接,
图标,而 .crumbicon
负责堆叠图标并选择
元素在一起。我称它为拆分链接
类似于分屏按钮,
而是针对网页导航
<span class="crumb">
<a href="#sub-collection-b">Category B</a>
<span class="crumbicon">
<svg>...</svg>
<select class="disguised-select" title="Navigate to another category">
<option>Category A</option>
<option selected>Category B</option>
<option>Category C</option>
</select>
</span>
</span>
链接和某些选项没什么特别之处,
简单的面包屑导航将 title
添加到 <select>
元素有助于改善屏幕
读者用户,向他们提供有关按钮操作的信息。然而,
也会为其他所有人提供相同的帮助,你会发现
iPad。一个属性可为许多用户提供按钮上下文。
分隔符装饰
<span class="crumb-separator" aria-hidden="true">→</span>
分隔符是可选的,仅添加一个分隔符也非常实用(请参阅视频中的第三个示例)
)。然后,我为每个aria-hidden="true"
分配了它们,因为它们是装饰性的,而不是
屏幕阅读器需要读出的内容。
接下来将介绍 gap
属性,可让这些元素的间距简单明了。
样式
由于颜色使用系统颜色,因此主要是样式的间隔和堆叠!
布局方向和流程
主要导航元素 nav.breadcrumbs
设置了限定了范围的自定义属性
否则会建立一个水平垂直对齐的
布局。这样可确保面包屑、分隔线和图标对齐。
.breadcrumbs {
--nav-gap: 2ch;
display: flex;
align-items: center;
gap: var(--nav-gap);
padding: calc(var(--nav-gap) / 2);
}
每个 .crumb
还会创建一个水平垂直对齐的布局,其中包含一些
但专门定位其 link 子项,并指定样式,
white-space: nowrap
。这对于多字词面包屑导航至关重要,因为我们
使用多行格式在这篇博文的后面部分,我们将添加样式来处理
此 white-space
属性导致的水平溢出。
.crumb {
display: inline-flex;
align-items: center;
gap: calc(var(--nav-gap) / 4);
& > a {
white-space: nowrap;
&[aria-current="page"] {
font-weight: bold;
}
}
}
添加了 aria-current="page"
,以帮助当前网页链接从
。屏幕阅读器用户不仅能清楚地看到链接
我们已经直观地设置了元素的样式,以帮助视力正常的用户
获得类似的用户体验。
.crumbicon
组件使用网格来堆叠 SVG 图标,该图标具有“几乎
不可见”<select>
元素。
.crumbicon {
--crumbicon-size: 3ch;
display: grid;
grid: [stack] var(--crumbicon-size) / [stack] var(--crumbicon-size);
place-items: center;
& > * {
grid-area: stack;
}
}
<select>
元素是 DOM 中的最后一个元素,因此位于堆栈的顶部。
且具有互动性添加 opacity: .01
样式,以便元素仍然可用。
最终形成一个与图标形状完美契合的选择框。
这是一种自定义 <select>
元素外观的好方法,
来维护内置功能
.disguised-select {
inline-size: 100%;
block-size: 100%;
opacity: .01;
font-size: min(100%, 16px); /* Defaults to 16px; fixes iOS zoom */
}
溢出
面包屑导航应该能够代表很长的路径。我非常喜欢 将内容横向移到屏幕之外,我觉得 面包屑导航组件的合格情况。
.breadcrumbs {
overflow-x: auto;
overscroll-behavior-x: contain;
scroll-snap-type: x proximity;
scroll-padding-inline: calc(var(--nav-gap) / 2);
& > .crumb:last-of-type {
scroll-snap-align: end;
}
@supports (-webkit-hyphens:none) { & {
scroll-snap-type: none;
}}
}
溢出样式可设置以下用户体验:
- 水平滚动和滚动包含。
- 水平滚动内边距。
- 最后一块面包上有一个快照点。也就是说,在网页加载时,第一个 面包屑的加载会迅速减弱,并显示在用户视野范围内。
- 从 Safari 中移除了与水平方向冲突的突起点 滚动和贴靠效果的组合。
媒体查询
针对较小视口的一项细微调整是隐藏“首页”加标签 仅图标:
@media (width <= 480px) {
.breadcrumbs .home-label {
display: none;
}
}
无障碍
动画
这个组件没有太多的动作
在 prefers-reduced-motion
检查中进行过渡时,我们可以防止不必要的动作。
@media (prefers-reduced-motion: no-preference) {
.crumbicon {
transition: box-shadow .2s ease;
}
}
其他样式均无需更改,悬停和聚焦效果都非常棒
且不需要 transition
即可实现,但如果可以移动,我们会添加细微的动作,
过渡到互动。
JavaScript
首先,无论您在网站或应用中使用何种路由器
当用户更改路径时,需要更新网址,
显示相应的页面。其次,为了让用户体验标准化
用户只是在浏览 <select>
时不会发生意外的浏览
选项。
JavaScript 要处理的两个关键用户体验衡量指标:select with
已更改并紧急 <select>
更改事件触发预防。
由于使用了 <select>
,因此需要预防紧急事件
元素。在 Windows Edge 上,可能还有其他浏览器,选择 changed
事件在用户使用键盘浏览选项时触发。这就是我
称为“Eager”,因为用户只选择了伪选项,
但尚未使用 enter
或 click
确认选择。渴望
事件会导致该组件的类别更改功能无法使用,因为
只需打开选择框并浏览某项即可触发事件
在用户做好准备之前更改页面。
已更改<select>
活动,效果更佳
const crumbs = document.querySelectorAll('.breadcrumbs select')
const allowedKeys = new Set(['Tab', 'Enter', ' '])
const preventedKeys = new Set(['ArrowUp', 'ArrowDown'])
// watch crumbs for changes,
// ensures it's a full value change, not a user exploring options via keyboard
crumbs.forEach(nav => {
let ignoreChange = false
nav.addEventListener('change', e => {
if (ignoreChange) return
// it's actually changed!
})
nav.addEventListener('keydown', ({ key }) => {
if (preventedKeys.has(key))
ignoreChange = true
else if (allowedKeys.has(key))
ignoreChange = false
})
})
策略是在每个 <select>
上监视键盘按下事件
元素,并确定所按下的键是否为导航确认(Tab
或
Enter
)或空间导航(ArrowUp
或 ArrowDown
)。这个
组件可以决定是等待还是离开,
系统触发 <select>
元素。
总结
现在您已经知道我是怎么做到的了,您该怎么做 ‽ 🙂?
让我们一起采用多样化的方法,学习所有在 Web 上构建应用的方法。 创建演示,在 Twitter 微博上添加链接,然后我会添加 到下面的社区混剪部分!
社区混剪作品
- 作为 Web 组件的 Tux Solbakk:演示和代码