Hello anh em! Xin chào tất cả các bạn độc giả yêu quý đã quay trở lại với bài viết tiếp theo của Blog Share Tips, lâu lắm rồi mình mới lại ngồi vào bàn bật chiếc máy tính thân yêu lên để gõ phím chia sẻ code mới cho anh em cộng đồng làm blog đây!
Lời mở đầu
Anh em ở ngoài miền Bắc với Hà Nội mấy hôm nay ra đường đã cảm nhận được cái rét đầu mùa của đợt gió mùa đông bắc tràn về chưa? Hôm nay mình ngồi viết bài này là đã bước sang đầu tháng 11 rồi, tính ra chỉ còn đúng 2 tháng cuối năm nữa thôi là chúng ta lại khép lại năm 2026 đầy biến động. Sau cái đợt cuối tháng 10 vừa rồi thời tiết mùa thu Hà Nội thất thường nắng nóng hầm hập 35-36 độ C làm mình kêu trời kêu đất ở bài viết trước vì sợ cụm từ "không khí lạnh lệch đông" quay xe, thì cuối cùng đợt không khí lạnh thật sự của mùa đông cũng chịu tràn xuống miền Bắc tụi mình. Đêm qua mình nằm ngủ trong phòng đóng kín cửa thì vẫn thấy bình thường, thế mà sáng nay dậy sớm chuẩn bị đi học mở cánh cửa nhà ra một cái là cơn gió lạnh đầu mùa nó tạt thẳng vào mặt làm mình rét run cầm cập luôn, kiểu cơ thể đang quen mấy hôm trời nóng xong đùng một cái nhiệt độ tụt sâu làm mình đứng đơ mất mấy giây mới hoàn hồn để quay vào nhà lấy thêm chiếc áo khoác gió mặc vào.
Cái tiết trời giao mùa chuyển lạnh đột ngột của 2 tháng cuối năm này đi ngoài đường phố Quán Thánh hay Phan Đình Phùng tầm hơn 6 giờ sáng phải gọi là lạnh buốt cả hai bàn tay, mình đạp xe khoảng 1 cây số tới trường Việt Đức thôi mà gió mùa nó thổi tạt vào người tê tái hết cả mặt mũi. Nhưng mà thú thật với các bạn là cá nhân mình lại cực kỳ thích cái không khí lạnh se sắt kiểu này, ngồi dưới sân trường đón gió đông về cảm giác nó tỉnh táo hẳn ra, chứ không uể oải mệt lả như mấy tuần nắng hanh khô trước đó. Chỉ có điều trời trở lạnh nhanh thế này làm mình hơi lo cho sức khỏe của ông mình ở nhà với bố mình thôi, bố mình vẫn đều đặn lịch trình 3 giờ sáng phải dậy đi làm đầu bếp ở khách sạn xong đến 12 giờ trưa về lại chạy xe Grab ngoài đường, cái sương lạnh buốt lúc rạng sáng mùa đông miền Bắc nó ngấm vào người dã man lắm. Còn mình thì năm nay cũng bước vào giai đoạn nước rút ôn thi THPTQG 2027 rồi nên bài vở trên lớp với lịch học thêm buổi tối cứ gọi là ngập đầu, tối đi học về ăn bát cơm nóng xong chỉ muốn chui tọt ngay vào chiếc chăn bông ấm áp để ngủ một mạch tới sáng, ấy thế mà nhìn sang chiếc máy tính để mốc meo mấy tuần chưa lên bài share thủ thuật gì cho anh em nên nay mình lại quyết định thức khuya một bữa để hoàn thiện nốt món quà này gửi tới mọi người.
1. Chuyện gì khiến mình quyết định tự ngồi code lại cái khung mục lục bài viết này?
Câu chuyện bắt nguồn từ chính mấy bài viết phân tích dài ngoằng về thời tiết mưa bão với hiện tượng mạng mà mình đăng lên blog dạo gần đây. Hôm trước lúc mình vừa đăng xong bài nhận định về mùa đông ấm với El Niño dài cả nghìn chữ, mình có lấy điện thoại ra mở lại bài viết của chính mình để kiểm tra xem bố cục hình ảnh hiển thị đã đẹp chưa, lúc đấy mình muốn tìm lại đúng cái đoạn nói về tác động đối với bà con trồng đào quất ngày Tết để đọc lại mà ngón tay cứ phải vuốt lên vuốt xuống màn hình điện thoại mỏi nhừ cả tay vẫn chưa mò ra nó nằm ở khúc nào. Lúc đó mình mới tự đập trán bảo quái lạ, sao cái blog của mình nhìn cứ thiếu thiếu cái gì đó, hóa ra từ đợt mình đổi sang bộ giao diện mới và dọn dẹp lại đống code rác trong template thì mình quên khuấy mất chưa gắn lại bộ khung mục lục bài viết tự động, hay anh em trong giới làm web vẫn hay gọi bằng cái tên tiếng Anh sang mồm là Table of Contents (viết tắt là TOC).
Nếu bạn nào đã từng đọc bài viết tâm sự về chuyện viết blog ở năm 2026 thời đại AI của mình hồi tháng 8 thì chắc chắn còn nhớ mình từng lấy ví dụ về việc đi ra hiệu sách đúng không? Khi người đọc bước vào một bài viết dài trên blog của bạn, cái ảnh bìa đập vào mắt đầu tiên giúp lôi kéo họ click vào, nhưng thứ giữ chân họ ở lại đọc hết bài chứ không bấm nút thoát trang ngay lập tức chính là cái khung mục lục bài viết. Thời bây giờ thói quen lướt mạng của người dùng thay đổi nhanh lắm, chẳng ai đủ kiên nhẫn ngồi đọc mò mẫm từng dòng chữ từ đầu tới cuối nếu họ không biết bài viết đó có đúng phần thông tin họ đang cần tìm hay không. Có một cái khung mục lục liệt kê rõ ràng từng phần 1, phần 2, phần 3 ngay đầu bài sẽ giúp độc giả nhìn lướt qua 3 giây là nắm được toàn bộ sườn ý chính, họ thích đọc mục nào chỉ cần chạm nhẹ ngón tay một cái là trình duyệt tự động trượt thẳng xuống đúng dòng tiêu đề đó luôn, tiện lợi vô cùng.
Chưa dừng lại ở chuyện trải nghiệm người dùng đâu nhé, đối với những anh em nào đang cày cuốc SEO bài viết lên top Google và nuôi mộng duyệt Google AdSense như mình thì cái Table of Contents này nó là một vũ khí ngầm cực kỳ lợi hại. Anh em có bao giờ để ý mỗi khi mình lên Google tìm kiếm một từ khóa hướng dẫn nào đó, ở ngay bên dưới dòng mô tả của mấy trang web đứng top 1, top 2 nó hay xuất hiện thêm một hàng các đường link nhỏ trỏ thẳng tới từng mục con bên trong bài viết không? Cái đó dân kỹ thuật SEO gọi là Jump Links (liên kết nhảy trên trang kết quả tìm kiếm SERP). Khi bộ code mục lục của mình tự động gắn các mã định danh id vào từng thẻ tiêu đề h2, h3 và tạo danh sách liên kết neo #id ở đầu bài, con bọ thu thập dữ liệu của Google (Googlebot) lúc vào quét mã nguồn HTML sẽ hiểu ngay cấu trúc phân cấp của bài viết. Hơn nữa trong bối cảnh Google đang ưu tiên trích dẫn câu trả lời trực tiếp lên khung AI tìm kiếm như hiện nay, một bài viết được chia thẻ Heading mạch lạc kèm mục lục neo rõ ràng sẽ có tỷ lệ được thuật toán bóc tách dữ liệu và trỏ link nguồn về blog cao hơn gấp nhiều lần so với những bài viết cứ tuôn chữ tràn lan đại hải.
2. Nỗi ám ảnh mang tên "code mục lục đi xin trên mạng" và cách mình khắc phục
Thú thật với anh em là hồi năm 2021 - 2022 lúc mình mới học lớp 7 lớp 8 bắt đầu tập tành vọc vạch HTML, CSS với Javascript trên nền tảng Blogger, mình cũng hay đi lượn lờ khắp các blog chia sẻ thủ thuật để copy code mục lục về dán vào web của mình lắm. Nhưng sau hơn 4 năm lăn lộn đập đi xây lại không biết bao nhiêu cái blog từ lOGHITECHUR, ANewPlus cho tới Blog Share Tips bây giờ, mình phát hiện ra gần như 90% các đoạn code Table of Contents đang được chia sẻ miễn phí trên mạng đều mắc phải 3 căn bệnh kinh niên cực kỳ ngứa mắt mà ít người chịu sửa.
Căn bệnh đầu tiên và cũng là thứ làm mình ghét nhất chính là sự phụ thuộc vào thư viện jQuery. Rất nhiều bài hướng dẫn trên mạng chia sẻ những đoạn script mục lục viết từ thời cổ đại cách đây 7-8 năm, chỉ để làm mỗi cái hiệu ứng bấm vào nút ẩn/hiện khung mục lục thôi mà bắt người ta phải nhúng thêm nguyên một thư viện jquery.min.js nặng gần cả trăm KB vào thẻ <head>. Hậu quả là khi anh em đem link blog đi đo tốc độ trên công cụ Google PageSpeed Insights thì điểm hiệu suất trên di động tụt đỏ lòm vì lỗi chặn hiển thị (Render-blocking resources), người dùng vào đọc blog bằng mạng 4G lúc sóng yếu là trang web cứ xoay vòng vòng mãi mới tải xong.
Căn bệnh thứ hai còn dở hơi hơn nữa, đó là lỗi đường dẫn neo (Anchor Link) bị mã hóa ký tự tiếng Việt trông như link rác! Anh em nào từng gắn mấy bản code TOC lấy từ các trang nước ngoài hoặc bóc tách từ bản gốc của mấy ông lập trình viên bên Indonesia (như dòng theme Median UI hay Fletro đời đầu) chắc chắn đã từng gặp cảnh này. Do người viết code gốc họ chỉ dùng bảng chữ cái tiếng Anh không dấu, nên khi đoạn script lấy nội dung chữ bên trong thẻ <h2> tiếng Việt của mình để gán vào thuộc tính id, những chữ có dấu như "Giới thiệu về công cụ" khi bấm vào sẽ biến thanh địa chỉ URL trên trình duyệt thành một dãy ký tự loằng ngoằng kiểu #Gi%E1%BB%9Bi-thi%E1%BB%87u-v%E1%BB%81-c%C3%B4ng-c%E1%BB%A5. Nhìn cái đường link nó vừa dài dòng vừa mất thẩm mỹ, nhiều khi mình muốn copy đúng cái link neo của mục số 3 gửi qua Messenger hay Zalo cho bạn bè đọc mà người ta nhìn cái đuôi phần trăm loằng ngoằng lại tưởng mình gửi link mã độc lừa đảo không dám bấm vào.
Căn bệnh thứ ba là hiện tượng nhảy trang bị thanh menu che mất chữ. Hầu hết các giao diện Blogspot hiện đại ngày nay từ Plus UI, Lantro UI cho tới giao diện riêng của Blog Share Tips đều thiết kế thanh tiêu đề (Header) ghim cố định ở mép trên màn hình khi cuộn chuột xuống. Khi anh em bấm vào một dòng trong mục lục, trình duyệt nó sẽ kéo cái thẻ <h2> đó lên sát mép trên cùng của màn hình, thế là cái thanh Header cố định kia nó đè lên che khuất mất luôn dòng tiêu đề mình vừa bấm vào, người đọc lại phải mất công lăn chuột ngược lên một chút mới nhìn thấy chữ, trải nghiệm cực kỳ ức chế.
Chính vì quá ngứa mắt với 3 cái lỗi đó nên tối qua, nhân lúc ngoài trời gió mùa về lạnh cóng chẳng đi lượn phố được, mình đã ngồi viết lại một bộ code Table of Contents hoàn toàn mới bằng Javascript thuần (Vanilla JS 100%). Bản code này của mình giải quyết triệt để toàn bộ những điểm yếu trên: nhẹ tênh chưa tới 3KB không cần bất kỳ thư viện jQuery nào, tích hợp sẵn bộ lọc khử sạch dấu tiếng Việt (chữ "1. Hướng dẫn cài đặt chi tiết" sẽ tự động chuyển thành đường dẫn sạch đẹp #1-huong-dan-cai-dat-chi-tiet), đồng thời áp dụng thuộc tính scroll-margin-top trong CSS để khi nhảy tới bất kỳ tiêu đề nào nó cũng tự động cách thanh Header phía trên một khoảng vừa đủ mắt nhìn, kèm theo hiệu ứng nháy sáng nhẹ ở tiêu đề vừa nhảy tới để người đọc định vị mắt ngay lập tức.
- Nền tảng: Blogspot / Blogger
- Phát hành: 01/11/2026
- Ngôn ngữ: HTML5, CSS3, Vanilla JS (Không dùng jQuery)
- Tương thích: Median UI, Plus UI, Lantro UI, Mặc định
- Developer: Blog Share Tips
- Chuẩn SEO & Darkmode: Có
3. Chia sẻ trọn bộ code tạo mục lục bài viết (Table of Contents) tự động cho Blogspot
Mình chia sẻ bộ code này hoàn toàn miễn phí cho anh em trong cộng đồng đem về trang trí và tối ưu SEO cho blog của mình, không cài cắm bất kỳ đoạn mã chuyển hướng hay khóa bản quyền gì bên trong cả. Để cài đặt vào blog thì có 2 cách: nếu bạn muốn áp dụng cho toàn bộ các bài viết trên blog thì vào phần Chủ đề (Theme) → Chỉnh sửa HTML (Edit HTML) để dán, hoặc nếu bạn chỉ muốn thử nghiệm trên 1 bài viết cụ thể thì chuyển khung soạn thảo bài viết sang chế độ HTML rồi dán trực tiếp vào cuối bài là nó tự chạy ngon lành.
Bước 1: Dán đoạn mã giao diện CSS
Anh em tìm thẻ đóng </head> trong template của mình (hoặc dán ngay đầu bài viết nếu chỉ dùng lẻ) và chèn toàn bộ đoạn code <style> bên dưới vào. Ở đây mình đã thiết kế sẵn màu sắc tự động nhận diện biến màu tối (Dark Mode) của các dòng theme đời mới nên anh em không phải lo chuyện bật giao diện ban đêm bị lỗi màu chữ nhé:
<style>
/* ====== CSS Mục lục tự động (Table of Contents) - Blog Share Tips ====== */
:root {
--tlit-toc-bg: #f8fafc;
--tlit-toc-border: #e2e8f0;
--tlit-toc-text: #1e293b;
--tlit-toc-accent: #007bff;
--tlit-toc-hover-bg: #eff6ff;
}
/* Tự động tương thích chế độ nền tối (Dark Mode) của Plus UI, Median UI, Lantro UI */
.drK, [data-theme="dark"], body.dark-mode {
--tlit-toc-bg: #1e242c;
--tlit-toc-border: #2d3748;
--tlit-toc-text: #e2e8f0;
--tlit-toc-accent: #38bdf8;
--tlit-toc-hover-bg: rgba(56, 189, 248, 0.1);
}
.tlit-toc-wrapper {
background: var(-- contentBs, var(--tlit-toc-bg));
border: 1px solid var(--contentBd, var(--tlit-toc-border));
border-left: 4px solid var(--linkC, var(--tlit-toc-accent));
border-radius: 10px;
padding: 16px 20px;
margin: 22px 0;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.03);
transition: all 0.25s ease;
clear: both;
}
.tlit-toc-header {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
user-select: none;
font-weight: 700;
font-size: 16px;
color: var(--bodyC, var(--tlit-toc-text));
}
.tlit-toc-title {
display: inline-flex;
align-items: center;
gap: 8px;
}
.tlit-toc-title svg {
width: 20px;
height: 20px;
stroke: var(--linkC, var(--tlit-toc-accent));
fill: none;
stroke-width: 2;
}
.tlit-toc-toggle-btn {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 13px;
font-weight: 500;
color: var(--linkC, var(--tlit-toc-accent));
background: transparent;
border: none;
padding: 4px 8px;
border-radius: 6px;
}
.tlit-toc-toggle-btn svg {
width: 16px;
height: 16px;
stroke: currentColor;
fill: none;
stroke-width: 2;
transition: transform 0.3s ease;
}
.tlit-toc-wrapper.is-collapsed .tlit-toc-toggle-btn svg {
transform: rotate(-90deg);
}
.tlit-toc-body {
margin-top: 12px;
padding-top: 12px;
border-top: 1px dashed var(--contentBd, var(--tlit-toc-border));
overflow: hidden;
transition: max-height 0.35s ease, opacity 0.25s ease;
}
.tlit-toc-wrapper.is-collapsed .tlit-toc-body {
display: none;
}
.tlit-toc-list {
list-style: none !important;
margin: 0 !important;
padding: 0 !important;
}
.tlit-toc-list li {
margin: 6px 0 !important;
padding: 0 !important;
line-height: 1.5;
}
.tlit-toc-list li.tlit-toc-h3 {
padding-left: 20px !important;
font-size: 0.94em;
}
.tlit-toc-list li.tlit-toc-h4 {
padding-left: 38px !important;
font-size: 0.88em;
}
.tlit-toc-list a {
display: inline-block;
color: var(--bodyC, var(--tlit-toc-text)) !important;
text-decoration: none !important;
padding: 3px 8px;
border-radius: 5px;
transition: all 0.2s ease;
}
.tlit-toc-list a:hover {
color: var(--linkC, var(--tlit-toc-accent)) !important;
background: var(--tlit-toc-hover-bg);
transform: translateX(4px);
}
/* Chống bị thanh Header cố định che khuất chữ khi nhảy tới tiêu đề */
.post-body h2[id], .post-body h3[id], .post-body h4[id],
.entry-content h2[id], .entry-content h3[id], .entry-content h4[id] {
scroll-margin-top: 85px;
transition: background-color 0.6s ease;
}
/* Hiệu ứng nháy nhẹ giúp người đọc nhận diện dòng tiêu đề vừa bấm */
.tlit-heading-highlight {
background-color: rgba(255, 235, 59, 0.35);
border-radius: 4px;
}
</style>
Bước 2: Dán đoạn mã xử lý Javascript thuần (Vanilla JS)
Tiếp theo, anh em kéo xuống cuối template tìm thẻ đóng </body> và dán đoạn code <script> này ngay phía trên nó. Điểm ăn tiền nhất ở đoạn code này là mình đã viết hàm slugifyVietnamese chuyển toàn bộ bảng chữ cái có dấu của tiếng Việt về dạng chuẩn không dấu và kiểm tra chống trùng lặp id nếu trong bài vô tình có 2 thẻ tiêu đề đặt tên giống hệt nhau:
<script>
/* ====== Script Tạo Mục Lục Tự Động Chuẩn SEO - Blog Share Tips ====== */
(function() {
var tlitTocConfig = {
containerSelector: '.post-body, .entry-content, #post-body', // Vùng chứa nội dung bài viết
headingSelectors: 'h2, h3, h4', // Các thẻ tiêu đề muốn đưa vào mục lục
minHeadings: 2, // Số thẻ tiêu đề tối thiểu để hiển thị mục lục
tocTitle: 'Nội dung chính trong bài',
autoNumbering: false, // Đổi thành true nếu muốn code tự đánh số 1, 1.1, 1.2...
defaultCollapsed: false // Đổi thành true nếu muốn mặc định đóng gọn mục lục khi mới vào
};
// Hàm khử dấu tiếng Việt tạo ID sạch đẹp chuẩn SEO trên thanh địa chỉ
function slugifyVietnamese(str) {
if (!str) return 'muc-luc';
str = str.toLowerCase().trim();
str = str.replace(/[àáạảãâầấậẩẫăằắặẳẵ]/g, 'a');
str = str.replace(/[èéẹẻẽêềếệểễ]/g, 'e');
str = str.replace(/[ìíịỉĩ]/g, 'i');
str = str.replace(/[òóọỏõôồốộổỗơờớợởỡ]/g, 'o');
str = str.replace(/[ùúụủũưừứựửữ]/g, 'u');
str = str.replace(/[ỳýỵỷỹ]/g, 'y');
str = str.replace(/đ/g, 'd');
str = str.replace(/[^a-z0-9\s-]/g, '');
str = str.replace(/[\s-]+/g, '-');
return str.replace(/^-+|-+$/g, '') || 'phan-noi-dung';
}
function initThangLongIT_TOC() {
var postBody = document.querySelector(tlitTocConfig.containerSelector);
if (!postBody) return;
// Không chạy ở trang chủ hoặc trang danh sách nhãn
var allHeadings = postBody.querySelectorAll(tlitTocConfig.headingSelectors);
if (!allHeadings || allHeadings.length < tlitTocConfig.minHeadings) return;
var usedIds = {};
var tocListHtml = '<ul class="tlit-toc-list">';
var h2Count = 0, h3Count = 0, h4Count = 0;
for (var i = 0; i < allHeadings.length; i++) {
var heading = allHeadings[i];
var text = (heading.textContent || heading.innerText || '').trim();
if (!text) continue;
// Tạo ID không dấu và chống trùng lặp
var baseId = heading.getAttribute('id') || slugifyVietnamese(text);
var uniqueId = baseId;
var counter = 1;
while (usedIds[uniqueId] || document.getElementById(uniqueId)) {
if (heading.getAttribute('id') === uniqueId && !usedIds[uniqueId]) break;
counter++;
uniqueId = baseId + '-' + counter;
}
usedIds[uniqueId] = true;
heading.setAttribute('id', uniqueId);
// Phân cấp thẻ H2, H3, H4
var tagName = heading.tagName.toLowerCase();
var prefix = '';
if (tlitTocConfig.autoNumbering) {
if (tagName === 'h2') { h2Count++; h3Count = 0; h4Count = 0; prefix = h2Count + '. '; }
else if (tagName === 'h3') { h3Count++; h4Count = 0; prefix = h2Count + '.' + h3Count + ' '; }
else if (tagName === 'h4') { h4Count++; prefix = h2Count + '.' + h3Count + '.' + h4Count + ' '; }
}
tocListHtml += '<li class="tlit-toc-' + tagName + '">' +
'<a href="#' + uniqueId + '" data-target="' + uniqueId + '">' + prefix + text + '</a>' +
'</li>';
}
tocListHtml += '</ul>';
// Dựng khung giao diện TOC
var wrapper = document.createElement('div');
wrapper.className = 'tlit-toc-wrapper' + (tlitTocConfig.defaultCollapsed ? ' is-collapsed' : '');
wrapper.setAttribute('role', 'navigation');
wrapper.setAttribute('aria-label', tlitTocConfig.tocTitle);
wrapper.innerHTML =
'<div class="tlit-toc-header" id="tlit-toc-Toggle">' +
'<span class="tlit-toc-title">' +
'<svg viewBox="0 0 24 24"><line x1="8" y1="6" x2="21" y2="6"></line><line x1="8" y1="12" x2="21" y2="12"></line><line x1="8" y1="18" x2="21" y2="18"></line><line x1="3" y1="6" x2="3.01" y2="6"></line><line x1="3" y1="12" x2="3.01" y2="12"></line><line x1="3" y1="18" x2="3.01" y2="18"></line></svg>' +
tlitTocConfig.tocTitle +
'</span>' +
'<button type="button" class="tlit-toc-toggle-btn" aria-label="Ẩn hoặc hiện mục lục">' +
'<span class="tlit-toc-status-text">' + (tlitTocConfig.defaultCollapsed ? 'Hiện' : 'Ẩn') + '</span>' +
'<svg viewBox="0 0 24 24"><polyline points="6 9 12 15 18 9"></polyline></svg>' +
'</button>' +
'</div>' +
'<div class="tlit-toc-body">' + tocListHtml + '</div>';
// Kiểm tra xem người viết có đặt thẻ đánh dấu vị trí thủ công <div id="tlit-toc"></div> không, nếu không thì tự chèn trước thẻ H2 đầu tiên
var manualPlaceholder = postBody.querySelector('#tlit-toc');
if (manualPlaceholder) {
manualPlaceholder.parentNode.replaceChild(wrapper, manualPlaceholder);
} else {
var firstHeading = allHeadings[0];
firstHeading.parentNode.insertBefore(wrapper, firstHeading);
}
// Sự kiện bấm ẩn/hiện mục lục
var headerBtn = wrapper.querySelector('#tlit-toc-Toggle');
var statusText = wrapper.querySelector('.tlit-toc-status-text');
headerBtn.addEventListener('click', function() {
var collapsed = wrapper.classList.toggle('is-collapsed');
if (statusText) statusText.textContent = collapsed ? 'Hiện' : 'Ẩn';
});
// Sự kiện cuộn mượt (Smooth Scroll) và nháy sáng tiêu đề khi click
var links = wrapper.querySelectorAll('.tlit-toc-list a');
for (var j = 0; j < links.length; j++) {
links[j].addEventListener('click', function(e) {
var targetId = this.getAttribute('data-target');
var targetEl = document.getElementById(targetId);
if (targetEl) {
e.preventDefault();
targetEl.scrollIntoView({ behavior: 'smooth', block: 'start' });
history.replaceState(null, null, '#' + targetId);
targetEl.classList.add('tlit-heading-highlight');
setTimeout(function() {
targetEl.classList.remove('tlit-heading-highlight');
}, 1500);
}
});
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initThangLongIT_TOC);
} else {
initThangLongIT_TOC();
}
})();
</script>
4. Một vài lưu ý nhỏ và mẹo tùy biến nâng cao cho anh em
Sau khi dán xong 2 đoạn code trên và bấm lưu lại thì coi như anh em đã hoàn thành 99% công việc rồi đó, từ giờ trở đi cứ mỗi lần viết bài mới chỉ cần bài viết có từ 2 thẻ tiêu đề <h2> trở lên là cái khung mục lục sẽ tự động hiện ra ngay phía trên thẻ <h2> đầu tiên mà không cần phải thao tác thêm bất cứ cái gì cả. Tuy nhiên trong quá trình mình hỗ trợ mấy bạn trong nhóm gắn code vào các dòng template khác nhau thì có một vài kinh nghiệm xương máu thế này anh em nên đọc kỹ để tự làm chủ con code của mình:
- Cách chọn vị trí hiển thị mục lục theo ý thích: Mặc định mình lập trình cho khung mục lục tự động chèn ngay trước thẻ tiêu đề đầu tiên (tức là nằm dưới đoạn mở bài giống như cấu trúc chuẩn của các báo lớn). Nhưng nếu ở một bài viết nào đó anh em muốn cái mục lục nó nằm ở giữa bài hoặc nằm sau tấm ảnh bìa thứ hai, anh em chỉ cần chuyển qua tab HTML trong lúc viết bài và gõ đúng dòng
<div id="tlit-toc"></div>vào vị trí mình muốn, đoạn script của mình khi quét thấy thẻ này sẽ ưu tiên đặt bảng mục lục vào đúng chỗ đó luôn. - Khắc phục lỗi dán code xong mà không thấy hiện gì: Như mình có giải thích ở phần chú thích trong code, đa số các giao diện Blogspot chuẩn đều đặt phần nội dung bài viết nằm trong thẻ có class là
.post-bodyhoặc.entry-content. Nếu anh em dùng một bản template tự thiết kế riêng mà dán code vào chưa thấy bảng mục lục hiện lên, anh em hãy bấm chuột phải vào chữ trong bài viết chọn Kiểm tra (Inspect) trên trình duyệt máy tính để xem thẻ<div>bao bọc toàn bộ bài viết của mình có tên class là gì, rồi điền thêm tên class đó vào dòngcontainerSelectorở đầu đoạn script là nó nhận diện được ngay. - Tự động đánh số thứ tự hay tự gõ tay: Ở dòng cấu hình
autoNumbering: falsetrong code Javascript, mình đang để mặc định làfalse(tắt tự động đánh số) bởi vì bản thân mình lúc viết bài rất hay tự gõ số "1., 2., 3." trực tiếp vào tiêu đề<h2>luôn rồi, nếu bật tự đánh số nữa thì nó sẽ bị lặp thành "1. 1. Tiêu đề" trông rất ngố. Còn nếu thói quen viết bài của bạn là chỉ viết chữ không đánh số ở tiêu đề mà vẫn muốn trong khung mục lục hiện số phân cấp 1, 1.1, 1.2 chuyên nghiệp thì chỉ cần sửa chữfalseđó thànhtruelà xong.
Mẹo nhỏ chuẩn SEO từ kinh nghiệm thực tế của mình: Khi đặt tên cho các thẻ tiêu đề <h2> và <h3> trong bài viết, anh em cố gắng viết dưới dạng câu hỏi trực diện mà người dùng hay gõ lên Google (ví dụ như "Mưa đá có nguy hiểm không?" hay "Cách khắc phục lỗi..."), kết hợp với bộ code mục lục tạo liên kết neo này thì khả năng bài viết của anh em được Google bóc lên phần Câu hỏi thường gặp (People Also Ask) trên trang tìm kiếm sẽ cao hơn hẳn đấy!
Đừng quên nhấn vào chiếc chuông màu xanh dưới góc phải màn hình để nhận thông báo mới nhất từ Blog Share Tips nhé. Nếu trong quá trình cài đặt code vào template của bạn có gặp bất kỳ lỗi hiển thị hay xung đột CSS nào thì cứ mạnh dạn để lại bình luận kèm link blog ở phía dưới, tối đi học về mình sẽ vào kiểm tra và hỗ trợ sửa trực tiếp cho anh em.
Lời kết
Cảm ơn bạn đã đến đây, cảm ơn bạn đã đọc bài viết này. Nhớ theo dõi và ủng hộ Blog Share Tips bằng một lượt chia sẻ bài viết và để lại bình luận tương tác ở bên dưới nhé. Trời miền Bắc vào đợt gió mùa đông bắc đầu tiên lạnh thật sự rồi, chúc các bạn luôn giữ ấm cơ thể, thật nhiều sức khỏe và tràn đầy năng lượng để hoàn thành tốt những dự định trong 2 tháng cuối năm 2026 này! (update 19:30 PM - 01/11/2026)
Copyright © Blog Share Tips