สร้าง Side Navigation Menu ที่ slide เข้ามา (animated) และปิดได้ (closable) ด้วย CSS Transition และ JavaScript
ตัวอย่างโค้ด
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <style> .sideNav { height: 100vh; width: 0; position: fixed; z-index: 1; top: 0; left: 0; background-color: rgb(46, 218, 195); overflow-x: hidden; padding-top: 60px; transition: 0.5s; } .sideNav a { padding: 8px 8px 8px 32px; text-decoration: none; font-size: 25px; color: #000000; font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; display: block; transition: 0.3s; } .sidenav a:hover { color: #f1f1f1; } .sideNav .closeBtn { position: absolute; top: 0; right: 25px; font-size: 36px; margin-left: 50px; } button { padding: 15px; background-color: rgb(0, 27, 145); color: rgb(255, 255, 255); font-size: 20px; border: none; border-radius: 2%; } </style> </head> <body> <nav class="sideNav"> <a href="#" class="closeBtn">×</a> <a href="#">Login</a> <a href="#">Register</a> <a href="#">Home</a> <a href="#">About Us</a> </nav> <button class="openSideNav">Click here to open sideNav</button> <script> let openBtn = document.querySelector(".openSideNav"); openBtn.addEventListener("click", () => { showNav(); }); let closeBtn = document.querySelector(".closeBtn"); closeBtn.addEventListener("click", () => { hideNav(); }); function showNav() { document.querySelector(".sideNav").style.width = "300px"; } function hideNav() { document.querySelector(".sideNav").style.width = "0"; } </script> </body> </html>
คำอธิบายการทำงาน
- CSS:
.sideNavเริ่มต้นwidth: 0ซ่อนไว้transition: 0.5sสำหรับ animation - Open: คลิกปุ่ม → JS ตั้ง
width: 300px→ CSS transition slide เข้ามา - Close: คลิก × (closeBtn) → JS ตั้ง
width: 0→ CSS transition slide ออก - Links:
transition: 0.3sสำหรับ hover effect
จุดแก้ไขในโค้ดต้นฉบับ (Typo Fix):
.sidenav a:hover→ ควรเป็น.sideNav a:hover(ตัวใหญ่ N)margin-left: 50pxบน closeBtn ควรใช้right: 25pxอย่างเดียวพอ
เวอร์ชันปรับปรุง (Modern & Accessible):
HTML:
<button class="nav-toggle" aria-expanded="false" aria-controls="sidenav" aria-label="Open menu">☰</button> <nav id="sidenav" class="sidenav" role="dialog" aria-modal="true" aria-label="Navigation"> <button class="close-btn" aria-label="Close menu">×</button> <a href="#">Login</a> ... </nav> <div class="overlay" hidden></div>
CSS:
.sidenav {
position: fixed; top: 0; left: 0; height: 100vh; width: 300px;
transform: translateX(-100%); transition: transform 0.3s ease;
background: white; z-index: 1000; padding-top: 60px;
}
.sidenav.open { transform: translateX(0); }
.overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 999; }
.overlay.hidden { display: none; }
JS:
const toggle = document.querySelector('.nav-toggle');
const sidenav = document.querySelector('.sidenav');
const overlay = document.querySelector('.overlay');
toggle.addEventListener('click', () => {
const open = sidenav.classList.toggle('open');
toggle.setAttribute('aria-expanded', open);
overlay.hidden = !open;
});
overlay.addEventListener('click', () => {
sidenav.classList.remove('open');
toggle.setAttribute('aria-expanded', 'false');
overlay.hidden = true;
});
// ESC key to close
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && sidenav.classList.contains('open')) {
sidenav.classList.remove('open');
toggle.setAttribute('aria-expanded', 'false');
overlay.hidden = true;
}
});
ข้อดีของเวอร์ชันปรับปรุง:
- ใช้
transform: translateXแทน width (performance ดีกว่า, ไม่ทำ reflow) - มี Overlay backdrop (คลิกนอกพื้นที่ปิดได้)
- รองรับ ESC key
- Accessible (ARIA attributes, focus management)
- ใช้ class toggle แทน inline style