Search code examples
htmlcssbootstrap-4scrollspy

Bootstrap 4 - how to make scrollspy work without using nav or list-group?


Is there a way to make scrollspy work without using nav or list-group?

Bootstrap documentation for scrollspy states that it may be used only on nav or list group components. DOCUMENTATION

How it works

Scrollspy has a few requirements to function properly:

  • If you’re building our JavaScript from source, it requires util.js.
  • It must be used on a Bootstrap nav component or list group.
  • Scrollspy requires position: relative; on the element you’re spying on, usually the <body>.
  • When spying on elements other than the <body>, be sure to have a height set and overflow-y: scroll; applied.
  • Anchors (<a>) are required and must point to an element with that id.

This question is similar, but for Bootstrap 3 (not 4) and the answer is to add role="tablist". Well, it doesn't work here. There are many questions on SO about scrollspy, but mostly for Bootstrap 3.

CODE:

/*DEMO*/
nav{top:50%;left:1.5rem;transform:translateY(-50%)}
nav a{display:block;width:20px;height:20px;margin-bottom:.5rem}

/*COLORS*/
nav a{background:black}
nav a.active{background:red}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">

</head>
<body data-spy="scroll" data-target="#nav" data-offset="0">

<section class="container-fluid">
    <div class="row">
        <div id="item-1" class="col-12 vh-100 bg-primary"></div>
        <div id="item-2" class="col-12 vh-100 bg-warning"></div>
        <div id="item-3" class="col-12 vh-100 bg-danger"></div>
        <div id="item-4" class="col-12 vh-100 bg-success"></div>
        <div id="item-5" class="col-12 vh-100 bg-info"></div>
    </div>
</section>

<nav id="nav" class="d-flex flex-column position-fixed">
    <a href="#item-1"></a>
    <a href="#item-2"></a>
    <a href="#item-3"></a>
    <a href="#item-4"></a>
    <a href="#item-5"></a>
</nav>


<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>

</body>
</html>


Solution

  • You can overcome this by using the required class list-group-item and reset the CSS like you want:

    /*DEMO*/
    
    nav {
      top: 50%;
      left: 1.5rem;
      transform: translateY(-50%)
    }
    
    #nav a {
      display: block;
      width: 20px;
      height: 20px;
      margin-bottom: .5rem;
      padding: 0;
      border: none;
      border-radius: 0;
    }
    
    
    /*COLORS*/
    
    #nav a {
      background: black
    }
    
    #nav a.active {
      background: red
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
    
    </head>
    
    <body data-spy="scroll" data-target="#nav" data-offset="0">
    
      <section class="container-fluid">
        <div class="row">
          <div id="item-1" class="col-12 vh-100 bg-primary"></div>
          <div id="item-2" class="col-12 vh-100 bg-warning"></div>
          <div id="item-3" class="col-12 vh-100 bg-danger"></div>
          <div id="item-4" class="col-12 vh-100 bg-success"></div>
          <div id="item-5" class="col-12 vh-100 bg-info"></div>
        </div>
      </section>
    
      <nav id="nav" class="d-flex flex-column position-fixed">
        <a href="#item-1" class="list-group-item"></a>
        <a href="#item-2" class="list-group-item"></a>
        <a href="#item-3" class="list-group-item"></a>
        <a href="#item-4" class="list-group-item"></a>
        <a href="#item-5" class="list-group-item"></a>
      </nav>
    
    
      <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
      <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
    
    </body>
    
    </html>