Codelab ini mengajarkan cara membuat komponen tata letak navigasi samping geser keluar responsif di web. Kita akan membangun komponen sambil berjalan, dimulai dengan HTML, lalu CSS, kemudian JavaScript.
Lihat postingan blog saya Membangun komponen Sidenav untuk mempelajari fitur platform web CSS yang dipilih untuk membangun komponen ini.
Penyiapan
- Klik Remix to Edit untuk membuat project dapat diedit.
- Buka
app/index.html
.
HTML
Pertama, siapkan HTML dasar agar ada konten dan beberapa kotak yang bisa digunakan.
Letakkan HTML berikut ke dalam tag <body>
.
<aside></aside>
<main></main>
<aside>
menyimpan menu navigasi sebagai elemen pelengkap untuk <main>
, yang menyimpan konten halaman utama.
Selanjutnya, kita akan mengisi elemen semantik tersebut dengan konten halaman lainnya.
Tambahkan elemen navigasi, beberapa link navigasi, dan link tutup di dalam elemen <aside>
.
<aside>
<nav>
<h4>My</h4>
<a href="#">Dashboard</a>
<a href="#">Profile</a>
<a href="#">Preferences</a>
<a href="#">Archive</a>
<h4>Settings</h4>
<a href="#">Accessibility</a>
<a href="#">Theme</a>
<a href="#">Admin</a>
</nav>
<a href="#"></a>
</aside>
Link sangat cocok di dalam elemen <nav>
, dan elemen <nav>
sangat cocok di sidebar <aside>
.
Namun, masih banyak yang dapat kita lakukan untuk meningkatkannya.
Di elemen konten utama, tambahkan header dan artikel untuk menyimpan konten tata letak secara semantik.
<main>
<header>
<a href="#sidenav-open" class="hamburger">
<svg viewBox="0 0 50 40">
<line x1="0" x2="100%" y1="10%" y2="10%" />
<line x1="0" x2="100%" y1="50%" y2="50%" />
<line x1="0" x2="100%" y1="90%" y2="90%" />
</svg>
</a>
<h1>Site Title</h1>
</header>
<article>
{put some placeholder content here}
</article>
</main>
Header memiliki link buka menu. Bagian samping memiliki tombol tutup. Kami akan segera menampilkan dan menyembunyikan elemen berdasarkan ukuran area tampilan.
Dalam elemen <article>
, kita menempelkan kalimat placeholder. Ganti `` dengan konten Anda sendiri, atau tempelkan lorem yang disediakan di bawah:
<h2>Totam Header</h2>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum consectetur, necessitatibus velit officia ut impedit veritatis temporibus soluta? Totam odit cupiditate facilis nisi sunt hic necessitatibus voluptatem nihil doloribus! Enim.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<h3>Subhead Totam Odit</h3>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<h3>Subhead</h3>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
Konten ini, dan panjangnya, akan menyebabkan halaman dapat di-scroll saat melebihi tinggi area pandang Anda.
Sejauh ini, Anda telah menambahkan elemen aside, dengan nav, link, dan cara untuk menutup sidenav. Anda juga menambahkan header, cara membuka sidenav, dan artikel ke elemen utama. Ini sudah bersih, semantik, dan cukup abadi, tetapi kita dapat membuatnya lebih bersih dan jelas bagi semua orang. Link terbuka di sidenav dapat ditandai dengan lebih jelas.
Tambahkan atribut title
dan aria-label
ke elemen link pembuka header:
<a href="#sidenav-open" class="hamburger">
<a href="#sidenav-open" title="Open Menu" aria-label="Open Menu" class="hamburger">
Ikon SVG terbuka juga dapat ditandai dengan lebih jelas. Tambahkan atribut berikut ke SVG di dalam elemen link terbuka:
<svg viewBox="0 0 50 40">
<svg viewBox="0 0 50 40" role="presentation" focusable="false" aria-label="trigram for heaven symbol">
Link tutup di sidenav dapat ditandai dengan lebih jelas.
Tambahkan atribut title
dan aria-label
ke elemen link tutup sidenav:
<a href="#"></a>
<a href="#" title="Close Menu" aria-label="Close Menu"></a>
CSS
Saatnya menata elemen. Konten utama dan sidenav adalah turunan langsung dari tag <body>
, jadi ini adalah tempat yang tepat untuk memulai.
Tambahkan CSS berikut ke css/sidenav.css
agar elemen <body>
menata tata letak turunan.
body {
display: grid;
grid: [stack] 1fr / min-content [stack] 1fr;
@media (max-width: 540px) {
& > :matches(aside, main) {
grid-area: stack;
}
}
}
Tata letak ini pada dasarnya mengatakan: Buat baris bernama stack
dengan semua isinya,
dan 2 kolom dalam baris tersebut, yang kedua juga bernama stack
. Kolom ke-1
harus disesuaikan ukurannya berdasarkan kebutuhan konten minimalnya, dan kolom ke-2 dapat menempati sisanya.
Kemudian, jika berada di area tampilan yang terbatas sebesar 540px
atau kurang, letakkan elemen sidenav dan konten utama
ke dalam baris dan kolom yang sama, sehingga elemen tersebut berada di atas satu sama lain dalam petak 1x1.
Dengan fungsi penumpukan responsif ini sebagai dasar, kita sekarang dapat memanfaatkan status kolom URL untuk mengalihkan visibilitas dan gaya transisi sidenav.
Perbarui elemen <aside>
kembali di app/index.html
:
<aside>
<aside id="sidenav-open">
Hal ini memungkinkan CSS mencocokkan elemen dan hash URL secara bersamaan. Hal ini penting untuk penggunaan :target
.
Sekarang ID elemen dapat cocok dengan hash URL yang akan kita tetapkan dengan tag <a>
.
Selain itu, untuk penargetan JavaScript yang lebih mudah, tambahkan ID untuk elemen utama yang mengontrol sidenav. Pertama, tambahkan ID ke link pembuka sidenav:
<a href="#sidenav-open" class="hamburger" title="Open Menu" aria-label="Open Menu">
<a href="#sidenav-open" id="sidenav-button" class="hamburger" title="Open Menu" aria-label="Open Menu">
Selanjutnya, tambahkan ID ke link tutup sidenav:
<a href="#" title="Close Menu" aria-label="Close Menu"></a>
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>
Hal ini melengkapi tata letak penumpukan responsif makro <body>
, sekaligus mengikat kita ke kolom URL.
Mari kita lanjutkan!
<aside>
juga memiliki tata letak yang rapi. Komponen ini memiliki 2 turunan, <nav>
yang merupakan komponen yang terlihat seperti kertas yang dapat ditarik keluar, dan elemen link penutup <a>
yang menetapkan bahwa url harus #
.
Link tidak terlihat di sebelah kanan nav geser kertas; link ini memungkinkan orang "mengklik keluar" komponen visual untuk menutupnya.
Tambahkan CSS berikut ke css/sidenav.css
:
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
}
Saya pikir rasio dan nama di sini sangat bagus, tempat petak dapat bersinar dan memberi desainer banyak kontrol.
Selanjutnya, saya perlu melapisi konten utama secara kondisional dan mempertahankan posisi saya
melalui scrolling dokumen apa pun. Ini adalah tugas yang bagus untuk position: sticky
dan
beberapa overscroll-behavior
.
Tambahkan gaya berikut untuk sidenav:
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
@media (max-width: 540px) {
position: sticky;
top: 0;
max-height: 100vh;
overflow: hidden auto;
overscroll-behavior: contain;
visibility: hidden; /* not keyboard accessible when closed */
}
}
Gaya tersebut memastikan sidenav memiliki tinggi area pandang, dapat di-scroll secara vertikal
dan berisi scroll. Yang sangat penting, elemen ini menyembunyikan elemen. Secara default,
saat viewport berukuran 540px
atau lebih kecil, sembunyikan sidenav tersebut. Kecuali!
Tambahkan pseudo-pemilih :target
ke elemen #sidenav-open
:
#sidenav-open {
@media (max-width: 540px) {
&:target {
visibility: visible;
}
}
}
Jika ID elemen tersebut dan kolom URL sama,
tetapkan visibility
ke visible
. Lanjutkan dan buka menu samping setelah men-scroll halaman,
atau coba scroll halaman saat sidenav terbuka. Bagaimana menurut Anda?
Tambahkan CSS berikut ke bagian bawah app/sidenav.css
:
#sidenav-button,
#sidenav-close {
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
user-select: none;
touch-action: manipulation;
@media (min-width: 540px) {
display: none;
}
}
Gaya ini menargetkan tombol buka dan tutup, menentukan gaya ketuk dan sentuh, serta menyembunyikannya saat area tampilan berukuran 540px
atau lebih besar.
Untuk menambahkan sentuhan menarik, mari tambahkan transformasi CSS dengan aksesibilitas yang baik.
Tambahkan CSS berikut ke css/sidenav.css
:
#sidenav-open {
--easeOutExpo: cubic-bezier(0.16, 1, 0.3, 1);
--duration: .6s;
...
@media (max-width: 540px) {
...
transform: translateX(-110vw);
will-change: transform;
transition:
transform var(--duration) var(--easeOutExpo),
visibility 0s linear var(--duration);
&:target {
visibility: visible;
transform: translateX(0);
transition: transform var(--duration) var(--easeOutExpo);
}
}
@media (prefers-reduced-motion: reduce) {
--duration: 1ms;
}
}
Tambahkan beberapa JavaScript
Tombol Escape
akan menutup menu. Tambahkan JS ini ke js/index.js
:
const sidenav = document.querySelector('#sidenav-open');
sidenav.addEventListener('keyup', e => {
if (e.code === 'Escape') {
document.location.hash = '';
}
});
Kode ini memproses peristiwa utama pada elemen sidenav.
Jika Escape
, hash URL akan disetel ke kosong, sehingga sidenav akan keluar.
Bagian UX JS berikutnya adalah pengelolaan fokus. Saya ingin mempermudah pembukaan dan penutupan, jadi saya menunggu hingga sidenav menyelesaikan transisi tertentu, lalu memeriksa silang dengan hash URL untuk menentukan apakah sidenav masuk atau keluar. Kemudian, saya menggunakan JavaScript untuk menetapkan fokus pada tombol yang melengkapi tombol yang baru saja ditekan.
Tambahkan JavaScript berikut ke js/index.js
:
const closenav = document.querySelector('#sidenav-close');
const opennav = document.querySelector('#sidenav-button');
sidenav.addEventListener('transitionend', e => {
if (e.propertyName !== 'transform') {
return;
}
const isOpen = document.location.hash === '#sidenav-open';
isOpen
? closenav.focus()
: opennav.focus();
});
Cobalah
- Untuk melihat pratinjau situs, tekan Lihat Aplikasi. Kemudian, tekan
Layar Penuh
.
Kesimpulan
Itulah ringkasan kebutuhan saya dengan komponen tersebut. Jangan ragu untuk mengembangkannya, menggunakannya dengan status JavaScript, bukan URL, dan secara umum menjadikannya milik Anda. Selalu ada hal lain yang dapat ditambahkan atau kasus penggunaan lain yang dapat dicakup.
Buka css/brandnav.css
untuk melihat gaya yang tidak terkait tata letak yang saya terapkan ke
komponen ini. Saya tidak merasa bahwa hal itu penting untuk kumpulan fitur yang saya fokuskan, dan saya berharap pemisahan gaya dari tata letak akan mendorong penyalinan dan penempelan. Mungkin ada lebih banyak hal yang bisa Anda pelajari di sana.
Bagaimana cara membuat komponen sidenav responsif yang dapat ditarik keluar? Apakah Anda pernah memiliki lebih dari 1, seperti satu di kedua sisi? Kami ingin menampilkan solusi Anda dalam video YouTube. Pastikan untuk mengirim tweet kepada kami atau berkomentar di YouTube dengan kode Anda. Hal ini akan membantu semua orang.