命名为 [escape],用于关闭菜单。#sidenav-open { display: grid; grid-template-columns: [nav] 2fr [escape] 1fr; }
调整 2fr 和 1fr,找到你喜欢的菜单覆盖和负空间关闭按钮的比例。
3D transforms
我们的布局现在是堆叠在一个移动视口大小。除非我添加一些新的样式,否则它将默认覆盖我们的文章。下面是一些我正在努力实现的用户体验:
动画打开和关闭;
只有在用户同意的情况下才使用动画;
键盘焦点不会进入屏幕以外的元素;
当我开始实现动作动画的时候,我想先从可访问性开始。
无障碍运动
不是每个人都想要幻灯片移动的体验。在我们的解决方案中,这个首选项是通过调整媒体查询中的 -- duration CSS 变量来实现的。此媒体查询值表示用户的操作系统对移动的偏好(如果可用)。
#sidenav-open { --duration: .6s; } @media (prefers-reduced-motion: reduce) { #sidenav-open { --duration: 1ms; } }
现在,当我们的 sidenav 滑动打开和关闭,如果用户喜欢减少运动,我立即移动元素进入视图,保持没有运动的状态。
Transition, transform, translate
Sidenav 默认是退出状态的。为了将移动设备上 Sidenav 的默认状态设置为屏幕外状态,我将元素的位置设置为:
transform: translateX (- 110vw);
注意,我在典型的屏幕外代码 -100vw 中添加了10vw,以确保当 sidenav 隐藏时,它的盒子阴影不会窥视主视图。
@media (max-width: 540px) { #sidenav-open { visibility: hidden; transform: translateX(-110vw); will-change: transform; transition: transform var(--duration) var(--easeOutExpo), visibility 0s linear var(--duration); } }
当 #sidenav 元素匹配为 :target 时,将 translateX() 位置设置为 0。当 URL 哈希值变化的时候,观察到元素会从 -110vw 的位置滑动到 0 的位置。
@media (max-width: 540px) { #sidenav-open:target { visibility: visible; transform: translateX(0); transition: transform var(--duration) var(--easeOutExpo); } }
过渡时期的可见性
现在的目标是屏幕阅读器看不到菜单,这样系统就不会把焦点放在屏幕外的菜单上。我通过在: 目标更改时设置可见性转换来实现这一点。
可访问性 UX 增强
链接
此解决方案依赖于更改 URL 以便管理状态。当然,这里应该使用 元素,它可以免费获得一些很好的可访问性特性。让我们用清楚表达意图的标签来装饰我们的交互式元素。
现在我们的主要交互按钮清楚地表明了鼠标和键盘的意图。
:is(:hover, :focus)
这个方便的 CSS 函数式伪选择器可以让我们通过分享焦点快速地包容我们的悬停样式。
.hamburger:is(:hover, :focus) svg > line { stroke: hsl(var(--brandHSL)); }
加上点 JS
键盘上的 Escape 键应该关闭菜单,对吗? 让我们把它实现:
const sidenav = document.querySelector('#sidenav-open'); sidenav.addEventListener('keyup', event => { if (event.code === 'Escape') document.location.hash = ''; });
下一个代码片段帮助我们将注意力集中在打开或关闭按钮上。我想让切换变得简单。
sidenav.addEventListener('transitionend', e => { const isOpen = document.location.hash === '#sidenav-open'; isOpen ? document.querySelector('#sidenav-close').focus() : document.querySelector('#sidenav-button').focus(); })
当 Sidenav 打开时,集中关闭按钮。当 Sidenav 关闭时,集中打开按钮。我通过在 JS 中的元素上调用 focus() 来实现这一点。