Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Thanh menu là thứ gần như trang web nào cũng có, và cũng là thứ dễ làm sai nhất trên điện thoại. Bài này hướng dẫn bạn làm menu trải ngang trên máy tính, tự thu gọn thành nút hamburger trên màn hình nhỏ, đồng thời đảm bảo dùng được bằng bàn phím.
Menu của chúng ta cần: logo bên trái, các liên kết bên phải trên màn hình rộng; trên màn hình hẹp, các liên kết ẩn đi và hiện ra khi bấm nút ba gạch. Ta làm theo hướng mobile first: viết style cho điện thoại trước, rồi dùng media query để mở rộng cho màn hình lớn.
Dùng thẻ nav bao quanh menu, danh sách ul cho các liên kết, và button thật cho nút hamburger (không dùng div) để trình đọc màn hình và bàn phím hiểu được.
<header class="site-header">
<a class="logo" href="/">MyBrand</a>
<button class="nav-toggle" aria-expanded="false" aria-controls="main-nav" aria-label="Mở menu">
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
</button>
<nav id="main-nav" class="main-nav">
<ul>
<li><a href="/">Trang chủ</a></li>
<li><a href="/khoa-hoc">Khóa học</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/lien-he">Liên hệ</a></li>
</ul>
</nav>
</header>Hai thuộc tính ARIA đáng chú ý: aria-expanded báo trạng thái đóng hay mở, còn aria-controls chỉ ra phần tử mà nút điều khiển. Tên nhãn aria-label cần thiết vì nút chỉ chứa các thanh trang trí, không có chữ.
.site-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 20px;
background: #111827;
position: relative;
}
.logo { color: #fff; font-weight: 700; text-decoration: none; }
.nav-toggle {
background: none; border: 0; cursor: pointer; padding: 8px;
display: flex; flex-direction: column; gap: 5px;
}
.bar { width: 24px; height: 3px; background: #fff; border-radius: 2px; }
.main-nav {
display: none;
position: absolute; top: 100%; left: 0; right: 0;
background: #1f2937;
}
.main-nav.open { display: block; }
.main-nav ul { list-style: none; margin: 0; padding: 0; }
.main-nav a {
display: block; padding: 14px 20px; color: #e5e7eb; text-decoration: none;
}
.main-nav a:hover, .main-nav a:focus-visible { background: #374151; }
@media (min-width: 768px) {
.nav-toggle { display: none; }
.main-nav { display: block; position: static; background: none; }
.main-nav ul { display: flex; gap: 8px; }
.main-nav a { padding: 8px 14px; border-radius: 6px; }
}Trên màn hình từ 768px trở lên, nút hamburger bị ẩn và menu luôn hiển thị theo hàng ngang nhờ Flexbox. Đặt position: relative cho header để menu thả xuống định vị tương đối theo nó.
const toggle = document.querySelector('.nav-toggle');
const nav = document.getElementById('main-nav');
function setMenu(open) {
nav.classList.toggle('open', open);
toggle.setAttribute('aria-expanded', String(open));
toggle.setAttribute('aria-label', open ? 'Đóng menu' : 'Mở menu');
}
toggle.addEventListener('click', () => {
setMenu(!nav.classList.contains('open'));
});
// Đóng menu khi nhấn Escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && nav.classList.contains('open')) {
setMenu(false);
toggle.focus();
}
});
// Đóng menu khi bấm vào một liên kết
nav.addEventListener('click', (e) => {
if (e.target.closest('a')) setMenu(false);
});button).:hover để mở menu con trên điện thoại, nơi không có chuột.display: none cho menu rồi quên hiển thị lại ở màn hình lớn, khiến menu biến mất khi xoay ngang.Một menu tốt không chỉ đẹp mà còn phải dùng được bằng cảm ứng, chuột và bàn phím. Với HTML ngữ nghĩa, vài dòng CSS Flexbox và đoạn JavaScript ngắn, bạn đã có thể tự làm thay vì phụ thuộc vào thư viện. Đây cũng là nền tảng để làm menu con, mega menu hay ngăn kéo bên cạnh.
Để học thiết kế giao diện web một cách bài bản, hãy tham khảo các khóa học tại codebem.com.
Nguyễn Đình Cường
0 comment