Open In App

Scrollspy using HTML CSS and JavaScript

Last Updated : 22 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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:

scrollspy

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:

scrollspyOne

Output



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads