สารบัญแบบไดนามิกบน Webflow CMS – วิธีที่ง่ายที่สุด

เผยแพร่แล้ว: 2022-03-22
เมื่อเร็ว ๆ นี้เราได้ทำให้สามารถเพิ่มสถานะที่ใช้งานไปยังสารบัญแบบติดหนึบได้ – ดูคำแนะนำที่ท้ายบทความ!

พื้นหลัง

ที่ Flowrite เราเพิ่งเริ่มเขียนเนื้อหาที่ยาวขึ้น และต้องการทำให้บล็อกของเราอ่านง่ายขึ้น โดยเริ่มจากองค์ประกอบพื้นฐานที่สุด - สารบัญ

เราใช้ Webflow และชอบมันมาก แต่กลายเป็นว่าการสร้าง ToC ที่ปรับขนาดได้สำหรับรายการ CMS นั้นไม่ได้ตรงไปตรงมาขนาดนั้น โซลูชันที่มีอยู่ทั้งหมดขึ้นอยู่กับการตั้งค่ารหัสและลิงก์ด้วยตนเองหรือใช้ปลั๊กอินของบุคคลที่สาม

เราต้องการระบบที่เรียบง่ายที่จะสร้าง ToC โดยอัตโนมัติตามหัวข้อในบล็อกของเรา นั่นคือสิ่งที่เราสร้างขึ้น และนี่คือวิธีที่คุณทำเช่นเดียวกัน!

มันทำงานอย่างไร?

  1. ออกแบบรายการ ToC ของคุณ ทำตามที่คุณต้องการ – สร้างสถานะโฮเวอร์ แอนิเมชั่น ฯลฯ
  2. สร้าง div สำหรับ ToC ด้วย id เฉพาะที่ใดก็ได้บนหน้า CMS ของคุณ
  3. แทรกโค้ดที่ส่วนท้ายของแท็ก <body> ในหน้า CMS ของคุณ
  4. ToC จะถูกสร้างขึ้นโดยอัตโนมัติสำหรับแต่ละรายการ CMS

การสร้างสารบัญแบบไดนามิกของคุณ

ออกแบบรายการ ToC ของคุณ

ให้รายการ ToC ของคุณมีคลาส (เราใช้ "tocitem") และจัดรูปแบบตามที่คุณต้องการ

คำแนะนำของฉันคือการใช้หน้าส่วนตัวแยกต่างหากสำหรับการออกแบบองค์ประกอบเหล่านี้ ด้วยวิธีนี้ คุณจะปรับเปลี่ยนการออกแบบในภายหลังได้อย่างง่ายดายหากจำเป็น

เราชอบความเรียบง่ายขององค์ประกอบสารบัญของ Notion ดังนั้นเราจึงใช้สิ่งนั้นเป็นเกณฑ์มาตรฐาน


หากคุณต้องการรวมส่วนหัวมากกว่าหนึ่งประเภท ตรวจสอบให้แน่ใจว่าได้ให้คลาสเพิ่มเติมแก่พวกเขา ("toc-h2", "toc-h3" เป็นต้น)

สร้างองค์ประกอบสำหรับ ToC . ของคุณ

เพิ่ม div ทุกที่ที่คุณต้องการให้ ToC ของคุณเป็น และระบุ id "toc" ให้กับมัน อีกครั้ง คุณสามารถจัดรูปแบบองค์ประกอบนี้ได้ตามที่คุณต้องการ

หากคุณต้องการให้ ToC ของคุณอยู่ในองค์ประกอบ Rich Text โปรดดูรายละเอียดเพิ่มเติมที่ส่วนท้ายของบทความนี้

สุดท้าย ให้องค์ประกอบ Rich Text เป็น "เนื้อหา" สิ่งนี้จำเป็นในภายหลังเพื่อให้แน่ใจว่าเราใช้หัวข้อที่ถูกต้องใน ToC

เลือกจากสองตัวเลือก

เนื่องจาก ToC จะถูกสร้างขึ้นโดยอัตโนมัติ เราจึงต้องระบุว่าเราต้องการรวมส่วนหัวใดไว้ด้วย ในโพสต์นี้ เราครอบคลุมสองตัวเลือก:

  1. การสร้าง ToC ตามประเภทส่วนหัวคงที่เพียงประเภทเดียว เช่น H2
  2. การสร้าง ToC ตามหัวข้อต่างๆ ที่คุณเลือก เช่น H2 และ H3 สำหรับโพสต์บล็อกหนึ่ง และ H2 และ H4 สำหรับอีกบล็อกหนึ่ง

ตัวเลือกที่ 1: ToC แบบหัวเดียว

ในตัวเลือกนี้ ToC จะถูกสร้างขึ้นตามหัวเรื่องเดียวกันเสมอ

ใส่รหัสต่อไปนี้ที่ส่วนท้ายของแท็ก <body> ของคุณในหน้าคอลเลกชันของคุณ ดูความคิดเห็นที่ส่วนท้ายของแต่ละบรรทัดหากคุณต้องการเข้าใจวิธีการทำงาน

  <script> document.getElementById("content").querySelectorAll("h2").forEach(function(heading, i) { // runs a function for all h2 elements inside your rich text element heading.setAttribute("id", "toc-" + i); // gives each h2 a unique id let str = heading.innerHTML; // adds section titles to slugs str = str.replace(/\s+/g, '-').replace(/[°&\/\\#,+()$~%.'":;*?<>{}]/g, "").toLowerCase(); // replaces spaces with hyphens, removes special characters and extra spaces from the headings, and applies lowercase in slugs heading.setAttribute("id", str); // gives each heading a unique id const item = document.createElement("a"); // creates an anchor element called "item" for each h2 item.innerHTML = heading.innerHTML // gives each item the text of the corresponding heading item.setAttribute("class", "tocitem"); // gives each item the correct class item.setAttribute("href", "#" + str); // gives each item the correct anchor link document.querySelector("#toc").appendChild(item); // places each item inside the Table of Contents div }); </script>
<script> document.getElementById("content").querySelectorAll("h2").forEach(function(heading, i) { // runs a function for all h2 elements inside your rich text element heading.setAttribute("id", "toc-" + i); // gives each h2 a unique id let str = heading.innerHTML; // adds section titles to slugs str = str.replace(/\s+/g, '-').replace(/[°&\/\\#,+()$~%.'":;*?<>{}]/g, "").toLowerCase(); // replaces spaces with hyphens, removes special characters and extra spaces from the headings, and applies lowercase in slugs heading.setAttribute("id", str); // gives each heading a unique id const item = document.createElement("a"); // creates an anchor element called "item" for each h2 item.innerHTML = heading.innerHTML // gives each item the text of the corresponding heading item.setAttribute("class", "tocitem"); // gives each item the correct class item.setAttribute("href", "#" + str); // gives each item the correct anchor link document.querySelector("#toc").appendChild(item); // places each item inside the Table of Contents div }); </script>

เผยแพร่เว็บไซต์และคุณก็พร้อมไป

ตัวเลือกที่ 2: ToCs แบบหลายหัวเรื่อง

ตัวเลือกนี้ให้โอกาสคุณกำหนดเป็นกรณีๆ ไปว่าจะใช้หัวข้อใดเพื่อสร้าง ToC

เริ่มต้นด้วยการสร้างช่องข้อความใหม่ในคอลเล็กชันของคุณ เราเรียกมันว่า "TOC ตาม ... " นี่คือที่ที่คุณระบุส่วนหัวที่จะใช้ใน ToC ของแต่ละรายการ CMS คั่นด้วยเครื่องหมายจุลภาคและอย่าเว้นวรรค


ตอนนี้ ให้ใส่โค้ดต่อไปนี้ที่ส่วนท้ายของแท็ก <body> ของคุณในหน้าคอลเลกชันของคุณ ดูความคิดเห็นที่ส่วนท้ายของแต่ละบรรทัดหากคุณต้องการเข้าใจวิธีการทำงาน

  <script> document.getElementById("content").querySelectorAll("[HEADINGS]").forEach(function(heading, i) { // runs a function for all headings inside your rich text element let str = heading.innerHTML; // adds section titles to slugs str = str.replace(/\s+/g, '-').replace(/[°&\/\\#,+()$~%.'":;*?<>{}]/g, "").toLowerCase(); // replaces spaces with hyphens, removes special characters and extra spaces from the headings, and applies lowercase in slugs heading.setAttribute("id", str); // gives each heading a unique id const item = document.createElement("a"); // creates an anchor element called "item" for each heading item.innerHTML = heading.innerHTML; // gives each item the text of the corresponding heading ("[HEADINGS]").split(",").forEach(function(x) { // runs a function for each item in your headings list if (heading.tagName.toLowerCase()==x) { item.classList.add("tocitem", "toc-" + x); // gives each item the correct class } }); item.setAttribute("href", "#" + str); // gives each item the correct anchor link document.querySelector("#toc").appendChild(item); // places each item inside the Table of Contents div }); </script>
<script> document.getElementById("content").querySelectorAll("[HEADINGS]").forEach(function(heading, i) { // runs a function for all headings inside your rich text element let str = heading.innerHTML; // adds section titles to slugs str = str.replace(/\s+/g, '-').replace(/[°&\/\\#,+()$~%.'":;*?<>{}]/g, "").toLowerCase(); // replaces spaces with hyphens, removes special characters and extra spaces from the headings, and applies lowercase in slugs heading.setAttribute("id", str); // gives each heading a unique id const item = document.createElement("a"); // creates an anchor element called "item" for each heading item.innerHTML = heading.innerHTML; // gives each item the text of the corresponding heading ("[HEADINGS]").split(",").forEach(function(x) { // runs a function for each item in your headings list if (heading.tagName.toLowerCase()==x) { item.classList.add("tocitem", "toc-" + x); // gives each item the correct class } }); item.setAttribute("href", "#" + str); // gives each item the correct anchor link document.querySelector("#toc").appendChild(item); // places each item inside the Table of Contents div }); </script>

สุดท้าย อย่าลืมแทนที่ [HEADINGS] ด้วยค่าของฟิลด์ "ToC based on..." CMS ของคุณ


เพียงเท่านี้คุณก็พร้อมที่จะเผยแพร่แล้ว

การปรับแต่ง

สถานะใช้งานอยู่ในสารบัญ

แรงบันดาลใจจากโพสต์ของ Chris Coyier เกี่ยวกับ CSS-Tricks เราได้สร้างวิธีการเพิ่มสถานะใช้งานให้กับรายการ ToC ที่มองเห็นได้ ซึ่งเป็นคุณสมบัติที่ยอดเยี่ยมสำหรับ ToC ที่ติดหนึบ

ขั้นแรก เพิ่ม "observer.observe(heading);" ที่จุดเริ่มต้นของรหัสที่คุณใช้งานก่อนหน้านี้ ดูภาพหน้าจอสำหรับตำแหน่งที่ถูกต้อง

จากนั้น เพิ่มข้อมูลโค้ดต่อไปนี้ทับโค้ด ToC ที่มีอยู่ทั้งหมด:

  <script> const observer = new IntersectionObserver(entries => { entries.forEach(entry => { const id = entry.target.getAttribute("id"); if (entry.isIntersecting) { document.querySelectorAll(".active").forEach((z) => { z.classList.remove("active") }); document.querySelector(`a[href="#${id}"]`).classList.add("active"); } }); }, { rootMargin: '0px 0px -75% 0px' }); </script>
<script> const observer = new IntersectionObserver(entries => { entries.forEach(entry => { const id = entry.target.getAttribute("id"); if (entry.isIntersecting) { document.querySelectorAll(".active").forEach((z) => { z.classList.remove("active") }); document.querySelector(`a[href="#${id}"]`).classList.add("active"); } }); }, { rootMargin: '0px 0px -75% 0px' }); </script>

รหัสจะเพิ่มคลาสที่เรียกว่า "active" ให้กับ tocitem ที่มองเห็นได้ และลบคลาสเมื่อ tocitem ใหม่ปรากฏขึ้น

สุดท้าย ตรวจสอบให้แน่ใจว่าได้จัดรูปแบบคลาส "แอ็คทีฟ" โดยกำหนดสีพื้นหลังที่ต่างกันออกไป เป็นต้น

แสดง ToC เฉพาะบางรายการของ CMS

หากคุณไม่ต้องการให้ ToC ปรากฏในรายการ CMS บางรายการของคุณ ให้ทำตามขั้นตอนต่อไปนี้:

‍ 1. เว้นช่อง "ToC ตาม .." ว่างไว้
หากคุณกำลังใช้ตัวเลือกที่ 1 ให้เพิ่มสวิตช์ในคอลเล็กชัน CMS เพื่อระบุว่า ToC ควรปรากฏขึ้นหรือไม่

2. ทำให้การมองเห็นของ ToC div แบบมีเงื่อนไข ตามตัวเลือกในขั้นตอนที่ 1

3. สร้างคำสั่ง if ที่ส่วนต้นของข้อมูลโค้ด ToC ของคุณเพื่อหลีกเลี่ยงการเรียกใช้ฟังก์ชันหากฟิลด์นั้นว่างเปล่า อย่าลืมปิดด้วย "}"

ToC ภายในองค์ประกอบ Rich Text ของคุณ

หากคุณต้องการวาง ToC ของคุณไว้ในองค์ประกอบ Rich Text คุณสามารถจำลององค์ประกอบ ToC div ด้วยโค้ดฝังตัวได้

สร้างองค์ประกอบโค้ดที่กำหนดเองภายใน Rich Text แล้วคัดลอกและวาง "<div id="toc" class="toc"></div>" ในช่องโค้ด


หากคุณต้องการมี ToC แบบอินไลน์กับบางรายการ CMS และ ToC "ปกติ" สำหรับรายการอื่นๆ คุณต้องทำเทคนิคเพิ่มเติมสองสามข้อ:

1. สร้างตัวเลือกตัวเลือก ด้วยตัวเลือกเดียว: ".getElementById('content') เลือกในรายการ CMS ที่คุณต้องการให้มี ToC ภายใน Rich Text

2. แสดง ToC "ปกติ" เฉพาะเมื่อไม่ได้ตั้งค่าตัวเลือก


3. เพิ่มค่าของตัวเลือกไปยังส่วนต่อไปนี้ของรหัส ตอนนี้ หากเลือกตัวเลือกนี้แล้ว โค้ดจะผนวกรายการ ToC ภายใน ToC div ที่ถูกต้อง

หลีกเลี่ยงการวางซ้อนแถบนำทางบน scroll

คุณอาจสังเกตเห็นว่าเมื่อคลิกลิงก์ ToC หน้าจะเลื่อนลงไปที่หัวข้อที่ถูกต้อง แต่แถบนำทางของคุณถูกบล็อก

วิธีแก้ไขปัญหานี้:

  1. ตรวจสอบให้แน่ใจว่าตำแหน่งขององค์ประกอบการนำทางของคุณถูกตั้งค่าเป็น "คงที่"
  2. เปลี่ยนแท็กขององค์ประกอบนำทางเป็น "ส่วนหัว"

แค่นั้นแหละ! ในกรณีที่คุณประสบปัญหาใดๆ ระหว่างทาง โปรดส่งอีเมลถึงฉันหรือติดต่อผ่าน Twitter / LinkedIn

ฉันชอบที่จะทราบด้วยว่าคุณจะจบลงด้วยการใช้ระบบนี้หรือไม่ ดังนั้นโปรด ping หากคุณทำและแบ่งปันโพสต์กับคนอื่นที่อาจได้รับประโยชน์จากระบบนี้️