Trong kỷ nguyên số, khi hơn 50% lưu lượng truy cập web toàn cầu đến từ các thiết bị di động, việc sở hữu một giao diện người dùng tối ưu trên mọi kích thước màn hình là điều tối quan trọng. Đặc biệt, một menu điều hướng rõ ràng, súc tích và trực quan không chỉ nâng cao trải nghiệm người dùng mà còn là yếu tố then chốt giúp website của bạn, như meetup.vn – nền tảng chia sẻ kiến thức và đánh giá ẩm thực, trở nên dễ sử dụng hơn. Thử tưởng tượng một người dùng đang tìm kiếm một nhà hàng đặc trưng trong vùng miền trên điện thoại di động của họ; một responsive menu CSS không JavaScript hoạt động mượt mà sẽ là cầu nối đưa họ đến thông tin cần thiết một cách nhanh chóng và hiệu quả.
Sự linh hoạt của menu không chỉ là một tính năng mà còn là một yêu cầu bắt buộc. Với triết lý thiết kế ưu tiên di động (mobile-first), các nhà phát triển bắt đầu xây dựng từ kích thước màn hình nhỏ nhất, sau đó dần mở rộng quy mô, bổ sung thêm tính năng và chức năng cho các kích thước màn hình lớn hơn. Điều này đảm bảo rằng các trang web sẽ tự động điều chỉnh phù hợp với kích thước cửa sổ trình duyệt của người dùng, mang lại trải nghiệm nhất quán và chuyên nghiệp.
Điều đáng chú ý là để xây dựng một menu đáp ứng hoàn hảo, bạn không nhất thiết phải dựa vào JavaScript. Hướng dẫn toàn diện này sẽ đi sâu vào cách tạo một responsive menu CSS không JavaScript từ đầu, bao gồm cả biểu tượng hamburger quen thuộc, chỉ sử dụng HTML và CSS thuần túy. Chúng ta sẽ khám phá các kỹ thuật từ cơ bản đến nâng cao, đảm bảo rằng menu của bạn không chỉ hoạt động tốt mà còn trông đẹp mắt trên mọi thiết bị.

Tầm Quan Trọng Của Menu Đáp Ứng Ưu Tiên Di Động Trong Kỷ Nguyên Số
Trong bối cảnh người dùng ngày càng phụ thuộc vào điện thoại thông minh để truy cập thông tin, một responsive menu CSS không JavaScript không chỉ là một lựa chọn mà là một yếu tố sống còn cho bất kỳ website nào. Sự phát triển mạnh mẽ của công nghệ di động đã thay đổi hoàn toàn cách chúng ta tương tác với internet. Điều này đòi hỏi các nhà phát triển web phải thích nghi và tạo ra những trải nghiệm mượt mà, nhất quán trên mọi thiết bị, từ máy tính để bàn, máy tính bảng cho đến điện thoại thông minh. Một menu được thiết kế đáp ứng tốt không chỉ giúp người dùng dễ dàng tìm thấy nội dung họ cần mà còn góp phần xây dựng hình ảnh chuyên nghiệp và đáng tin cậy cho thương hiệu của bạn.
Việc ưu tiên thiết kế cho di động không chỉ đơn thuần là thu nhỏ giao diện máy tính để bàn. Nó là một triết lý thiết kế tập trung vào việc cung cấp trải nghiệm tối ưu nhất cho người dùng trên màn hình nhỏ, sau đó mới dần mở rộng và bổ sung các tính năng cho màn hình lớn hơn. Một menu điều hướng được xây dựng theo cách này sẽ đảm bảo các yếu tố quan trọng luôn dễ tiếp cận, không bị che khuất hoặc khó thao tác. Đối với một nền tảng như meetup.vn, nơi người dùng thường xuyên tìm kiếm các gợi ý ẩm thực hoặc địa điểm ăn uống khi đang di chuyển, một responsive menu CSS không JavaScript hoạt động hiệu quả có thể là yếu tố quyết định giữa việc người dùng tìm thấy thông tin mình cần hay bỏ cuộc vì trải nghiệm kém.
Ngoài ra, việc sử dụng CSS thuần túy để xây dựng menu đáp ứng còn mang lại nhiều lợi ích đáng kể. Nó giảm thiểu sự phụ thuộc vào JavaScript, giúp giảm tải thời gian tải trang, cải thiện hiệu suất tổng thể của website và giảm thiểu rủi ro về bảo mật. Khi không có JavaScript, menu của bạn sẽ hoạt động ngay cả khi người dùng tắt JavaScript trong trình duyệt của họ, đảm bảo tính bền vững và khả năng tiếp cận rộng rãi hơn. Hơn nữa, việc chỉ sử dụng CSS cũng đơn giản hóa quy trình phát triển và bảo trì, cho phép các nhà phát triển tập trung hơn vào cấu trúc và kiểu dáng mà không cần lo lắng về các kịch bản phức tạp.

Kỹ Thuật Xây Dựng Menu Di Động Đáp Ứng Chỉ Bằng CSS
Kỹ thuật tạo responsive menu CSS không JavaScript phổ biến nhất dựa trên việc sử dụng cấu trúc danh sách HTML đơn giản (HTML list structure) để phát triển một menu chứa các liên kết. Sau đó, các liên kết này sẽ được tạo kiểu và hiển thị khác nhau dựa trên kích thước màn hình của thiết bị thông qua các quy tắc CSS. Cách tiếp cận này giúp menu có khả năng tự động điều chỉnh mà không cần bất kỳ đoạn mã JavaScript phức tạp nào.
Trong phần này, chúng ta sẽ bắt tay vào xây dựng một menu đáp ứng hoàn chỉnh, bao gồm biểu tượng hamburger cho màn hình nhỏ và các mục menu hiển thị cùng hàng (inline) trên màn hình lớn. Mục tiêu là tạo ra một menu có khả năng chuyển đổi mượt mà giữa các chế độ xem di động, máy tính bảng và máy tính để bàn. Đối với các màn hình nhỏ hơn, người dùng sẽ nhấp vào biểu tượng hamburger để mở rộng và hiển thị các mục menu. Ngược lại, trên các màn hình lớn, các mục menu sẽ được hiển thị trực tiếp trong thanh điều hướng, tạo ra một trải nghiệm liền mạch và hiệu quả cho người dùng.
Kỹ thuật cốt lõi để tạo biểu tượng hamburger và khả năng chuyển đổi menu mà không cần JavaScript là sử dụng “checkbox hack”. Đây là một phương pháp thông minh dựa vào thuộc tính :checked của <input type="checkbox"> kết hợp với <label> và bộ chọn CSS (CSS selectors) để điều khiển trạng thái hiển thị của menu. Khi checkbox được đánh dấu (checked), chúng ta sẽ áp dụng các kiểu CSS để hiển thị menu và chuyển đổi biểu tượng hamburger thành biểu tượng đóng (close icon). Phương pháp này tận dụng hoàn toàn sức mạnh của CSS để tạo ra một hiệu ứng tương tác mà không cần phải viết bất kỳ dòng mã JavaScript nào, đảm bảo hiệu suất cao và khả năng tiếp cận tốt hơn.
Khởi Tạo Dự Án: Cấu Trúc HTML Ban Đầu
Để bắt đầu, hãy tạo hai tệp trong một thư mục chung: index.html cho mã HTML và style.css cho mã CSS. Sau đó, mở tệp index.html bằng trình duyệt yêu thích của bạn để xem trước ứng dụng.
Cấu trúc HTML ban đầu cho trang web sẽ bao gồm các phần chính như thanh điều hướng và nội dung chính của trang. Chúng ta sẽ sử dụng các thẻ ngữ nghĩa như <header> và <main> để phân tách rõ ràng các thành phần này. Thẻ <header> sẽ chứa logo và menu điều hướng, trong khi thẻ <main> sẽ chứa nội dung chính của trang.
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Responsive Pure CSS Menu</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
</head>
<body>
<header class="header" role="banner">
<a href="https://meetup.vn/" class="logo" aria-label="Meetup.vn Logo">Meetup</a>
<input class="side-menu" type="checkbox" id="side-menu" aria-label="Nút mở/đóng menu điều hướng"/>
<label class="hamb" for="side-menu" aria-label="Mở menu điều hướng">
<span class="hamb-line"></span>
</label>
<nav class="nav" role="navigation" aria-label="Menu Chính">
<ul class="menu">
<li><a href="#">Trang Chủ</a></li>
<li><a href="#">Món Ăn Đặc Trưng</a></li>
<li class="subnav">
<a href="#" class="subnavbtn" aria-current="page">Địa Điểm <i class="fa fa-caret-down"></i></a>
<ul class="subnav-content">
<li><a href="#">Nhà Hàng</a></li>
<li><a href="#">Quán Cafe</a></li>
<li><a href="#">Quán Bar</a></li>
</ul>
</li>
<li><a href="#">Đánh Giá</a></li>
<li><a href="#">Liên Hệ</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h1>Nội Dung Chính Của Trang Web</h1>
<p>Chào mừng bạn đến với Meetup.vn, nơi bạn có thể khám phá những món ăn ngon và địa điểm ẩm thực tuyệt vời. Website này sử dụng một responsive menu CSS không JavaScript để đảm bảo trải nghiệm tốt nhất trên mọi thiết bị.</p>
<p>Để tìm kiếm các địa điểm ăn uống phù hợp cho chuyến đi của bạn hoặc tham khảo thực đơn nhà hàng, một menu điều hướng tiện lợi là vô cùng cần thiết. Menu này được thiết kế để hoạt động mượt mà trên điện thoại, máy tính bảng và máy tính để bàn, giúp bạn dễ dàng truy cập thông tin.</p>
<p>Chúng tôi cam kết mang đến những đánh giá chân thực và hữu ích về các nhà hàng, quán ăn, giúp bạn đưa ra lựa chọn tốt nhất. Hãy khám phá ngay các món ăn đặc trưng và chia sẻ trải nghiệm của bạn trên <a href="https://meetup.vn/">meetup.vn</a>.</p>
<img src="https://blog.logrocket.com/wp-content/uploads/2024/06/create-responsive-mobile-menu-css-without-javascript.png" alt="Ảnh minh họa Responsive Menu CSS không JavaScript trên các thiết bị" title="Responsive Menu CSS không JavaScript: Tổng quan hiển thị trên nhiều thiết bị">
<p>Việc xây dựng một menu điều hướng hoàn toàn bằng HTML và CSS mang lại lợi ích về hiệu suất và tính ổn định. Nó loại bỏ sự phụ thuộc vào các thư viện JavaScript bên ngoài, giúp trang web tải nhanh hơn và hoạt động mượt mà hơn, đặc biệt trên các thiết bị di động có tài nguyên hạn chế. Điều này đặc biệt quan trọng đối với một nền tảng như Meetup, nơi tốc độ tải trang ảnh hưởng trực tiếp đến khả năng người dùng tiếp cận các thông tin về thực đơn và địa điểm.</p>
<p>Trong các phần tiếp theo, chúng ta sẽ đi sâu vào từng bước cấu hình CSS để biến cấu trúc HTML cơ bản này thành một menu đáp ứng đầy đủ tính năng. Từ việc thiết lập các biến CSS cho màu sắc đến tạo hiệu ứng chuyển động và đảm bảo khả năng truy cập, mọi khía cạnh đều được xem xét kỹ lưỡng để mang lại một giải pháp menu tối ưu.</p>
</article>
</main>
</body>
</html>Trong đoạn mã HTML này, chúng ta sử dụng header và main là các thẻ ngữ nghĩa để phân tách thanh điều hướng và nội dung chính của trang. Một logo đơn giản được thêm vào bằng thẻ neo <a>. Điểm mấu chốt là việc tạo menu hamburger bằng “checkbox hack”. Với chiến lược này, chúng ta có thể tạo kiểu menu tùy thuộc vào trạng thái của hộp kiểm. Thẻ label được sử dụng để định nghĩa biểu tượng menu hamburger, trong khi thẻ input (với class side-menu) được sử dụng để hiển thị menu một cách có điều kiện tùy thuộc vào trạng thái của hộp kiểm. Cuối cùng, các mục menu được thêm vào dưới dạng các phần tử danh sách liên kết <li> trong một danh sách không có thứ tự <ul>, với thẻ nav đóng vai trò là container cho danh sách đó. Chúng ta cũng đã thêm các thuộc tính ARIA để cải thiện khả năng truy cập, giúp người dùng sử dụng trình đọc màn hình có thể hiểu rõ hơn về cấu trúc và chức năng của menu.
Bắt Đầu Với CSS: Định Dạng Nội Dung và Nền
Sau khi có cấu trúc HTML cơ bản, bước tiếp theo là áp dụng các kiểu CSS để làm cho trang web trở nên sống động và dễ nhìn. Chúng ta sẽ bắt đầu bằng việc thiết lập các kiểu dáng chung cho nội dung và nền trang, sau đó là các thành phần cụ thể như tiêu đề và logo.
/* Theming */
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap"); /* import font */
:root {
--white: #f9f9f9;
--black: #36383F;
--gray: #85888C;
--menu-background-color: #333; /* Màu nền tối cho menu */
--menu-text-color: #fff; /* Màu chữ trắng cho menu */
--hover-color: #ff9900; /* Màu khi di chuột vào */
}
/* Reset */
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: var(--white);
font-family: "Poppins", sans-serif;
line-height: 1.6; /* Tăng khoảng cách dòng để dễ đọc hơn */
color: var(--black);
}
a {
text-decoration: none;
color: inherit; /* Kế thừa màu chữ từ phần tử cha */
}
ul {
list-style: none;
}
p {
margin-bottom: 1em; /* Khoảng cách dưới cho mỗi đoạn văn */
}
main {
padding: 20px;
max-width: 960px; /* Giới hạn chiều rộng nội dung chính */
margin: 20px auto; /* Căn giữa nội dung chính */
background-color: #fff;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
border-radius: 8px;
}
h1 {
font-size: 2.5em;
margin-bottom: 0.8em;
color: var(--black);
text-align: center;
}
article p {
font-size: 1.1em;
line-height: 1.8;
}
article img {
max-width: 100%;
height: auto;
display: block;
margin: 20px auto;
border-radius: 5px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
/* Thêm các định nghĩa cho H2, H3 nếu cần */
h2 {
font-size: 2em;
margin-top: 1.5em;
margin-bottom: 0.6em;
color: var(--black);
}
h3 {
font-size: 1.5em;
margin-top: 1.2em;
margin-bottom: 0.5em;
color: var(--black);
}Đoạn mã CSS này bắt đầu bằng việc nhập phông chữ Poppins từ Google Fonts, mang lại vẻ ngoài hiện đại và chuyên nghiệp cho văn bản. Tiếp theo, chúng ta định nghĩa các biến CSS (--white, --black, --gray, v.v.) trong :root để dễ dàng quản lý màu sắc và các giá trị khác trong toàn bộ stylesheet. Việc sử dụng biến giúp việc cập nhật giao diện trở nên đơn giản hơn rất nhiều, chỉ cần thay đổi một giá trị duy nhất là toàn bộ các phần tử sử dụng biến đó sẽ được cập nhật.
Phần “Reset” được áp dụng để loại bỏ các cài đặt mặc định của trình duyệt cho margin, padding, box-sizing, text-decoration và list-style. Đây là một bước quan trọng để đảm bảo rằng các kiểu dáng của chúng ta sẽ được áp dụng một cách nhất quán trên các trình duyệt khác nhau, tránh các vấn đề về hiển thị không mong muốn. Sau đó, chúng ta chỉ định background-color trắng và font-family Poppins cho toàn bộ nội dung trang. Các quy tắc CSS bổ sung cho main, h1, p, img cũng được thêm vào để tạo kiểu cho nội dung chính, giới hạn chiều rộng, căn giữa và thêm đổ bóng nhẹ nhàng, mang lại một bố cục rõ ràng và dễ đọc. Việc định dạng các thẻ heading như h2 và h3 cũng quan trọng để duy trì cấu trúc nội dung và khả năng đọc.
Tạo Kiểu Cho Header và Logo: Nền Tảng Của Thanh Điều Hướng
Sau khi thiết lập các kiểu dáng chung, chúng ta sẽ tập trung vào việc định dạng phần đầu trang (header) và logo. Đây là những yếu tố đầu tiên mà người dùng nhìn thấy, vì vậy việc thiết kế chúng một cách thu hút và chức năng là rất quan trọng.
/* Header */
.header {
background-color: var(--menu-background-color); /* Sử dụng biến CSS cho màu nền */
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); /* Đổ bóng chuyên nghiệp hơn */
position: sticky; /* Giữ header ở phía trên khi cuộn */
top: 0;
width: 100%;
z-index: 1000; /* Đảm bảo header nằm trên các phần tử khác */
padding: 10px 20px; /* Thêm padding cho header */
display: flex; /* Sử dụng flexbox để căn chỉnh các mục */
align-items: center; /* Căn giữa theo chiều dọc */
justify-content: space-between; /* Đẩy logo và menu ra hai phía */
}
/* Logo */
.logo {
display: inline-block;
color: var(--menu-text-color); /* Sử dụng biến CSS cho màu chữ */
font-size: 2em; /* Kích thước chữ logo tương đối */
font-weight: 700; /* Chữ đậm */
text-transform: uppercase; /* Chữ hoa */
margin-left: 0; /* Bỏ margin-left vì đã dùng justify-content */
letter-spacing: 1px; /* Khoảng cách giữa các chữ cái */
}
.logo:hover {
color: var(--hover-color);
transition: color 0.3s ease;
}Đoạn mã này áp dụng màu nền tối (--menu-background-color) và đổ bóng nhẹ nhàng (box-shadow) cho header, tạo hiệu ứng nổi bật và chiều sâu. Thuộc tính position: sticky là chìa khóa để giữ header luôn hiển thị ở đầu màn hình khi người dùng cuộn trang. Điều này cực kỳ hữu ích cho việc điều hướng liên tục, đặc biệt trên các trang web có nội dung dài. Thuộc tính top: 0 đảm bảo header dính sát vào mép trên cùng của viewport. Việc sử dụng z-index: 1000 giúp header luôn nằm trên các nội dung khác, tránh bị che khuất.
Đối với logo, chúng ta thiết lập màu chữ trắng (--menu-text-color), kích thước chữ lớn hơn (font-size: 2em) và chữ in hoa (text-transform: uppercase) để làm nổi bật. Thuộc tính display: inline-block đảm bảo logo hiển thị đúng cách trong luồng văn bản, trong khi font-weight: 700 làm cho logo trở nên đậm và dễ đọc hơn. Hiệu ứng hover thay đổi màu chữ của logo khi di chuột qua, tạo phản hồi trực quan cho người dùng. Kỹ thuật margin liên quan đến khoảng trống xung quanh một phần tử, giúp tách biệt nó với các yếu tố khác trên trang. Trong trường hợp này, việc bỏ margin-left và sử dụng justify-content: space-between trong flexbox cho .header giúp căn chỉnh logo và menu một cách linh hoạt.
Định Hình Menu Điều Hướng: Xây Dựng Trái Tim Của Giao Diện
Sau khi đã định dạng header và logo, chúng ta sẽ chuyển sang phần quan trọng nhất: tạo kiểu cho menu điều hướng (nav). Đây là nơi các liên kết của bạn sẽ được hiển thị và tương tác.
/* Nav menu - mặc định cho mobile */
.nav {
width: 100%;
height: 100vh; /* Sử dụng 100vh để chiếm toàn bộ chiều cao viewport trên mobile */
position: fixed; /* Đặt menu cố định trên màn hình */
top: 60px; /* Hạ menu xuống dưới header */
left: 0;
background-color: var(--menu-background-color);
overflow-y: auto; /* Cho phép cuộn nếu nội dung menu dài hơn màn hình */
max-height: 0; /* Ẩn menu mặc định */
transition: max-height 0.5s ease-out; /* Tạo hiệu ứng trượt mượt mà */
padding-top: 0; /* Bỏ padding-top ban đầu */
box-shadow: 0 4px 8px rgba(0,0,0,0.1); /* Thêm bóng nhẹ cho menu */
}
.menu {
padding: 0;
}
.menu a {
display: block; /* Mỗi liên kết chiếm một hàng */
padding: 20px 30px; /* Tăng padding để dễ chạm hơn trên mobile */
color: var(--menu-text-color);
font-size: 1.1em;
border-bottom: 1px solid rgba(255, 255, 255, 0.1); /* Đường phân cách mỏng */
white-space: nowrap; /* Ngăn chặn xuống dòng cho các mục menu */
}
.menu a:hover {
background-color: var(--hover-color); /* Thay đổi màu nền khi di chuột */
color: var(--black); /* Đổi màu chữ khi hover */
transition: background-color 0.3s ease, color 0.3s ease;
}
.menu li:last-child a {
border-bottom: none; /* Bỏ đường kẻ cuối cùng */
}Trong đoạn mã này, chúng ta định nghĩa width và height của phần tử nav là 100% để nó chiếm toàn bộ chiều rộng và chiều cao của viewport trên thiết bị di động. Thuộc tính position: fixed rất quan trọng, nó đặt menu cố định trên màn hình, che phủ nội dung chính của ứng dụng khi được mở. Chúng ta cũng chọn màu nền đen (--menu-background-color) cho phần tử nav và chỉ định overflow-y: auto để cho phép cuộn nếu nội dung menu vượt quá chiều cao màn hình, đảm bảo tất cả các mục menu đều có thể truy cập được.
Đối với các phần tử liên kết trong menu, chúng ta chỉ định hiển thị block để mỗi liên kết chiếm một hàng riêng biệt, tăng cường khả năng tương tác trên thiết bị di động. Thêm padding và màu chữ (--menu-text-color) giúp các liên kết dễ nhìn và dễ chạm hơn. Hiệu ứng hover thay đổi background-color từ trắng sang xám (hoặc màu --hover-color đã định nghĩa) khi di chuột qua, cung cấp phản hồi trực quan cho người dùng.
Điểm mấu chốt để ẩn menu mặc định và tạo hiệu ứng đóng mở là sử dụng thuộc tính max-height của CSS kết hợp với transition. Mặc định, max-height được đặt là 0 để ẩn menu. Khi menu được kích hoạt, max-height sẽ được thay đổi thành một giá trị đủ lớn để hiển thị toàn bộ nội dung menu, tạo ra hiệu ứng trượt mượt mà nhờ thuộc tính transition. Điều này loại bỏ hoàn toàn nhu cầu sử dụng JavaScript để điều khiển hoạt ảnh, giúp menu hoạt động nhanh chóng và hiệu quả hơn.
Tạo Kiểu Cho Biểu Tượng Hamburger: Nút Điều Hướng Tinh Tế
Biểu tượng hamburger là một yếu tố không thể thiếu trong các menu đáp ứng trên thiết bị di động. Nó giúp tiết kiệm không gian và cung cấp một cách trực quan để người dùng mở và đóng menu.
/* Menu Icon (Hamburger) */
.hamb {
cursor: pointer; /* Hiển thị con trỏ dạng bàn tay khi di chuột */
padding: 20px; /* Tăng padding để dễ chạm */
position: relative; /* Để căn chỉnh các đường kẻ */
z-index: 1001; /* Đảm bảo nút hamburger nằm trên header và nav */
}
/* Style cho thẻ span tạo đường kẻ hamburger */
.hamb-line {
background: var(--white);
display: block;
height: 2px;
position: relative;
width: 24px;
border-radius: 2px; /* Bo tròn các góc của đường kẻ */
}
/* Tạo đường kẻ thứ nhất và thứ ba bằng pseudo-elements */
.hamb-line::before,
.hamb-line::after {
background: var(--white);
content: '';
display: block;
height: 100%;
position: absolute;
transition: all 0.3s ease-out; /* Hoạt ảnh mượt mà khi chuyển đổi */
width: 100%;
border-radius: 2px;
}
.hamb-line::before {
top: 7px; /* Vị trí đường kẻ phía trên */
}
.hamb-line::after {
top: -7px; /* Vị trí đường kẻ phía dưới */
}
/* Ẩn checkbox */
.side-menu {
display: none;
}Đoạn mã này định nghĩa kiểu dáng cho biểu tượng hamburger. Đầu tiên, chúng ta chỉ định con trỏ dạng bàn tay (cursor: pointer) khi người dùng tương tác với biểu tượng. Phần tử label (đại diện cho biểu tượng hamburger) được định vị ở bên phải và thêm một số padding để dễ tương tác. Tiếp theo, chúng ta tạo kiểu cho phần tử span để tạo ba đường kẻ của biểu tượng menu.
Chúng ta sử dụng các pseudo-elements CSS ::before và ::after trên phần tử span để định nghĩa ba đường kẻ của biểu tượng hamburger. .hamb-line chọn đường kẻ trung tâm (thứ hai). .hamb-line::before và .hamb-line::after định vị đường kẻ thứ nhất và thứ ba lần lượt 7px phía trên và dưới đường kẻ trung tâm. Điều này tạo ra hình dạng ba đường kẻ quen thuộc của biểu tượng hamburger. Cuối cùng, chúng ta sử dụng display: none cho .side-menu để ẩn hộp kiểm, vì nó chỉ được sử dụng cho mục đích điều khiển trạng thái bằng CSS. Việc này giúp giao diện người dùng trở nên gọn gàng và chuyên nghiệp hơn, không hiển thị các thành phần không cần thiết.
Tạo Hiệu Ứng Chuyển Đổi cho Biểu Tượng và Menu: Mở Rộng Trải Nghiệm Người Dùng
Để hoàn thiện chức năng của responsive menu CSS không JavaScript, chúng ta cần tạo hiệu ứng chuyển đổi khi người dùng nhấp vào biểu tượng hamburger. Điều này bao gồm việc hiển thị menu và biến đổi biểu tượng hamburger thành biểu tượng đóng (dấu X).
/* Toggle menu icon */
.side-menu:checked ~ nav {
max-height: 100vh; /* Hiển thị menu bằng cách đặt max-height đủ lớn */
transition: max-height 0.5s ease-in-out; /* Hiệu ứng trượt vào mượt mà */
}
.side-menu:checked ~ .hamb .hamb-line {
background: transparent; /* Ẩn đường kẻ giữa */
}
.side-menu:checked ~ .hamb .hamb-line::before {
transform: rotate(-45deg); /* Xoay đường kẻ trên */
top: 0; /* Di chuyển về giữa */
}
.side-menu:checked ~ .hamb .hamb-line::after {
transform: rotate(45deg); /* Xoay đường kẻ dưới */
top: 0; /* Di chuyển về giữa */
}
/* Vô hiệu hóa cuộn trang khi menu mở trên mobile */
body:has(.side-menu:checked) {
overflow: hidden;
}Đoạn mã này thực hiện việc chuyển đổi trạng thái của menu và biểu tượng hamburger khi hộp kiểm (.side-menu) được đánh dấu. Khi .side-menu được checked, bộ chọn ~ nav sẽ kích hoạt các kiểu CSS cho phần tử nav, đặt max-height thành 100vh để hiển thị menu. Thuộc tính transition đảm bảo menu trượt xuống một cách mượt mà, thay vì xuất hiện đột ngột.
Tiếp theo, chúng ta biến đổi biểu tượng hamburger thành hình chữ X. Đầu tiên, chúng ta ẩn đường kẻ giữa của biểu tượng bằng cách đặt background thành transparent. Sau đó, các pseudo-elements ::before và ::after (đại diện cho đường kẻ trên và dưới) được xoay lần lượt -45 độ và 45 độ, đồng thời di chuyển về vị trí trung tâm (top: 0), tạo thành hình chữ X. Thuộc tính transition: all .3s ease-out trên các pseudo-elements đảm bảo quá trình chuyển đổi này diễn ra mượt mà và đẹp mắt.
Cuối cùng, để nâng cao trải nghiệm người dùng trên thiết bị di động, chúng ta vô hiệu hóa khả năng cuộn trang khi menu được mở bằng cách sử dụng body:has(.side-menu:checked) { overflow: hidden; }. Điều này đảm bảo rằng người dùng sẽ tập trung vào menu và ngăn chặn việc cuộn nội dung nền một cách vô ý, mang lại một trải nghiệm người dùng chuyên nghiệp và tập trung hơn.
Đảm Bảo Tính Đáp Ứng Với Media Queries
Media queries là một công cụ mạnh mẽ trong CSS cho phép chúng ta áp dụng các kiểu dáng khác nhau tùy thuộc vào điều kiện của thiết bị (chẳng hạn như chiều rộng màn hình, chiều cao, hướng, v.v.). Đây là chìa khóa để tạo ra một responsive menu CSS không JavaScript hoạt động linh hoạt trên mọi kích thước màn hình.
/* Responsiveness */
@media (min-width: 768px) {
.hamb {
display: none; /* Ẩn biểu tượng hamburger trên màn hình lớn */
}
.side-menu:checked ~ nav {
max-height: none; /* Bỏ giới hạn chiều cao khi menu mở */
}
.nav {
max-height: none; /* Hiển thị menu đầy đủ */
top: 0;
position: relative; /* Đặt menu theo luồng tài liệu */
width: auto; /* Chiều rộng tự động */
background-color: transparent; /* Nền trong suốt */
box-shadow: none; /* Bỏ đổ bóng */
overflow: visible; /* Cho phép các submenu hiển thị */
display: flex; /* Sử dụng flexbox cho menu ngang */
justify-content: flex-end; /* Căn menu sang phải */
padding: 0;
}
.menu {
display: flex; /* Sử dụng flexbox cho các mục menu */
align-items: center; /* Căn giữa theo chiều dọc */
height: 100%;
}
.menu li {
margin: 0 10px; /* Khoảng cách giữa các mục menu */
position: relative; /* Cần thiết cho submenu */
}
.menu a {
padding: 15px 10px; /* Điều chỉnh padding cho màn hình lớn */
border-bottom: none; /* Bỏ đường phân cách */
color: var(--menu-text-color);
font-size: 1em;
}
.menu a:hover {
background-color: transparent; /* Nền trong suốt khi hover */
color: var(--hover-color); /* Thay đổi màu chữ khi hover */
}
/* Sub nav cho desktop */
.subnav-content {
padding: 10px 0;
display: none; /* Ẩn mặc định trên desktop */
background-color: var(--menu-background-color);
position: absolute; /* Đặt submenu tuyệt đối */
min-width: 160px; /* Chiều rộng tối thiểu */
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 100;
border-radius: 4px;
top: 100%; /* Đặt submenu bên dưới mục cha */
left: 0;
}
.subnav-content a {
color: var(--menu-text-color);
padding: 12px 16px;
text-align: left;
display: block;
font-size: 0.9em;
}
.subnav-content a:hover {
background-color: var(--hover-color);
color: var(--black);
}
.subnav:hover .subnav-content {
display: block; /* Hiển thị submenu khi di chuột vào mục cha */
}
.subnavbtn {
display: flex;
align-items: center;
}
.subnavbtn i {
margin-left: 5px;
font-size: 0.8em;
}
/* Cải thiện khả năng truy cập cho submenu trên desktop */
.subnavbtn:focus + .subnav-content,
.subnav:focus-within .subnav-content {
display: block; /* Hiển thị submenu khi focus vào nút hoặc bên trong submenu */
}
.subnav-content a:focus {
background-color: var(--hover-color);
color: var(--black);
}
body:has(.side-menu:checked) {
overflow: auto; /* Cho phép cuộn lại trên desktop khi menu mở */
}
}Trong đoạn mã này, chúng ta thêm một quy tắc @media với điều kiện thiết bị là min-width: 768px. Điều này có nghĩa là các thuộc tính CSS bên trong khối này sẽ chỉ được áp dụng cho các thiết bị có chiều rộng màn hình từ 768px trở lên (tức là máy tính bảng và máy tính để bàn).
Trên các màn hình lớn hơn, chúng ta muốn hiển thị menu điều hướng đầy đủ thay vì biểu tượng hamburger. Để làm điều này, chúng ta đặt display: none cho .hamb để ẩn biểu tượng hamburger. Các thuộc tính max-height: none, position: relative, top: 0, width: auto, background-color: transparent được áp dụng cho phần tử nav để nó hiển thị đầy đủ, theo luồng tài liệu và không có nền hoặc đổ bóng, tích hợp mượt mà vào header.
Các mục danh sách menu (.menu li) được đặt float: left hoặc sử dụng display: flex để chúng hiển thị nằm ngang. Padding và màu chữ của các liên kết được điều chỉnh cho phù hợp với bố cục màn hình lớn. Hiệu ứng hover trên các liên kết cũng được thay đổi để chỉ thay đổi màu chữ thành xám (--gray hoặc --hover-color), giữ cho nền trong suốt, phù hợp với thiết kế thanh điều hướng ngang.
Quan trọng hơn, chúng ta cũng đã thêm các kiểu dáng cho submenu để nó hiển thị dưới dạng dropdown khi di chuột qua trên màn hình lớn. Submenu được ẩn mặc định (display: none) và chỉ hiển thị khi subnav được hover. Các thuộc tính position: absolute, min-width, box-shadow được sử dụng để định vị và tạo kiểu cho submenu, đảm bảo nó trông chuyên nghiệp và dễ sử dụng. Các cải tiến về khả năng truy cập (accessibility) cũng được tích hợp, cho phép người dùng điều hướng submenu bằng bàn phím thông qua bộ chọn :focus và :focus-within.
![]()
So Sánh Menu Điều Hướng Cố Định, Tương Đối và Dính
Thuộc tính position trong CSS là một công cụ mạnh mẽ để định vị các phần tử trên trang web, và nó đóng vai trò quan trọng trong cách menu điều hướng của bạn tương tác với nội dung khi người dùng cuộn. Hiểu rõ sự khác biệt giữa fixed, relative và sticky sẽ giúp bạn lựa chọn phương pháp phù hợp nhất cho thiết kế của mình.
Vị Trí Cố Định (Fixed Positioning)
Với position: fixed, menu điều hướng sẽ luôn giữ nguyên vị trí trên viewport, bất kể người dùng cuộn trang đến đâu. Điều này có nghĩa là menu sẽ “dán” vào một vị trí cụ thể trên màn hình (ví dụ: top: 0, left: 0) và không thay đổi. Ưu điểm chính là menu luôn hiển thị và dễ truy cập, cung cấp khả năng điều hướng liên tục.
Tuy nhiên, nhược điểm là menu cố định có thể chồng lên một số nội dung trang nếu không được quản lý cẩn thận, đặc biệt trên các màn hình nhỏ. Nội dung trang sẽ điều chỉnh để vừa với khoảng trống còn lại, nhưng đôi khi có thể gây ra hiện tượng che khuất hoặc khó đọc. Điều này đặc biệt cần lưu ý khi thiết kế cho các thiết bị di động, nơi không gian màn hình là cực kỳ quý giá.
.header {
/* ... các thuộc tính khác ... */
position: fixed; /* Header sẽ luôn cố định ở vị trí này */
top: 0;
left: 0;
/* ... */
}Vị Trí Tương Đối (Relative Positioning)
position: relative đặt một phần tử tương đối với vị trí mặc định của chính nó trong luồng tài liệu. Khi bạn sử dụng các thuộc tính top, right, bottom, left với position: relative, phần tử sẽ di chuyển khỏi vị trí ban đầu nhưng không ảnh hưởng đến vị trí của các phần tử khác xung quanh nó.
Sự khác biệt chính ở đây là các nội dung khác trên trang không điều chỉnh để lấp đầy khoảng trống mà phần tử đã di chuyển để lại. Thay vào đó, khoảng trống ban đầu vẫn được giữ nguyên. Điều này có thể hữu ích cho các hiệu ứng nhỏ hoặc điều chỉnh vị trí tinh tế, nhưng thường không được dùng cho menu điều hướng chính vì nó không cung cấp khả năng “dính” vào màn hình khi cuộn và có thể gây ra các vấn đề về bố cục không mong muốn nếu di chuyển quá nhiều.
.header {
/* ... các thuộc tính khác ... */
position: relative; /* Header sẽ di chuyển tương đối */
top: 20px; /* Di chuyển xuống 20px so với vị trí ban đầu */
/* ... */
}Vị Trí Dính (Sticky Positioning)
position: sticky là một sự kết hợp linh hoạt giữa relative và fixed. Nó cho phép một phần tử hoạt động như relative cho đến khi nó đạt đến một ngưỡng cuộn nhất định (được xác định bởi top, right, bottom, hoặc left), sau đó nó sẽ hoạt động như fixed.
Điều này có nghĩa là thanh điều hướng sẽ cuộn cùng với nội dung khác cho đến khi nó chạm đến một vị trí offset đã chỉ định (ví dụ: top: 0). Sau khi đạt đến ngưỡng đó, nó sẽ “dính” vào vị trí đó và giữ nguyên khi người dùng tiếp tục cuộn. Ưu điểm lớn của sticky là nội dung trang không điều chỉnh để lấp đầy khoảng trống như fixed, mà sẽ cuộn bên dưới thanh điều hướng đã được định vị. Điều này tạo ra một trải nghiệm mượt mà và ít gây xáo trộn hơn cho người dùng, giúp menu luôn hiển thị khi cần thiết mà không chiếm quá nhiều không gian.
.header {
/* ... các thuộc tính khác ... */
position: sticky; /* Header sẽ dính khi đạt ngưỡng */
top: 0; /* Dính vào mép trên khi cuộn */
/* ... */
}Lựa chọn giữa các loại vị trí này phụ thuộc vào hành vi mong muốn của menu và thiết kế tổng thể của trang web. Đối với một menu điều hướng chính, sticky hoặc fixed thường là các lựa chọn tốt nhất để đảm bảo khả năng truy cập liên tục.

Tùy Biến Menu Nâng Cao: Cá Nhân Hóa Với CSS
Sau khi đã xây dựng một responsive menu CSS không JavaScript cơ bản, việc nâng cao vẻ ngoài của nó bằng các kỹ thuật tùy biến nâng cao sẽ giúp bạn tạo ra một thiết kế độc đáo và thu hút. CSS cung cấp nhiều công cụ mạnh mẽ để thêm chiều sâu, hiệu ứng thị giác và tương tác mà không cần phải dùng đến JavaScript.
Sử Dụng Biến CSS (CSS Variables)
Biến CSS, hoặc thuộc tính tùy chỉnh CSS, cho phép bạn định nghĩa các giá trị có thể tái sử dụng trong toàn bộ stylesheet của mình. Điều này giúp việc cập nhật kiểu dáng menu trở nên dễ dàng hơn nhiều, vì bạn chỉ cần thay đổi giá trị của biến ở một nơi duy nhất.
Chúng ta đã sử dụng biến CSS từ đầu bài viết để định nghĩa màu sắc. Đây là một ví dụ minh họa cách chúng giúp đơn giản hóa việc quản lý kiểu dáng:
/* Định nghĩa biến CSS cho màu sắc */
:root {
--menu-background-color: #2c3e50; /* Màu nền xanh đậm */
--menu-text-color: #ecf0f1; /* Màu chữ trắng nhạt */
--hover-color: #3498db; /* Màu xanh sáng khi di chuột */
--shadow-color: rgba(0, 0, 0, 0.3); /* Màu đổ bóng */
}
/* Sử dụng biến CSS trong các kiểu menu */
.nav {
background-color: var(--menu-background-color);
/* ... các thuộc tính khác ... */
}
.menu a {
color: var(--menu-text-color);
/* ... các thuộc tính khác ... */
}
.menu a:hover {
background-color: var(--hover-color);
color: var(--black);
}Bằng cách sử dụng biến, nếu bạn quyết định thay đổi bảng màu của trang web, bạn chỉ cần điều chỉnh các giá trị trong khối :root và toàn bộ menu sẽ tự động cập nhật, tiết kiệm thời gian và đảm bảo tính nhất quán.
Hiệu Ứng Gradient và Đổ Bóng (Gradients and Shadows)
Gradient và đổ bóng CSS có thể được sử dụng để thêm chiều sâu và sự hấp dẫn thị giác cho menu của bạn, làm cho nó trở nên sống động hơn.
/* Thêm nền gradient cho menu */
.nav {
background-image: linear-gradient(to bottom, var(--menu-background-color), #4a69bd); /* Gradient từ đậm đến nhạt */
/* ... */
}
/* Thêm đổ bóng cho menu khi nó mở */
.side-menu:checked ~ nav {
box-shadow: 0 5px 15px var(--shadow-color); /* Đổ bóng với hiệu ứng mờ */
}
/* Đổ bóng cho các mục menu khi hover (tinh tế) */
.menu a:hover {
box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.2); /* Đổ bóng bên trong khi hover */
/* ... */
}linear-gradient tạo ra một sự chuyển đổi màu sắc mượt mà, từ màu --menu-background-color sang một màu xanh lam khác (#4a69bd), mang lại cảm giác hiện đại và cao cấp. box-shadow được sử dụng để tạo hiệu ứng đổ bóng bên dưới menu khi nó mở, làm nổi bật menu so với nội dung nền. Việc sử dụng inset cho box-shadow khi hover sẽ tạo ra một hiệu ứng đổ bóng bên trong, làm cho các mục menu trông như được nhấn chìm nhẹ nhàng, tăng thêm sự tinh tế cho tương tác.
Hiệu Ứng Di Chuột (Hover Effects)
Thêm hiệu ứng di chuột vào các mục menu có thể tăng cường khả năng tương tác của người dùng và cung cấp phản hồi trực quan. Với CSS, bạn có thể dễ dàng tạo các hiệu ứng di chuột thay đổi màu sắc, kích thước hoặc kiểu dáng của các mục menu khi người dùng di chuột qua chúng.
/* Thay đổi màu chữ khi di chuột */
.menu a:hover {
color: var(--hover-color);
background-color: var(--menu-background-color); /* Giữ nền đồng nhất trên mobile */
/* ... */
}
/* Thêm gạch chân khi di chuột */
.menu a:hover {
text-decoration: underline;
text-decoration-color: var(--hover-color); /* Màu gạch chân */
text-underline-offset: 5px; /* Khoảng cách gạch chân */
}
/* Hiệu ứng phóng to khi di chuột (chỉ áp dụng trên desktop) */
@media (min-width: 768px) {
.menu li {
transition: transform 0.3s ease-out; /* Thêm transition cho hiệu ứng phóng to */
}
.menu li:hover {
transform: scale(1.05); /* Tăng kích thước 5% khi di chuột */
}
}
/* Hiệu ứng mờ dần/hiện ra khi di chuột */
.menu a {
opacity: 0.8; /* Độ mờ ban đầu */
transition: opacity 0.3s ease; /* Thêm transition để hiệu ứng mượt mà */
}
.menu a:hover {
opacity: 1; /* Hiển thị đầy đủ khi di chuột */
}Các ví dụ trên cho thấy cách sử dụng pseudo-class :hover trong CSS. Chúng ta có thể thay đổi màu chữ và màu nền, thêm gạch chân, hoặc thậm chí tạo hiệu ứng phóng to (transform: scale) hoặc làm mờ/hiện ra (opacity). Quan trọng là áp dụng transition cho các thuộc tính này để đảm bảo hiệu ứng diễn ra mượt mà, không bị giật cục, mang lại trải nghiệm chuyên nghiệp hơn cho người dùng. Đối với hiệu ứng phóng to, việc áp dụng nó chỉ trên desktop thông qua media query sẽ phù hợp hơn để tránh các vấn đề về chạm trên mobile.
Tạo Hiệu Ứng Động cho Các Mục Menu (Animating Menu Items)
Kết hợp các hiệu ứng động tinh tế như trượt hoặc mờ dần có thể làm cho menu của bạn trở nên hấp dẫn và thu hút hơn đối với người dùng.
/* Định nghĩa hoạt ảnh trượt vào */
@keyframes slideIn {
from {
transform: translateY(-20px); /* Bắt đầu từ phía trên một chút */
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
/* Áp dụng hoạt ảnh cho các mục menu khi menu mở */
.side-menu:checked ~ nav .menu li {
animation: slideIn 0.4s forwards; /* Hoạt ảnh trượt vào */
opacity: 0; /* Mặc định ẩn trước khi hoạt ảnh */
}
/* Trì hoãn hoạt ảnh cho từng mục menu */
.side-menu:checked ~ nav .menu li:nth-child(1) { animation-delay: 0.1s; }
.side-menu:checked ~ nav .menu li:nth-child(2) { animation-delay: 0.2s; }
.side-menu:checked ~ nav .menu li:nth-child(3) { animation-delay: 0.3s; }
.side-menu:checked ~ nav .menu li:nth-child(4) { animation-delay: 0.4s; }
.side-menu:checked ~ nav .menu li:nth-child(5) { animation-delay: 0.5s; }
/* ... Thêm delay cho các mục khác nếu có */Trong ví dụ này, chúng ta định nghĩa một hoạt ảnh slideIn sử dụng @keyframes. Hoạt ảnh này làm cho các mục menu di chuyển từ trên xuống (translateY(-20px)) và dần hiện ra (opacity: 0 đến opacity: 1). Sau đó, chúng ta áp dụng hoạt ảnh này cho từng mục menu (.menu li) khi menu được mở (.side-menu:checked ~ nav). Thuộc tính forwards đảm bảo rằng trạng thái cuối cùng của hoạt ảnh sẽ được giữ lại.
Để làm cho hiệu ứng động trở nên mượt mà và chuyên nghiệp hơn, chúng ta có thể thêm animation-delay cho từng mục menu con bằng cách sử dụng bộ chọn :nth-child(). Điều này tạo ra hiệu ứng “dàn trải” hoặc “xếp tầng”, nơi mỗi mục menu xuất hiện sau mục trước đó một khoảng thời gian ngắn, làm tăng tính thẩm mỹ và trải nghiệm người dùng.
Cải Thiện Khả Năng Truy Cập Với Thuộc Tính ARIA
Khả năng truy cập (accessibility) là một khía cạnh cực kỳ quan trọng trong phát triển web, đảm bảo rằng mọi người, bao gồm cả những người khuyết tật, đều có thể truy cập và sử dụng website của bạn một cách hiệu quả. Các thuộc tính ARIA (Accessible Rich Internet Applications) đóng vai trò then chốt trong việc làm cho nội dung web của bạn dễ tiếp cận hơn.
Chúng ta đã tích hợp một số thuộc tính ARIA trong cấu trúc HTML ban đầu. Bây giờ, chúng ta sẽ đi sâu hơn vào ý nghĩa và cách sử dụng chúng để cải thiện responsive menu CSS không JavaScript của mình.
<header class="header" role="banner">
<a href="https://meetup.vn/" class="logo" aria-label="Logo Meetup.vn - Về trang chủ">Meetup</a>
<input class="side-menu" type="checkbox" id="side-menu" aria-controls="main-navigation" aria-expanded="false" aria-label="Nút mở/đóng menu điều hướng"/>
<label class="hamb" for="side-menu" aria-label="Mở menu điều hướng">
<span class="hamb-line"></span>
</label>
<nav class="nav" role="navigation" aria-label="Menu Chính">
<ul class="menu" id="main-navigation">
<li><a href="#" role="menuitem">Trang Chủ</a></li>
<li><a href="#" role="menuitem">Món Ăn Đặc Trưng</a></li>
<li class="subnav" role="none"> <!-- role="none" vì li là container cho subnavbtn và ul -->
<a href="#" class="subnavbtn" aria-haspopup="true" aria-expanded="false" role="menuitem">Địa Điểm <i class="fa fa-caret-down"></i></a>
<ul class="subnav-content" role="menu">
<li role="none"><a href="#" role="menuitem">Nhà Hàng</a></li>
<li role="none"><a href="#" role="menuitem" aria-current="page">Quán Cafe</a></li> <!-- Ví dụ mục hiện tại -->
<li role="none"><a href="#" role="menuitem">Quán Bar</a></li>
</ul>
</li>
<li><a href="#" role="menuitem">Đánh Giá</a></li>
<li><a href="#" role="menuitem">Liên Hệ</a></li>
</ul>
</nav>
</header>Trong đoạn mã trên, chúng ta đã thêm một số thuộc tính ARIA quan trọng:
role="banner"vào thẻ<header>giúp trình đọc màn hình xác định nó là một landmark (điểm mốc) biểu ngữ, làm cho việc điều hướng trở nên trực quan hơn.role="navigation"cho thẻ<nav>làm rõ mục đích của nó đối với các công nghệ hỗ trợ, giúp người dùng dễ dàng tìm thấy các liên kết điều hướng chính.aria-labelđược thêm vào logo và biểu tượng hamburger cung cấp văn bản mô tả rõ ràng mục đích của các phần tử này, đảm bảo người dùng hiểu chức năng của chúng ngay cả khi không nhìn thấy giao diện. Ví dụ:aria-label="Logo Meetup.vn - Về trang chủ".aria-controls="main-navigation"trêninputcheckbox chỉ ra rằng checkbox này điều khiển phần tử cóid="main-navigation"(tức làulcủa menu).aria-expanded="false"ban đầu trên checkbox cho biết menu đang đóng. Khi checkbox đượcchecked, chúng ta có thể cập nhật thuộc tính này thànhtruebằng JavaScript nếu muốn, nhưng với CSS thuần, nó sẽ phản ánh trạng thái đóng/mở.role="menuitem"được thêm vào các thẻ<a>trong<ul>giúp xác định chúng là các mục trong một menu, giúp trình đọc màn hình hiểu rõ hơn về ngữ cảnh.aria-current="page"được thêm vào liên kết “Quán Cafe” để chỉ ra rằng đây là trang hiện tại mà người dùng đang truy cập, cung cấp phản hồi rõ ràng về vị trí của họ trên trang web.aria-haspopup="true"trên nút “Địa Điểm” (subnavbtn) cho trình đọc màn hình biết rằng phần tử này có một menu con hoặc popup liên quan.role="menu"được thêm vàoulcủa submenu, chỉ ra rằng đây là một tập hợp các mục menu.
Cải Thiện Trải Nghiệm Điều Hướng Bằng Bàn Phím
Đối với người dùng sử dụng bàn phím để điều hướng, việc đảm bảo submenu hoạt động tốt là rất quan trọng.
@media (min-width: 768px) {
/* ... các thuộc tính media query khác ... */
/* Subnav content */
.subnav-content li {
display: block;
width: 100%;
background-color: var(--menu-background-color);
}
/* Hiển thị submenu khi nút cha được focus */
.subnavbtn:focus + .subnav-content,
.subnav:focus-within .subnav-content {
display: block;
}
/* Đổi màu nền khi focus vào các mục submenu */
.subnav-content a:focus {
background-color: var(--hover-color);
color: var(--black);
outline: 2px solid var(--hover-color); /* Thêm viền nổi bật khi focus */
outline-offset: -2px;
}
}Đoạn mã CSS này cải thiện khả năng hiển thị và khả năng sử dụng của submenu. Các mục submenu được hiển thị dưới dạng khối (display: block) để đảm bảo chúng được định vị chính xác trong dropdown. Chúng ta cũng thêm các kiểu dáng để làm nổi bật các mục submenu khi chúng được focus, giúp người dùng bàn phím dễ dàng nhìn thấy mục nào đang được chọn.
Để đảm bảo submenu vẫn hiển thị trong quá trình tương tác, chúng ta cập nhật thuộc tính display cho submenu thành block khi liên kết cha (.subnavbtn) được focus hoặc khi bất kỳ phần tử nào bên trong subnav được focus (sử dụng :focus-within). Sự thay đổi này đảm bảo trải nghiệm liền mạch hơn cho tất cả người dùng, đặc biệt là những người dựa vào bàn phím để điều hướng website.
Menu Điều Hướng Di Động Ngang so với Dọc
Khi thiết kế một responsive menu CSS không JavaScript cho thiết bị di động, bạn có thể lựa chọn hiển thị menu theo chiều ngang hoặc chiều dọc, tùy thuộc vào sở thích và mục tiêu thiết kế. Mỗi cách bố trí đều có những ưu và nhược điểm riêng ảnh hưởng đến trải nghiệm người dùng.
Ưu và Nhược Điểm của Menu Điều Hướng Di Động Ngang (Horizontal Mobile Navbar)
Menu điều hướng ngang là lựa chọn phổ biến hơn, thường được sử dụng trên hầu hết các website. Thứ tự từ trái sang phải tự nhiên hơn đối với người nói tiếng Việt. Ngoài ra, bố cục này khuyến khích mô tả liên kết điều hướng ngắn gọn hơn trên menu.
Ưu điểm:
- Quen thuộc và Trực quan: Hầu hết người dùng đã quen thuộc với menu ngang, giúp họ dễ dàng hiểu và sử dụng.
- Tiết kiệm không gian chiều dọc: Không chiếm nhiều không gian trên màn hình theo chiều dọc, giữ cho nội dung chính của trang hiển thị rõ ràng.
- Khuyến khích nội dung ngắn gọn: Buộc các nhà thiết kế phải sử dụng các nhãn menu ngắn gọn và súc tích.
Nhược điểm:
- Không gian hạn chế: Bố cục này cung cấp không gian hạn chế cho việc thêm các liên kết, đặc biệt khi có nhiều mục.
- Khó thêm các liên kết cấp cao: Việc thêm các liên kết cấp cao mới có thể là một thách thức.
- Menu thả xuống có thể chồng chéo: Các menu thả xuống (dropdown) có thể chồng chéo lên nội dung web, gây khó chịu cho người dùng.
Ưu và Nhược Điểm của Menu Điều Hướng Di Động Dọc (Vertical Mobile Navbar)
Ngược lại với bố cục ngang, menu điều hướng dọc thường được sắp xếp dọc theo một bên của trang và thường được mở/đóng bằng một nút hamburger.
Ưu điểm:
- Nhiều không gian hơn cho liên kết: Cung cấp nhiều không gian hơn cho các liên kết bổ sung.
- Mô tả liên kết dài hơn: Tên của các liên kết điều hướng có thể dài hơn mà không gây ra vấn đề về bố cục.
- Dễ dàng thêm liên kết mới: Việc bổ sung các liên kết mới đơn giản hơn vì có nhiều không gian hơn.
- Thích hợp cho nội dung đa dạng: Rất phù hợp với các trang web có nhiều danh mục hoặc cấp độ thông tin sâu.
Nhược điểm:
- Ít phổ biến và trực quan hơn: Bố cục này ít phổ biến và có thể không quen thuộc với một số người dùng, dẫn đến khó khăn khi sử dụng.
- Có thể chiếm nhiều không gian: Khi mở, menu dọc có thể chiếm một phần đáng kể không gian màn hình, che khuất nội dung chính.
- Khó tiếp cận submenu: Người dùng có thể gặp khó khăn khi truy cập các submenu mở rộng sang bên cạnh so với menu ngang có submenu mở rộng xuống dưới.
- Dễ lộn xộn: Sự linh hoạt về không gian có thể dẫn đến việc tạo ra các liên kết điều hướng không được tổ chức hoặc quá dài, gây lộn xộn.
Lựa chọn giữa menu điều hướng ngang và dọc phụ thuộc vào số lượng liên kết, độ phức tạp của cấu trúc website và đối tượng người dùng mục tiêu. Đối với meetup.vn, một nền tảng với nhiều danh mục món ăn và địa điểm, một menu dọc có thể cung cấp không gian linh hoạt hơn để hiển thị các lựa chọn một cách rõ ràng trên di động, trong khi menu ngang sẽ phù hợp hơn cho desktop.
Tối Ưu Hiệu Suất Và Các Thực Hành Tốt Nhất
Việc xây dựng một responsive menu CSS không JavaScript không chỉ dừng lại ở chức năng và thẩm mỹ, mà còn bao gồm cả hiệu suất và tuân thủ các thực hành tốt nhất trong phát triển web.
Hiệu Suất (Performance)
- Tải trang nhanh hơn: Việc loại bỏ JavaScript cho các chức năng cơ bản giúp giảm kích thước tệp và số lượng yêu cầu HTTP, từ đó làm tăng tốc độ tải trang. Điều này đặc biệt quan trọng đối với người dùng di động, những người có thể có kết nối internet không ổn định.
- Giảm tải cho CPU: JavaScript yêu cầu bộ xử lý của thiết bị phải chạy các tập lệnh, tiêu tốn tài nguyên CPU và pin. Menu chỉ với CSS không gây ra gánh nặng này, giúp thiết bị hoạt động mượt mà hơn và kéo dài thời lượng pin.
- Độ tin cậy cao: Menu CSS sẽ hoạt động ngay cả khi JavaScript bị vô hiệu hóa hoặc gặp lỗi, đảm bảo tính bền vững của trải nghiệm điều hướng.
Các Thực Hành Tốt Nhất (Best Practices)
- Mobile-First Design: Luôn bắt đầu thiết kế cho màn hình nhỏ nhất. Điều này giúp bạn tập trung vào những gì thiết yếu và đảm bảo hiệu suất tốt nhất cho đối tượng người dùng di động đông đảo.
- Sử dụng biến CSS: Quản lý màu sắc, phông chữ và các giá trị khác bằng biến CSS để dễ dàng bảo trì và cập nhật giao diện.
- Khả năng truy cập (Accessibility): Tích hợp các thuộc tính ARIA và đảm bảo menu có thể điều hướng bằng bàn phím. Điều này mở rộng phạm vi tiếp cận của trang web đến tất cả người dùng.
- Kiểm tra trên nhiều thiết bị: Luôn kiểm tra menu trên nhiều kích thước màn hình và trình duyệt khác nhau để đảm bảo tính nhất quán và không có lỗi hiển thị.
- Duy trì đơn giản: Tránh các hiệu ứng động quá phức tạp hoặc menu có quá nhiều cấp độ. Một menu đơn giản, rõ ràng sẽ luôn mang lại trải nghiệm tốt hơn.
- Cung cấp phản hồi trực quan: Sử dụng hiệu ứng hover và active để cho người dùng biết khi họ tương tác với các mục menu.
Bằng cách tuân thủ những nguyên tắc này, bạn không chỉ xây dựng được một responsive menu CSS không JavaScript mạnh mẽ mà còn đảm bảo rằng website của bạn, như meetup.vn, mang lại trải nghiệm tối ưu, nhanh chóng và dễ tiếp cận cho mọi người dùng. Điều này không chỉ giúp giữ chân khách truy cập mà còn cải thiện thứ hạng SEO của bạn.
Kết Luận
Trong hướng dẫn chi tiết này, chúng ta đã cùng nhau thiết kế và xây dựng một responsive menu CSS không JavaScript từ đầu, tuân thủ triết lý mobile-first. Bằng cách tận dụng sức mạnh của HTML và CSS thuần túy, bao gồm kỹ thuật “checkbox hack”, media queries, biến CSS, hiệu ứng gradient, đổ bóng, và hoạt ảnh, chúng ta đã tạo ra một menu điều hướng không chỉ hoạt động hiệu quả trên mọi thiết bị mà còn mang lại trải nghiệm người dùng mượt mà, trực quan và có tính thẩm mỹ cao. Đặc biệt, việc tích hợp các thuộc tính ARIA đã nâng cao đáng kể khả năng tiếp cận, đảm bảo rằng menu của bạn có thể được sử dụng bởi mọi đối tượng người dùng. Phương pháp này không chỉ giảm thiểu sự phụ thuộc vào JavaScript, cải thiện hiệu suất tải trang mà còn đơn giản hóa quy trình phát triển và bảo trì. Kỹ thuật được trình bày chỉ là một trong nhiều cách để xây dựng một menu di động đáp ứng, khuyến khích bạn thử nghiệm và khám phá các phương pháp khác nhau để tìm ra giải pháp phù hợp nhất với nhu cầu dự án của mình, góp phần xây dựng một website như meetup.vn vững chắc và thân thiện với người dùng.
Ngày Cập Nhật: Tháng 8 29, 2025 by Nguyễn Jun


