命名為 [escape],用于關(guān)閉菜單。#sidenav-open { display: grid; grid-template-columns: [nav] 2fr [escape] 1fr; }
調(diào)整 2fr 和 1fr,找到你喜歡的菜單覆蓋和負(fù)空間關(guān)閉按鈕的比例。

3D transforms
我們的布局現(xiàn)在是堆疊在一個移動視口大小。除非我添加一些新的樣式,否則它將默認(rèn)覆蓋我們的文章。下面是一些我正在努力實現(xiàn)的用戶體驗:
動畫打開和關(guān)閉;
只有在用戶同意的情況下才使用動畫;
鍵盤焦點不會進(jìn)入屏幕以外的元素;
當(dāng)我開始實現(xiàn)動作動畫的時候,我想先從可訪問性開始。
無障礙運動
不是每個人都想要幻燈片移動的體驗。在我們的解決方案中,這個首選項是通過調(diào)整媒體查詢中的 -- duration CSS 變量來實現(xiàn)的。此媒體查詢值表示用戶的操作系統(tǒng)對移動的偏好(如果可用)。
#sidenav-open { --duration: .6s; } @media (prefers-reduced-motion: reduce) { #sidenav-open { --duration: 1ms; } }

現(xiàn)在,當(dāng)我們的 sidenav 滑動打開和關(guān)閉,如果用戶喜歡減少運動,我立即移動元素進(jìn)入視圖,保持沒有運動的狀態(tài)。
Transition, transform, translate
Sidenav 默認(rèn)是退出狀態(tài)的。為了將移動設(shè)備上 Sidenav 的默認(rèn)狀態(tài)設(shè)置為屏幕外狀態(tài),我將元素的位置設(shè)置為:
transform: translateX (- 110vw);
注意,我在典型的屏幕外代碼 -100vw 中添加了10vw,以確保當(dāng) 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); } }
當(dāng) #sidenav 元素匹配為 :target 時,將 translateX() 位置設(shè)置為 0。當(dāng) URL 哈希值變化的時候,觀察到元素會從 -110vw 的位置滑動到 0 的位置。
@media (max-width: 540px) { #sidenav-open:target { visibility: visible; transform: translateX(0); transition: transform var(--duration) var(--easeOutExpo); } }
過渡時期的可見性
現(xiàn)在的目標(biāo)是屏幕閱讀器看不到菜單,這樣系統(tǒng)就不會把焦點放在屏幕外的菜單上。我通過在: 目標(biāo)更改時設(shè)置可見性轉(zhuǎn)換來實現(xiàn)這一點。
可訪問性 UX 增強
鏈接
此解決方案依賴于更改 URL 以便管理狀態(tài)。當(dāng)然,這里應(yīng)該使用 元素,它可以免費獲得一些很好的可訪問性特性。讓我們用清楚表達(dá)意圖的標(biāo)簽來裝飾我們的交互式元素。
現(xiàn)在我們的主要交互按鈕清楚地表明了鼠標(biāo)和鍵盤的意圖。
:is(:hover, :focus)
這個方便的 CSS 函數(shù)式偽選擇器可以讓我們通過分享焦點快速地包容我們的懸停樣式。
.hamburger:is(:hover, :focus) svg > line { stroke: hsl(var(--brandHSL)); }
加上點 JS
鍵盤上的 Escape 鍵應(yīng)該關(guān)閉菜單,對嗎? 讓我們把它實現(xiàn):
const sidenav = document.querySelector('#sidenav-open'); sidenav.addEventListener('keyup', event => { if (event.code === 'Escape') document.location.hash = ''; });
下一個代碼片段幫助我們將注意力集中在打開或關(guān)閉按鈕上。我想讓切換變得簡單。
sidenav.addEventListener('transitionend', e => { const isOpen = document.location.hash === '#sidenav-open'; isOpen ? document.querySelector('#sidenav-close').focus() : document.querySelector('#sidenav-button').focus(); })
當(dāng) Sidenav 打開時,集中關(guān)閉按鈕。當(dāng) Sidenav 關(guān)閉時,集中打開按鈕。我通過在 JS 中的元素上調(diào)用 focus() 來實現(xiàn)這一點。