Scrollspy using HTML CSS and JavaScript
Last Updated :
23 Jul, 2024
In this article, we will learn about Scrollspy which is a popular feature used in modern web applications. It is used to highlight and allow to navigate through different sections of long web pages as the user scrolls. It increases the interaction between the user and the web application by providing visual cues and making it easier to navigate through content.
Approach:
- To apply the Scrollspy using CSS, the basic idea is to define a set of styles that change dynamically based on the scroll position. This is achieved by utilizing CSS selectors and the :target pseudo-class.
- HTML pages need to be organized into sections, each with a unique identifier using the id attribute. This section contains different content areas of the page.
- CSS is defined for the sections and the navigation menu.
- Apply Javascript to handle the navigation by applying the :active to the class.
Example: In this example, we will create a scrollspy by creating a different section.
HTML
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Scrollspy</title>
<link href="style.css" rel="stylesheet">
</head>
<body>
<main>
<nav class="section-nav">
<ol>
<li>
<a href="#introduction">
GeeksforGeeks
</a>
</li>
<li>
<a href="#request-response">
Write & Earn
</a>
</li>
<li>
<a href="#authentication">
Problem solving
</a>
</li>
<li>
<a href="#endpoints">
Courses
</a>
<ul>
<li class="">
<a href="#endpoints--root">
Data Structure
</a>
</li>
<li class="">
<a href="#endpoints--cities-overview">
Java
</a>
</li>
<li class="">
<a href="#endpoints--city-detail">
DBMS
</a>
</li>
<li class="">
<a href="#endpoints--city-config">
JavaScript
</a>
</li>
<li class="">
<a href="#endpoints--city-spots-overview">
Python
</a>
</li>
</ul>
</li>
</ol>
</nav>
<div class="contentArea">
<h1>GeeksforGeeks</h1>
<section id="introduction">
<h2>GeeksforGeeks</h2>
<p>…</p>
</section>
<section id="request-response">
<h2>Write & Earn</h2>
<p>…</p>
</section>
<section id="authentication">
<h2>Problem Solving</h2>
<p>…</p>
</section>
<section id="endpoints">
<h2>Courses</h2>
<section id="endpoints--root">
<h3>Data Structure</h3>
<p>…</p>
</section>
<section id="endpoints--cities-overview">
<h3>Java</h3>
<p>…</p>
</section>
<section id="endpoints--city-detail">
<h3>DBMS</h3>
<p>…</p>
</section>
<section id="endpoints--city-config">
<h3>JavaScript</h3>
<p>…</p>
</section>
<section id="endpoints--city-spots-overview">
<h3>Python</h3>
<p>…</p>
</section>
<section id="endpoints--city-spot-detail">
<h3>C/C++</h3>
<p>…</p>
</section>
</section>
</div>
</main>
</body>
</html>
CSS
/* style.css */
:root {
--linkheight: 2rem;
}
* {
box-sizing: border-box;
margin: 0px;
padding: 0px;
}
html {
scroll-behavior: smooth;
}
ul,
ol {
list-style: none;
}
ul {
background-color: rgb(0 0 0 / 0);
}
ul li {
padding-left: 1rem;
}
.section-nav {
display: flex;
flex-direction: row;
width: 15em;
position: fixed;
top: 2rem;
right: 2rem;
padding-left: 0;
border-left: 1px solid #ddd;
background-color: rgb(0 0 0 / 0);
}
.section-nav a {
display: inline-block;
text-decoration: none;
line-height: 2rem;
padding: 0 1rem;
color: #202020;
}
.section-nav a:hover,
.section-nav a:focus {
color: rgb(9, 153, 59);
text-decoration: underline;
}
h1 {
text-align: center;
font-weight: 1000;
color: rgb(9, 153, 59);
width: calc(100% - 7.5em);
margin: 1rem 0;
}
main {
width: 80%;
margin: 0 auto;
}
section {
padding-bottom: 20rem;
}
section:nth-of-type(even) {
padding-bottom: 20rem;
}
section:nth-of-type(1) {
background:
right 2rem
top 2rem / 15em var(--linkheight)
no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(2) {
background:
right 2rem top
calc(2 * var(--linkheight)) / 15em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(3) {
background: right 2rem top
calc(3 * var(--linkheight)) / 15em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(4) {
padding-bottom: 0;
background: right 2rem top
calc(4 * var(--linkheight)) / 15em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(4) section:nth-of-type(1) {
background: right 2rem top
calc(5 * var(--linkheight)) / 14em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(4) section:nth-of-type(2) {
background: right 2rem top
calc(6 * var(--linkheight)) / 14em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(4) section:nth-of-type(3) {
background: right 2rem top
calc(7 * var(--linkheight)) / 14em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(4) section:nth-of-type(4) {
background: right 2rem top
calc(8 * var(--linkheight)) / 14em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(4) section:nth-of-type(5) {
background: right 2rem top
calc(9 * var(--linkheight)) / 14em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(4) section:nth-of-type(6) {
background: right 2rem top
calc(10 * var(--linkheight)) / 14em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(4) section:nth-of-type(7) {
background: right 2rem top
calc(11 * var(--linkheight)) / 14em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(4) section:nth-of-type(8) {
background: right 2rem top
calc(12 * var(--linkheight)) / 14em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(5) {
background: right 2rem top
calc(13 * var(--linkheight)) / 15em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(6) {
background: right 2rem top
calc(14 * var(--linkheight)) / 15em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(7) {
background: right 2rem top
calc(15 * var(--linkheight)) / 15em
var(--linkheight) no-repeat
linear-gradient(#ccc, #ccc);
}
section:nth-of-type(n),
section:nth-of-type(4) section:nth-of-type(n) {
background-attachment: fixed;
}
Output:
Example 2: In this example, use some JavaScript code to build a Scrollspy to navigate through content.
HTML
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<nav class="navbar">
<ul>
<li><a href="#section1">Section 1</a></li>
<li><a href="#section2">Section 2</a></li>
<li><a href="#section3">Section 3</a></li>
<li><a href="#section4">Section 4</a></li>
</ul>
</nav>
<div id="section1" class="section">Section 1</div>
<div id="section2" class="section">Section 2</div>
<div id="section3" class="section">Section 3</div>
<div id="section4" class="section">Section 4</div>
<script src="script.js"></script>
</body>
</html>
CSS
/*Add code in styles.css file*/
body {
margin: 0;
padding: 0;
}
a {
text-decoration: none;
color: black;
background-color: white;
padding: 10px;
border-radius: 10px;
}
.navbar {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: lightgray;
z-index: 999;
}
.navbar ul {
list-style-type: none;
display: flex;
justify-content: center;
padding: 0;
margin: 0;
}
.navbar li {
border-radius: 20px;
padding: 10px;
margin: 10px 10px;
}
.navbar li:active {
font-weight: bold;
color: green;
}
.section {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
}
.section:nth-child(even) {
background-color: rgb(8, 143, 44);
}
.section:nth-child(odd) {
background-color: lightblue;
}
.navbar li.active {
font-weight: bold;
}
JavaScript
// script.js
document.addEventListener('DOMContentLoaded', function () {
const navbarLinks =
document.querySelectorAll('.navbar a');
const sections =
document.querySelectorAll('.section');
window.addEventListener('scroll', function () {
const currentPos = window.scrollY;
sections.forEach(function (section) {
const sectionTop = section.offsetTop - 50;
const sectionHeight = section.offsetHeight;
const sectionId = section.getAttribute('id');
if (currentPos >= sectionTop &&
currentPos < sectionTop + sectionHeight) {
navbarLinks.forEach(function (navbarLink) {
navbarLink.classList.remove('active');
});
document.querySelector('.navbar a[href="#'
+ sectionId + '"]')
.classList.add('active');
}
});
});
});
Output:
Similar Reads
Create an Infinite Scroll Page using HTML CSS & JavaScript In this article, we will create an infinite scroll page using HTML, CSS, and JavaScript. Infinite scrolling allows you to load and display content as the user scrolls down the page, providing a seamless browsing experience. We'll fetch and append new content dynamically as the user reaches the end o
2 min read
How to Create Scroll Indicator using HTML CSS and JavaScript ? Scroll Indicator is a progress bar that represents how much a page has been scrolled. When we scroll down the bar fills up and when we scroll up the bar amount reduces. Approach: Now, we will create a basic webpage with text to enable scrolling and then use JavaScript to make the scroll indicator wo
3 min read
Slide Down a Navigation Bar on Scroll using HTML, CSS and JavaScript To create a slide down navigation bar you need to use HTML, CSS, and JavaScript. HTML will make the structure of the body, CSS will make it looks good. This kind of sliding navbar looks attractive on a site. By using JavaScript you can easily make the navigation bar slideable when the user scrolls d
4 min read
How to Create Shrink Header on Scroll using HTML, CSS and JavaScript ? The Shrink Navigation bar works when the user scrolls down the page. In this article, we will use HTML, CSS, and JavaScript to design a shrink navigation bar. HTML is used to create the structure, and CSS is used to set the style of the HTML structure to make it looks good. This kind of shrinking na
3 min read
Check whether HTML element has scrollbars using JavaScript Given an HTML document, the task is to identify whether a particular element has scrollbars or not. In this article, we are going to check whether the HTML element has scrollbars using JavaScript. Below are the different approaches to check whether HTML element has scrollbars using JavaScript: Table
3 min read