Code tạo mục lục tự động cho bài viết trong Elementor
Bài viết này mình sẽ hướng dẫn bạn cách tạo mục lục tự động cho bài viết trong Elementor nhé.
Bài viết dài mà không có mục lục thì người đọc phải cuộn tay tìm từng phần, nhiều người nản bỏ đi giữa chừng. Một hộp mục lục ở đầu bài, liệt kê sẵn các tiêu đề và bấm vào là nhảy đúng tới phần đó, vừa giúp người đọc đi nhanh tới phần họ cần, vừa làm bài viết trông chuyên nghiệp hẳn. Elementor bản miễn phí không có widget mục lục nào cả, widget Table of Contents chỉ có ở bản Pro, nên muốn có mục lục mà không nâng cấp thì bạn phải code thêm bằng PHP và JavaScript nhé.
Mục lục nội dung bài viếtHiện
Thêm code tạo mục lục tự động
Bạn chỉ cần thêm code dưới vào cuối file functions.php của child theme nhé. Nhớ sao lưu file trước khi sửa, và đừng chèn vào theme cha vì khi theme cập nhật sẽ mất code.
<?php
// Mục lục tự động cho bài viết dựng bằng Elementor (bản miễn phí)
// Cách dùng: dán code này vào cuối file functions.php của child theme,
// rồi chèn shortcode [nn_muc_luc] bằng widget Shortcode vào đầu mẫu bài viết
// trong Elementor (Theme Builder -> Mẫu bài viết) hoặc vào đầu nội dung bài viết.
add_shortcode('nn_muc_luc', 'nn_muc_luc_shortcode');
function nn_muc_luc_shortcode() {
return '<nav class="nn-muc-luc" aria-label="Mục lục bài viết"><p class="nn-muc-luc-tieu-de">Mục lục</p><ol class="nn-muc-luc-danh-sach"></ol></nav>';
}
add_action('wp_footer', 'nn_muc_luc_script');
function nn_muc_luc_script() {
if (!is_singular('post')) {
return;
}
echo '<style>.nn-muc-luc { background: #F7F7FB; border: 1px solid #E3E3EF; border-radius: 12px; padding: 18px 22px; margin: 0 0 28px; } .nn-muc-luc-tieu-de { font-weight: 700; font-size: 17px; margin: 0 0 10px; color: #1A1B6B; } .nn-muc-luc-danh-sach { margin: 0; padding-left: 20px; } .nn-muc-luc-danh-sach li { margin: 6px 0; } .nn-muc-luc-danh-sach li.nn-muc-cap-2 { margin-left: 18px; list-style-type: circle; } .nn-muc-luc-danh-sach a { color: #333; text-decoration: none; } .nn-muc-luc-danh-sach a:hover, .nn-muc-luc-danh-sach a.nn-dang-doc { color: #1A1B6B; font-weight: 700; } .elementor-widget-theme-post-content h2, .elementor-widget-theme-post-content h3 { scroll-margin-top: 90px; }</style>';
echo '<script>(function () { var hop = document.querySelector(".nn-muc-luc-danh-sach"); if (!hop) { return; } var vung = document.querySelector(".elementor-widget-theme-post-content") || document.querySelector(".entry-content") || document.querySelector("article"); if (!vung) { return; } var tieuDe = vung.querySelectorAll("h2, h3"); if (tieuDe.length < 2) { hop.closest(".nn-muc-luc").style.display = "none"; return; } var lienKet = []; tieuDe.forEach(function (td, i) { if (!td.id) { td.id = "nn-muc-" + (i + 1); } var li = document.createElement("li"); if (td.tagName === "H3") { li.className = "nn-muc-cap-2"; } var a = document.createElement("a"); a.href = "#" + td.id; a.textContent = td.textContent; a.addEventListener("click", function (e) { e.preventDefault(); document.getElementById(td.id).scrollIntoView({ behavior: "smooth" }); }); li.appendChild(a); hop.appendChild(li); lienKet.push({ tieuDe: td, lienKet: a }); }); if ("IntersectionObserver" in window) { var quanSat = new IntersectionObserver(function (muc) { muc.forEach(function (m) { if (m.isIntersecting) { lienKet.forEach(function (cap) { cap.lienKet.classList.toggle("nn-dang-doc", cap.tieuDe === m.target); }); } }); }, { rootMargin: "-80px 0px -70% 0px" }); lienKet.forEach(function (cap) { quanSat.observe(cap.tieuDe); }); } })();</script>';
}
Code trên có hai phần. Phần đầu đăng ký shortcode [nn_muc_luc], shortcode này chỉ in ra một khung mục lục rỗng. Phần sau móc vào wp_footer để chạy JavaScript ở cuối trang bài viết: script tìm vùng nội dung bài viết trong Elementor (widget Post Content, dự phòng là .entry-content hoặc thẻ article), quét toàn bộ tiêu đề H2 và H3, tự gắn id cho tiêu đề nào chưa có rồi dựng thành danh sách liên kết. Tiêu đề H3 sẽ thụt vào một cấp so với H2. Bấm vào mục nào, trang cuộn mượt tới đúng tiêu đề đó, và mục đang đọc được tô đậm nhờ IntersectionObserver theo dõi vị trí cuộn.
Chèn shortcode mục lục vào bài viết
Code chỉ tạo ra shortcode, bạn cần đặt nó vào chỗ muốn hiện mục lục. Cách gọn nhất là mở mẫu bài viết trong Elementor → Theme Builder → Mẫu bài viết, kéo một widget Shortcode vào ngay trên widget Post Content rồi nhập [nn_muc_luc]. Nếu bạn viết bài bằng trình soạn thảo thường thì chỉ cần chèn shortcode vào đầu nội dung bài viết là được. Bài nào có dưới 2 tiêu đề thì hộp mục lục tự ẩn đi, không hiện khung trống.

Lưu ý khi dùng
Mục lục chỉ quét tiêu đề H2 và H3 trong nội dung bài viết, tiêu đề đặt bằng widget Heading của Elementor nằm ngoài vùng Post Content sẽ không được tính, nên bạn viết tiêu đề trong nội dung bài thì mục lục mới đủ. Con số 90px trong CSS là khoảng chừa cho header cố định, nếu header của bạn cao hơn thì tăng số này lên để tiêu đề không bị header che khi cuộn tới. Tính năng này đi chung với bài code thêm nút quay lại đầu trang trong Elementor là thành combo điều hướng cho bài viết dài.
Kết luận
Vậy là chỉ với 1 đoạn code ngắn bạn đã tạo mục lục tự động cho bài viết trong Elementor mà không cần mua bản Pro hay cài thêm plugin rồi nhé. Tính năng này đi chung với bài code thêm nút quay lại đầu trang trong Elementor và bài code thêm thanh tiến trình đọc bài viết trong Elementor là thành bộ tiện ích đọc bài đầy đủ cho site dựng bằng Elementor.
Nếu cần mình kèm 1-1 về Elementor thì cứ liên hệ mình nhé.
