Skip to content

Instantly share code, notes, and snippets.

@bhaveshxrawat
Last active March 1, 2024 16:21
Show Gist options
  • Save bhaveshxrawat/7c3b869c74797adfbb10655af2b4cfe2 to your computer and use it in GitHub Desktop.
Save bhaveshxrawat/7c3b869c74797adfbb10655af2b4cfe2 to your computer and use it in GitHub Desktop.
Intersection Observer
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Intersection Observer</title>
<link rel="stylesheet" href="style.css">
<script defer src="script.js"></script>
</head>
<body>
<main>
<article>
<h1>Main Heading</h1>
<h2>
Heading First
</h2>
<p>Lorem ipsum dolor sit...</p>
<h2>
Heading Second
</h2>
<p>Lorem ipsum dolor sit...</p>
<h2>
Heading Third
</h2>
<p>Lorem ipsum dolor sit...</p>
<h2>
Heading Fourth
</h2>
<p>Lorem ipsum dolor sit...</p>
<h2>
Heading Fifth
</h2>
<p>Lorem ipsum dolor sit...</p>
<h2>
Heading Sixth
</h2>
<p>Lorem ipsum dolor sit...</p>
<h2>
Heading Seventh
</h2>
<p>Lorem ipsum dolor sit...</p>
<h2>
Heading Eighth
</h2>
<p>Lorem ipsum dolor sit...</p>
<h2>
Heading Ninth
</h2>
<p>Lorem ipsum dolor sit...</p>
</article>
<aside></aside>
</main>
</body>
</html>
const headings = Array.from(document.getElementsByTagName("h2"));
const aside = document.querySelector("aside");
const ul = document.createElement("ul");
aside.appendChild(ul);
headings.map((heading) => {
const id = heading.innerText.toLowerCase().replaceAll(" ", "_");
heading.setAttribute("id", id);
const anchorElement = `<a href="#${id}">${heading.textContent}</a>`;
const keyPointer = `<li>${anchorElement}</li>`;
ul.insertAdjacentHTML("beforeend", keyPointer);
});
const tocAnchors = aside.querySelectorAll("a");
const obFunc = (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const index = headings.indexOf(entry.target);
tocAnchors.forEach((tab) => {
tab.classList.remove("active");
});
tocAnchors[index].classList.add("active");
tocAnchors[index].scrollIntoView({
block: "nearest",
inline: "nearest"
});
}
});
};
const obOption = {
rootMargin: "-30px 0% -77%",
threshold: 1
};
const observer = new IntersectionObserver(obFunc, obOption);
headings.forEach((hTwo) => observer.observe(hTwo));
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;600&display=swap');
html {
scroll-padding: 50px;
font-family: 'DM Sans', sans-serif;
}
main {
padding: 10px;
display: grid;
gap: 2rem;
grid-template-columns: 3fr 1fr;
}
aside {
padding: 16px;
background-color: rgba(1, 1, 1, 0.2);
align-self: start;
position: sticky;
top: 10px;
border-radius: 0.2em;
ul {
margin: 0;
padding: 0;
list-style: none;
li {
padding: 0.15em;
a {
color: inherit;
text-transform: none;
display: inline-block;
transform-origin: left;
transition: transform 0.1s linear;
&.active {
font-weight: 600;
transform: scale(1.1);
}
}
}
}
}
@media (max-width: 767px) {
main {
grid-template-columns: 1fr;
}
aside {
display: none;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment