I managed to solve the first issue by setting up the root margin in the code.
Here is the code I used:
<script>
const options = {
rootMargin: '0px 0px -80% 0px'
};
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");
}
});
},options);
</script>
<script>
document.getElementById("content").querySelectorAll("h2,h3,h4").forEach(function(heading, i) { // runs a function for all headings inside your rich text element
observer.observe(heading);
heading.setAttribute("id", "toc-" + i); // 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
("h2,h3,h4").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", "#toc-" + i); // gives each item the correct anchor link
document.querySelector("#toc").appendChild(item); // places each item inside the Table of Contents div
});
</script>