製作回應式投影片的側邊導覽列基礎總覽
在這篇文章中,我想與您分享如何為網頁設計的側邊導覽元件設計原型 回應式、有狀態且支援鍵盤瀏覽,不論是否使用 JavaScript, 而且適用於多種瀏覽器歡迎查看示範內容。
如果您喜歡看影片,請參考這篇文章的 YouTube 版本:
總覽
建置回應式導航系統相當困難。部分使用者會使用鍵盤 有些電腦功能強大,有些則用小型行動裝置造訪 所有造訪的使用者都應該能開啟及關閉選單。
網路戰術
在這個元件探索中,我可以結合幾項重要的網路平台功能,享受愉快的體驗:
我的解決方案只有一個側欄,且只有在處於「行動」狀態時才會切換可視區域為 540px
以下。
我們的中斷點會是 540px
,在行動裝置互動版面配置和靜態桌面版面配置之間進行切換。
CSS :target
虛擬類別
一個 <a>
連結會將網址雜湊設為 #sidenav-open
,另一個連結則設為空白 (''
)。
最後,元素擁有與雜湊相符的 id
:
<a href="#sidenav-open" id="sidenav-button" title="Open Menu" aria-label="Open Menu">
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>
<aside id="sidenav-open">
…
</aside>
只要按一下每個連結,就會變更網頁網址的雜湊狀態。 然後用虛擬類別顯示或隱藏側邊導覽列:
@media (max-width: 540px) {
#sidenav-open {
visibility: hidden;
}
#sidenav-open:target {
visibility: visible;
}
}
CSS 格線
過去我只使用絕對或固定位置
側邊導覽列版面配置和元件但使用 grid-area
語法時
這樣就能將多個元素指派給同一個列或欄
堆疊
主要版面配置元素 #sidenav-container
是一個格狀檢視畫面,可建立 1 列和 2 欄。
其中 1 個皆名為「stack
」。當空間受限時,CSS 會指派所有 <main>
元素的
將子項置於相同的格線名稱,將所有元素放在同一個空間中,進而形成堆疊。
#sidenav-container {
display: grid;
grid: [stack] 1fr / min-content [stack] 1fr;
min-height: 100vh;
}
@media (max-width: 540px) {
#sidenav-container > * {
grid-area: stack;
}
}
選單背景幕
<aside>
是包含側邊導覽的動畫元素。它有
2 個子項:名為 [nav]
的導覽容器 <nav>
和背景 <a>
名為 [escape]
的對話方塊,用於關閉選單。
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
}
調整「2fr
」和1fr
,找出您想要的選單疊加層及其負空間關閉按鈕的比例。
CSS 3D 變形和轉場
我們的版面配置現已堆疊在行動裝置可視區域的大小。直到我加入新樣式為止 預設會覆蓋我們的文章在接下來的章節中,我將會拍攝一些使用者體驗:
- 為開場和關閉製作動畫
- 只有在使用者允許時,才為動畫加入動畫
- 為
visibility
建立動畫效果,讓鍵盤焦點不會進入螢幕外元素
開始導入動作動畫時,我想先從無障礙需求著手。
無障礙動作
並非每個人都會希望獲得滑出運動體驗。這項解決方案偏好在我們的解決方案中
是藉由調整媒體查詢中的 --duration
CSS 變數來套用。這個媒體查詢值代表
使用者的作業系統偏好設定 (如果有的話)。
#sidenav-open {
--duration: .6s;
}
@media (prefers-reduced-motion: reduce) {
#sidenav-open {
--duration: 1ms;
}
}
現在,當側邊導覽列保持開啟及關閉時,如果使用者偏好減少動態效果 我立即將元素移到檢視畫面中,不動手就能保留狀態。
轉換、轉換、翻譯
退出側邊導覽列 (預設)
如要將行動版側邊導覽列的預設狀態設為螢幕外狀態,
我使用 transform: translateX(-110vw)
定位元素。
請注意,我已在 -100vw
的一般螢幕外程式碼中新增另一個 10vw
。
可確保側邊導覽列的 box-shadow
在隱藏時不會透視至主要可視區域。
@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()
位置設為 homebase 0
。
並留意,將元素從 -110vw
的位置滑到其「in」
網址雜湊變更時,0
的位置超過 var(--duration)
。
@media (max-width: 540px) {
#sidenav-open:target {
visibility: visible;
transform: translateX(0);
transition:
transform var(--duration) var(--easeOutExpo);
}
}
轉場效果顯示設定
現在的目標在於在無法使用螢幕閱讀器時
隱藏選單
這樣系統就不會將焦點移至螢幕外的選單我透過設定
在 :target
變更時,會轉換顯示設定轉換。
- 進入網站時不要轉場,都能看到該元素的位置滑入畫面 然後接受焦點
- 離開時,系統會延遲顯示轉換的顯示狀態,但延遲顯示,所以在轉場結束時,就會轉換為
hidden
。
改善無障礙使用者體驗
連結
這項解決方案需變更網址,才能管理狀態。
當然,<a>
元素應在此使用,以便提供良好的無障礙功能
所有免費功能現在交織互動元素,使用標籤清楚表達意圖。
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>
<a href="#sidenav-open" id="sidenav-button" class="hamburger" title="Open Menu" aria-label="Open Menu">
<svg>...</svg>
</a>
現在,我們的主要互動按鈕都能清楚指出他們使用滑鼠和鍵盤的意圖。
:is(:hover, :focus)
運用這項便利的 CSS 功能虛擬選取器,我們迅速地展現多元包容的精神 與懸停樣式一併分享
.hamburger:is(:hover, :focus) svg > line {
stroke: hsl(var(--brandHSL));
}
JavaScript 上的 Sprinkle
按下 escape
鍵即可關閉
鍵盤上的Escape
鍵應該向右關閉選單?我們來接線吧。
const sidenav = document.querySelector('#sidenav-open');
sidenav.addEventListener('keyup', event => {
if (event.code === 'Escape') document.location.hash = '';
});
瀏覽器歷史記錄
以免在開啟和關閉的互動中堆疊多個 將下列 JavaScript 內嵌於瀏覽器歷史記錄中 關閉按鈕:
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu" onchange="history.go(-1)"></a>
這會在關閉時移除網址紀錄項目,使其像是選單 從未開啟過。
以使用者體驗為重
下一段程式碼片段能幫助我們將焦點放在 開啟或關閉我想輕鬆換機。
sidenav.addEventListener('transitionend', e => {
const isOpen = document.location.hash === '#sidenav-open';
isOpen
? document.querySelector('#sidenav-close').focus()
: document.querySelector('#sidenav-button').focus();
})
開啟側邊導覽列時,將焦點移至關閉按鈕。當側邊導覽列關閉時
將焦點移至開啟按鈕只要在 JavaScript 中呼叫元素上的 focus()
即可。
結論
現在你知道該怎麼做了,你會怎麼做?!這可以提供一些有趣的元件架構! 誰打算使用第 1 版使用運算單元?🙂
我們來擴展 ,瞭解建立網路世界的所有方式。建立 Glitch。 透過 Twitter 發布你的版本,然後將它新增到 下方的社群重混作品專區。
社群重混作品
- @_developit 加上自訂元素:示範 &程式碼
- 包含 HTML/CSS/JS 的 @mayeedwin1:示範與程式碼
- @a_nurella 搭配 Glitch Remix:示範與程式碼
- 加上 HTML/CSS/JS 的 @EvroMalarkey:示範與程式碼