建立側邊導覽列元件

製作回應式投影片的側邊導覽列基礎總覽

在這篇文章中,我想與您分享如何為網頁設計的側邊導覽元件設計原型 回應式、有狀態且支援鍵盤瀏覽,不論是否使用 JavaScript, 而且適用於多種瀏覽器歡迎查看示範內容

如果您喜歡看影片,請參考這篇文章的 YouTube 版本:

總覽

建置回應式導航系統相當困難。部分使用者會使用鍵盤 有些電腦功能強大,有些則用小型行動裝置造訪 所有造訪的使用者都應該能開啟及關閉選單。

電腦版到行動裝置回應式版面配置示範
iOS 和 Android 裝置上的淺色和深色主題

網路戰術

在這個元件探索中,我可以結合幾項重要的網路平台功能,享受愉快的體驗:

  1. CSS :target
  2. CSS 格狀檢視
  3. CSS 轉換
  4. 可視區域和使用者偏好設定的 CSS 媒體查詢
  5. focus 改善使用者體驗的 JS

我的解決方案只有一個側欄,且只有在處於「行動」狀態時才會切換可視區域為 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 發布你的版本,然後將它新增到 下方的社群重混作品專區。

社群重混作品