带滚动和下拉菜单的优先级导航

Avatar of Micah Miller-Eshleman
Micah Miller-Eshleman 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

以下是 Micah Miller-Eshleman 的客座文章。Micah 设计了“优先级+导航”概念的一个变体,并在其工作的大学的生产环境中使用它。我一直喜欢了解设计模式背后的思考和创建过程,尤其是在它在现实世界中发挥作用的时候。

在小屏幕上显示较长的导航菜单很棘手。汉堡菜单随处可见,尽管 经常被劝阻使用。在每个断点显示“刚刚好”的导航感觉像是一项不可能完成的任务。对于需要适应任意数量菜单项的模板开发人员来说尤其如此。

优先级+设计模式 旨在在给定任意屏幕宽度的情况下显示尽可能多的项目,同时使其余项目可以通过单击即可访问。我将介绍我在 戈申学院 工作时进行的实现,其中包括下拉菜单和水平滚动,这是我在其他地方从未见过的。

用户在导航菜单上水平滚动

1. 使用纯 CSS 实现带有固定项目的水平滚动

让我们从一个简单的水平滚动菜单开始

查看 CodePen 上 Micah Miller-Eshleman (@pranksinatra) 编写的 带有固定项目的优先级+导航

(对于好奇的人,我正在使用 BEM 命名约定 作为类的名称,并使用 PostCSS 来实现一些简单的便利功能,例如嵌套和变量。)

请注意,在上面的演示中,如何调整屏幕宽度在 480px 以上/以下切换“GC Admissions”(第一个菜单项)的固定性。这是通过使用两个包装器实现的:一个外部包装器包含所有在 <480px 宽度下可滚动的菜单项,以及一个内部包装器包含所有非固定菜单项并在 >480px 宽度下可滚动。

2. 添加按钮和下拉菜单

在这里,我通过添加下拉菜单和点击滚动按钮扩展了之前的演示。我需要一些 JavaScript 来帮助实现滚动功能。

查看 CodePen 上 Micah Miller-Eshleman (@pranksinatra) 编写的 带有下拉菜单和滚动按钮的优先级+导航

关于依赖项的快速说明:我内联了一个部分 classList、performance.now 和 requestAnimationFrame polyfill 用于 IE9+。 Font Face Observer 用于检测 Source Sans Pro 字体 何时加载。jQuery 通过使用 focusin()focusout() 绑定来监听其子链接的 :focus 状态,从而帮助使下拉菜单可通过 Tab 键进行导航。请异步加载它(或找到更轻量级的替代方案)。

2a. 点击滚动按钮

按钮不仅对于启用鼠标和键盘用户的水平滚动很重要,而且对于指示滚动是可能的也很重要。这个概念借鉴于 Apple.com iPhone 页面

从根本上说,按钮点击通过更新相关包装器的 scrollLeft 属性来滚动菜单项。然后使用缓动函数对其进行动画处理,以模拟平滑的“动量”滚动。

您还会注意到一些显示/隐藏按钮、确定要滚动哪个包装器等的逻辑。为了做出这些决定,我们监听菜单的水平滚动位置和窗口的宽度(使用 去抖事件处理程序 来提高性能)。

2b. 水平滚动器上的下拉菜单

构建水平滚动下拉菜单证明是这个项目中最具挑战性的部分。

菜单的基本 HTML 结构由一个可滚动的包装器组成,该包装器包含菜单项列表,其中一些包含下拉菜单。菜单项是相对定位的,它们的下拉菜单是绝对定位的,因此它们作为一个单元滚动,但不会影响彼此的宽度。

必须为包装器指定一个显式高度,以防止下拉菜单被截断。然后我们遇到一个问题,即有一个非常高的包装器,要么向下推,要么覆盖后续内容。

查看 CodePen 上 Micah Miller-Eshleman (@pranksinatra) 编写的 定位可滚动包装器

我选择的方法是使菜单在与之交互之前保持折叠状态,此时我们立即过渡到状态 #3(反之亦然)。这是通过侦听组件和包装器的 mouseovertouchstart 事件来实现的。

演示有意简化,只使用了一个包装器。对于多个包装器,我实际上是在 .nav 组件上切换 overflow 属性(hidden/visible),而不是单个包装器的高度,但底层概念是一样的。

如果您发现了更优雅的方法来实现这一点,我洗耳恭听!