レスポンシブ スライドアウト サイドナビゲーションの基本的な作成方法
今回の投稿では、私がこのウェブ用 Sidenav コンポーネントをプロトタイピングし、 レスポンシブ、ステートフル、キーボード ナビゲーションをサポートし、JavaScript の有無にかかわらず動作します。 ブラウザをまたいで動作します。デモをお試しください。
動画で視聴したい場合は、この投稿の YouTube バージョンをご利用ください。
概要
レスポンシブ ナビゲーション システムを構築するのは簡単ではありません。キーボードを使うユーザーもいれば 高性能なパソコンを使用している人もいれば、小型のモバイル デバイスからアクセスする人もいます。 アクセスするユーザー全員がメニューを開閉できる必要があります。
<ph type="x-smartling-placeholder">ウェブ戦術
このコンポーネントの探索では、いくつかの重要なウェブ プラットフォーム機能を組み合わせることができました。
私のソリューションにはサイドバーが 1 つあり、「モバイル」のときだけ切り替えられる540px
以下のビューポート。
540px
は、モバイルのインタラクティブ レイアウトと静的なデスクトップ レイアウトを切り替えるためのブレークポイントです。
CSS :target
疑似クラス
一方の <a>
リンクは URL ハッシュを #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>
これらの各リンクをクリックすると、ページの URL のハッシュ状態が変更されます。 次に、疑似クラスを使用して、sidenav を表示および非表示にします。
@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 変換と切り替え効果
レイアウトがモバイルのビューポート サイズで積み重ねられました。新しいスタイルを追加するまで デフォルトで記事の上に重ねて表示されます次のセクションで狙う UX は次のとおりです。
- 開閉をアニメーション化する
- ユーザーが納得できる場合にのみ、動きのあるアニメーションにします。
- キーボード フォーカスが画面外の要素に入らないように
visibility
をアニメーション化する
モーション アニメーションを実装するにあたり、まずはユーザー補助を念頭に置いてください。
アクセシブルなモーション
誰もがスライドアウト モーションを望んでいるわけではありません。ソリューションでは
を適用するには、メディアクエリ内の CSS 変数 --duration
を調整します。このメディアクエリ値は
オペレーティング システムでのモーションに関する設定(利用可能な場合)。
#sidenav-open {
--duration: .6s;
}
@media (prefers-reduced-motion: reduce) {
#sidenav-open {
--duration: 1ms;
}
}
サイドナビゲーションをスライドさせて開閉するときに 要素を即座にビューに移動し、動きのない状態を維持します。
遷移、変換、翻訳
サイド ナビゲーション(デフォルト)
モバイルのサイド ナビゲーションのデフォルト状態をオフスクリーン状態に設定するには、
transform: translateX(-110vw)
で要素を配置します。
-100vw
の一般的なオフスクリーン コードに、別の 10vw
を追加しました。
これにより、sidenav の 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()
の位置をホームベースの 0
に設定します。
CSS が要素を -110vw
以外の位置から「イン」にスライドするのを待ちます。
URL ハッシュが変更されたときの var(--duration)
に対する 0
の位置。
@media (max-width: 540px) {
#sidenav-open:target {
visibility: visible;
transform: translateX(0);
transition:
transform var(--duration) var(--easeOutExpo);
}
}
切り替え効果の表示
目標はスクリーンリーダーの
メニューを非表示にすることです
オフスクリーン メニューにフォーカスが移動しません。それには、ファイアウォール ルールで
:target
が変更されたときの可視性の遷移。
- 最初は表示を移行しないでください。要素がスライドインして フォーカスが当たるのを確認できます
- 外出時は表示を遷移しますが、遅らせることで、遷移終了時に
hidden
に切り替わります。
ユーザー補助機能の UX の強化
リンク
このソリューションでは、状態を管理できるように URL を変更する必要があります。
当然、ここでは <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 にスプリンクルを追加する
閉じるには 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>
これにより、閉じるときに URL 履歴エントリが削除され、メニューが 表示されます。
UX を重視
次のスニペットは、変更後に [開く] ボタンと [閉じる] ボタンにフォーカスするためです。 開閉します。簡単に切り替えられるようにしたい。
sidenav.addEventListener('transitionend', e => {
const isOpen = document.location.hash === '#sidenav-open';
isOpen
? document.querySelector('#sidenav-close').focus()
: document.querySelector('#sidenav-button').focus();
})
サイド ナビゲーションが開いたら、閉じるボタンをフォーカスします。サイドナビゲーションが閉じると
「開く」ボタンをフォーカスします。これを行うには、JavaScript の要素で focus()
を呼び出します。
まとめ
私のやり方わかったな、どうやって?!これで、コンポーネント アーキテクチャが面白いものになります。 スロット付きの最初のバージョンは誰が制作するのでしょうか。🙂
多様なデータで さまざまなアプローチを学び、ウェブで構築するあらゆる方法を学べます。Glitch を作成します。 あなたのバージョンをツイートしていただければ、 以下のコミュニティ リミックスのセクションをご覧ください。
コミュニティ リミックス
- カスタム要素を使用した @_developit: demo &コード
- @mayeedwin1(HTML/CSS/JS 使用): デモ、コード
- @a_nurella と Glitch Remix: デモとコード
- @EvroMalarkey と HTML/CSS/JS: デモ、コード