Việc triển khai wordpress custom menu là kỹ năng nền tảng cho bất kỳ nhà phát triển theme nào. Menu mặc định thường bị giới hạn về vị trí và kiểu dáng. Bài viết này hướng dẫn chi tiết cách đăng ký và hiển thị các vị trí menu mới. Chúng ta sẽ làm việc trực tiếp với file Functions.php và theme’s template. Việc này giúp tối ưu hiệu suất trang web. Nó cũng mang lại sự linh hoạt cao hơn nhiều so với việc dựa vào các plugin. Bạn sẽ nắm vững hàm lõi register_nav_menu và hàm hiển thị wp_nav_menu.
Tại Sao Cần Tùy Biến Vị Trí Menu Trong WordPress?
Các theme WordPress thường chỉ cung cấp một hoặc hai vị trí menu mặc định. Chúng thường nằm ở header hoặc footer. Tuy nhiên, nhiều dự án đòi hỏi cấu trúc phức tạp hơn. Ví dụ, một menu cho sidebar, một menu cho thanh thông báo, hoặc menu cho Custom Post Types cụ thể.
Tùy biến cho phép bạn kiểm soát hoàn toàn vị trí hiển thị. Bạn có thể đặt menu tại bất cứ đâu trong cấu trúc theme. Điều này giúp cải thiện trải nghiệm người dùng. Nó cũng giúp quản lý nội dung tốt hơn.
Việc không sử dụng plugin cho các tác vụ cơ bản này là cần thiết. Nó giúp giảm thiểu rủi ro bảo mật và xung đột. Đồng thời, code lõi của theme sẽ gọn gàng và tải nhanh hơn. Đây là phương pháp chuyên nghiệp được cộng đồng WordPress khuyến nghị.
Đăng Ký Vị Trí Menu Tùy Chỉnh Mới (Register Custom Menu Location)
Bước đầu tiên để có wordpress custom menu là khai báo vị trí của nó. Khai báo này được thực hiện trong file functions.php của theme đang hoạt động. Bạn nên sử dụng trình soạn thảo văn bản chuyên nghiệp như Sublime Text để chỉnh sửa.
Sử dụng register_nav_menu()
Bạn cần mở file functions.php của theme. Sau đó, thêm đoạn mã sau vào cuối file. Đoạn mã này sử dụng hook add_action để gọi hàm đăng ký.
function my_custom_menu() { register_nav_menu('my-custom-menu',__( 'My Custom Menu' )); } add_action( 'init', 'my_custom_menu' );Hàm add_action() móc chức năng của chúng ta vào hành động init. Hành động init chạy cùng với các hàm cốt lõi khác của WordPress. Điều này đảm bảo menu được đăng ký ngay khi WordPress khởi tạo.
Tham số đầu tiên 'my-custom-menu' là tên ID nội bộ (slug) của menu. Tên này được dùng để tham chiếu trong code. Tham số thứ hai, 'My Custom Menu', là phiên bản dễ đọc mà bạn sẽ thấy trong khu vực quản trị.
Đăng ký nhiều menu bằng register_nav_menus()
Nếu dự án yêu cầu nhiều vị trí menu tùy chỉnh, bạn có thể sử dụng hàm register_nav_menus() thay thế. Hàm này chấp nhận một mảng các vị trí menu. Mỗi vị trí được định nghĩa bằng một cặp ID và tên hiển thị.
Dưới đây là ví dụ đăng ký hai vị trí menu cùng lúc:
function my_custom_menu() { register_nav_menus( array( 'my-custom-menu' => _( 'My Custom Menu' ), 'my-custom-menu-2' =>_('My Second Custom Menu') ) ); } add_action( 'init', 'my_custom_menu' );Sau khi thêm và lưu file functions.php, bạn cần kiểm tra lại kết quả. Truy cập khu vực quản trị WordPress. Điều hướng đến Appearance > Menus. Trong cài đặt Menu (Menu Settings), bạn sẽ thấy vị trí menu tùy chỉnh đã được liệt kê.
Lưu ý rằng việc đăng ký chỉ là bước khai báo vị trí. Tại thời điểm này, menu sẽ chưa hiển thị bất cứ thứ gì ở giao diện người dùng (frontend). Chúng ta cần thêm code hiển thị ở bước tiếp theo.
Hiển Thị Menu Tùy Chỉnh Ra Giao Diện Người Dùng
Để menu hiển thị, chúng ta cần chèn một hàm đặc biệt vào file template của theme. Vị trí chèn sẽ quyết định nơi menu xuất hiện trên trang.
Thêm code vào Theme Template (ví dụ: header.php)
Giả sử chúng ta muốn menu tùy chỉnh xuất hiện ngay dưới menu chính của theme. Trong ví dụ này, chúng ta sử dụng theme Twenty Twenty. Chúng ta sẽ chỉnh sửa file header.php. File này thường nằm trong thư mục gốc của theme.
Mở file header.php và tìm kiếm phần tử liên quan đến header theme. Trong theme Twenty Twenty, đoạn code sau thường nằm xung quanh dòng 33.
<div class="header-navigation-wrapper">Ngay dưới phần tử này, chúng ta sẽ chèn hàm wp_nav_menu(). Hàm này chịu trách nhiệm hiển thị menu.
Giao diện file header.php của theme Twenty Twenty, nơi chèn code hiển thị wordpress custom menu
Đây là đoạn code cần chèn:
wp_nav_menu( array( 'theme_location' => 'my-custom-menu' ) ); Giá trị của theme_location phải trùng khớp tuyệt đối với ID nội bộ (my-custom-menu) đã đăng ký trong functions.php. Điều này tạo ra sự liên kết giữa vị trí khai báo và vị trí hiển thị. Hàm này sẽ tự động tìm menu đã được gán cho vị trí đó và render ra HTML.
Tạo Menu Test và Gán Vị Trí
Trước khi kiểm tra giao diện, chúng ta cần tạo một menu thực tế. Quay lại Appearance > Menus trong khu vực quản trị. Tạo một menu mới, ví dụ đặt tên là “Secondary Menu”.
Quan trọng là phải chọn vị trí hiển thị là “My Custom Menu” (tên dễ đọc) trong Menu Settings. Sau đó, nhấn “Create Menu”. Thêm vài mục menu như “Menu item 1”, “Menu item 2”, v.v., và lưu lại.
Giao diện tạo Menu phụ (Secondary Menu) trong quản trị WordPress và gán vị trí My Custom Menu
Kiểm tra giao diện frontend, menu mới sẽ xuất hiện. Tuy nhiên, giao diện mặc định có thể không đẹp. WordPress sử dụng các thẻ <ul> và <li> cơ bản.
Kết quả hiển thị ban đầu của menu tùy chỉnh (wordpress custom menu) trước khi áp dụng CSS
Tùy chỉnh giao diện bằng CSS
Menu mới hiển thị cần được tạo kiểu để phù hợp với theme. Hàm wp_nav_menu() tự động tạo ra một cấu trúc HTML với các ID và class nhất định.
Cấu trúc HTML được tạo ra sẽ giống như sau (tùy thuộc vào tên menu bạn đặt):
<div class="menu-secondary-menu-container">
<ul id="menu-secondary-menu" class="menu">
<li id="menu-item-12" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-12">
<a href="#">Menu item 1</a>
</li>
<!-- ... các menu item khác ... -->
</ul>
</div>Chúng ta sẽ sử dụng ID hoặc Class này để áp dụng CSS. Mở file style.css của theme (thường cùng vị trí với header.php). Thêm các quy tắc CSS để làm đẹp menu.
ul#menu-secondary-menu {
text-align: right;
padding: 10px 30px;
}
ul#menu-secondary-menu li {
list-style: none;
display: inline-block;
padding: 1px;
}
ul#menu-secondary-menu li:hover {
border: 1px solid #c00202;
padding: 0;
border-radius: 3px;
}
ul#menu-secondary-menu li a {
text-decoration: none;
padding: 5px;
font-size: 14px;
}Với việc áp dụng CSS này, menu sẽ trông gọn gàng và chuyên nghiệp hơn. Nó phù hợp hơn với phong cách thiết kế của website. Đây là bước quan trọng trong việc hoàn thiện wordpress custom menu.
Các Tham Số Tùy Biến Nâng Cao Cho Hàm wp_nav_menu()
Hàm wp_nav_menu() cực kỳ mạnh mẽ. Nó cung cấp hàng loạt tham số (arguments) để tùy chỉnh đầu ra HTML. Hiểu rõ các tham số này giúp bạn có thể kiểm soát chi tiết mọi khía cạnh của menu.
Tùy chỉnh ID và Class (menu_id, menu_class)
Hai tham số này cho phép bạn định nghĩa các thuộc tính CSS cho thẻ <ul> chứa menu.
Tham số menu_class cho phép bạn chỉ định lớp CSS riêng cho menu. Lớp này được thêm vào thẻ <ul>. Nó không thay thế các lớp mặc định.
wp_nav_menu( array(
'theme_location' => 'my-custom-menu',
'menu_class' => 'my-custom-menu-class'
) ); Khi kiểm tra mã nguồn, bạn sẽ thấy lớp mới được thêm vào. Điều này giúp tăng tính đặc hiệu khi viết CSS.
Kiểm tra mã nguồn HTML sau khi áp dụng tham số menu_class cho wordpress custom menu
Tham số menu_id hoạt động khác. Nó sẽ thay thế ID mặc định của thẻ <ul>. Nếu không sử dụng tham số này, ID mặc định thường là slug của menu. ID này sẽ tự tăng nếu bạn gọi hàm nhiều lần.
wp_nav_menu( array(
'theme_location' => 'my-custom-menu',
'menu_id' => 'custom-unique-id'
) );
// Kết quả HTML: <ul id="custom-unique-id" class="menu">...</ul>Kiểm soát phần tử bao quanh (container, container_class)
Theo mặc định, WordPress bao quanh thẻ <ul> bằng thẻ <div>. Bạn có thể thay đổi loại phần tử bao quanh này bằng tham số container.
Nếu muốn sử dụng thẻ <nav> thay cho <div>, bạn thiết lập như sau:
wp_nav_menu( array(
'theme_location' => 'my-custom-menu',
'container' => 'nav',
) ); Nếu bạn không muốn có phần tử bao quanh nào, chỉ cần đặt container là false hoặc một chuỗi rỗng.
Tham số container_class cho phép bạn áp dụng lớp CSS cho phần tử bao quanh. Điều này hữu ích để tạo kiểu cho vùng chứa menu.
wp_nav_menu( array(
'theme_location' => 'my-custom-menu',
'container_class' => 'my-custom-menu-wrapper',
) ); Kết quả sẽ tạo ra thẻ chứa có lớp tùy chỉnh.
Mã nguồn HTML hiển thị phần tử bao quanh container_class của vị trí menu mới trong WordPress
Thêm nội dung trước và sau liên kết (before, after, link_before, link_after)
Các tham số này cho phép bạn chèn nội dung vào cấu trúc menu ở cấp độ item và link.
before: Nội dung được chèn ngay trước thẻ<li class="menu-item">.after: Nội dung được chèn ngay sau thẻ</li>.link_before: Nội dung được chèn ngay trước thẻ<a>.link_after: Nội dung được chèn ngay sau thẻ</a>.
Ví dụ, để bọc văn bản liên kết trong thẻ <span>, chúng ta sử dụng link_before và link_after.
wp_nav_menu( array(
'theme_location' => 'my-custom-menu',
'link_before' => '<span>',
'link_after' => '</span>',
) );Bạn có thể chèn các biểu tượng (icons) bằng cách sử dụng các tham số này. Nếu bạn đã cài đặt plugin Font Awesome, bạn có thể thêm icon bằng cách chèn mã HTML của icon đó vào link_before.
wp_nav_menu( array(
'theme_location' => 'my-custom-menu',
'link_before' => '<i class="fa fa-chevron-right"></i> ', // Ví dụ sử dụng Font Awesome
) ); Bạn có thể tham khảo danh sách icon trên trang chính thức của plugin Font Awesome.
Tối ưu hóa hiển thị (depth, fallback_cb, items_wrap)
Đây là các tham số quan trọng để kiểm soát cấu trúc và sự ổn định. Việc tối ưu hóa các tham số này là dấu hiệu của chuyên môn cao.
Tham số depth kiểm soát số lượng cấp độ menu được hiển thị. Giá trị mặc định là 0 (hiển thị tất cả). Nếu bạn chỉ muốn hiển thị menu cấp một, đặt depth là 1. Điều này hữu ích khi bạn có nhiều menu phụ, phức tạp.
Tham số fallback_cb định nghĩa hàm dự phòng nếu không tìm thấy menu. Mặc định, WordPress sẽ hiển thị danh sách các trang.
wp_nav_menu( array(
'theme_location' => 'my-custom-menu',
'fallback_cb' => false // Không hiển thị gì nếu menu không được gán
) );Hoặc bạn có thể tự viết một hàm dự phòng tùy chỉnh. Hàm này sẽ thông báo cho người dùng biết cần tạo menu.
Tham số items_wrap cho phép bạn định nghĩa cấu trúc HTML bao quanh các item menu. Giá trị mặc định là <ul id="%1$s" class="%2$s">%3$s</ul>.
%1$s: Dành cho ID của menu.%2$s: Dành cho Class của menu.%3$s: Dành cho tất cả các item menu (<li>).
Nếu muốn bọc menu bằng một thẻ <section> đặc biệt, bạn có thể thay đổi items_wrap.
wp_nav_menu( array(
'theme_location' => 'my-custom-menu',
'items_wrap' => '<section class="menu-items-list">%3$s</section>'
) );Sử dụng items_wrap cho phép tùy biến sâu hơn nữa. Nó tách biệt cấu trúc hiển thị khỏi logic code chính. Bạn có thể dễ dàng kiểm tra các bài viết khác trên hanoidep.vn để xem ứng dụng thực tế của việc tối ưu hóa hiệu suất web.
Tùy Biến Cấu Trúc Menu Với WordPress Walker Class
Đối với các nhà phát triển chuyên nghiệp, việc tùy chỉnh HTML đầu ra sâu hơn là cần thiết. Đặc biệt khi bạn cần menu tuân thủ các chuẩn CSS framework như Bootstrap. WordPress cung cấp Walker Class để kiểm soát chi tiết từng thẻ HTML của menu.
Hiểu về Walker Class và vai trò của nó
Walker Class là một lớp trừu tượng (abstract class). Nó giúp bạn duyệt qua cấu trúc dữ liệu phân cấp. Trong trường hợp menu, nó duyệt qua các mục menu (cấp cha, cấp con).
Mặc định, WordPress sử dụng Walker_Nav_Menu. Lớp này nằm trong file wp-includes/class-walker-nav-menu.php. Để thay đổi HTML đầu ra, chúng ta cần tạo một lớp kế thừa và ghi đè (override) các phương thức của nó.
Các phương thức quan trọng bao gồm:
start_lvl()vàend_lvl(): Định nghĩa thẻ bao quanh các menu cấp con (<ul>hoặc<div>).start_el()vàend_el(): Định nghĩa thẻ bao quanh từng mục menu (<li>và<a>).
Để chứng minh, chúng ta sẽ thêm một mục menu phụ (Sub item) trong khu vực quản trị.
Minh họa cấu trúc menu đa cấp với Sub Item để thử nghiệm Walker Class
Thực hiện Custom Walker Class
Để tạo Custom Walker Class, chúng ta thêm đoạn mã sau vào file functions.php. Chúng ta cần kiểm tra sự tồn tại của lớp trước khi khai báo. Điều này ngăn chặn lỗi fatal error.
if ( !class_exists('My_Nav_Menu_Walker') ) {
class My_Nav_Menu_Walker extends Walker {
var $tree_type = array( 'post_type', 'taxonomy', 'custom' );
var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );
function start_lvl(&$output, $depth, $args = null) {
$indent = str_repeat("t", $depth);
$output .= "n$indent";
$output .= "n";
$output .= "<div>n"; // Thay thế <ul> bằng <div>
}
function end_lvl(&$output, $depth, $args = null) {
$indent = str_repeat("t", $depth);
$output .= "$indent</div>n"; // Đóng </div>
}
function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
$value = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes = in_array( 'current-menu-item', $classes ) ? array( 'current-menu-item' ) : array();
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
$class_names = strlen( trim( $class_names ) ) > 0 ? ' class="' . esc_attr( $class_names ) . '"' : '';
$id = apply_filters( 'nav_menu_item_id', '', $item, $args );
$id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';
$attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) .'"' : '';
$attributes .= ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) .'"' : '';
$attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) .'"' : '';
$attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) .'"' : '';
$item_output = $args->before;
$item_output .= '<a ' . $class_names . ' ' . $id . ' ' . $attributes . '>';
$item_output .= '<div>'; // Bọc nội dung liên kết trong <div>
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
$item_output .= '</div>';
$item_output .= "</a>n";
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
}Trong đoạn code trên, chúng ta đã thay đổi cấu trúc của submenu. Cấp submenu đã được bọc bằng thẻ <div> thay vì <ul>. Ngoài ra, chúng ta bọc tiêu đề liên kết bằng một thẻ <div> bổ sung.
So sánh kết quả
Cuối cùng, chúng ta áp dụng Walker Class tùy chỉnh này khi gọi hàm wp_nav_menu(). Trong file header.php, chúng ta sẽ tạm thời hiển thị cả hai phiên bản menu để so sánh.
Menu mặc định (sử dụng Walker_Nav_Menu):
wp_nav_menu();Menu sử dụng Custom Walker:
wp_nav_menu( array( 'walker' => new My_Nav_Menu_Walker() ) ); Bạn sẽ thấy rõ sự khác biệt trong cấu trúc HTML đầu ra. Menu sử dụng Walker tùy chỉnh sẽ có cấu trúc mới.
So sánh kết quả hiển thị giữa menu mặc định và menu sử dụng Custom Walker Class
Bằng cách so sánh mã nguồn và kết quả hiển thị, bạn có thể hiểu rõ tác động của Custom Walker. Nó mang lại khả năng tùy biến HTML không giới hạn.
Nắm vững Walker Class là chìa khóa để xây dựng theme WordPress chất lượng cao. Nó đảm bảo mã nguồn HTML sạch và tuân thủ các tiêu chuẩn. Nếu bạn quan tâm đến việc nâng cao kỹ năng phát triển, hãy nghiên cứu lập trình hướng đối tượng (OOP) trong WordPress. Các kỹ thuật này sẽ cải thiện khả năng tái sử dụng và tính bảo mật của mã nguồn.
Kiểm soát hoàn toàn wordpress custom menu là điều cần thiết. Nó giúp nhà phát triển theme cung cấp trải nghiệm tối ưu. Việc đăng ký vị trí, hiển thị bằng wp_nav_menu(), và tùy chỉnh nâng cao bằng Walker Class đều nằm trong tầm tay bạn. Bạn đã học được cách thêm các vị trí menu linh hoạt mà không cần dựa vào plugin. Điều này không chỉ tăng tốc độ mà còn giúp mã nguồn theme gọn gàng hơn. Kỹ năng này mở ra nhiều khả năng thiết kế mới khi xây dựng website. Việc áp dụng các tham số tối ưu và hiểu sâu về cấu trúc code sẽ đảm bảo chất lượng kỹ thuật cao nhất cho dự án của bạn.
Ngày Cập Nhật: Tháng 11 26, 2025 by Ngô Hồng Thái