Bootstrap 3 - ScrollSpy

Александр Мальцев
Александр Мальцев
31K
13
Содержание:
  1. Использования плагина ScrollSpy для создании навигации внутри страницы с помощью компонента Bootstrap Nav
  2. Событие activate.bs.scrollspy плагина ScrollSpy
  3. Комментарии

В этом уроке Вы узнаете, как использовать плагин "scrollspy", отвечающий за слежением положения прокрутки, для создания навигации внутри страницы с помощью платформы Bootstrap.

Использования плагина ScrollSpy для создании навигации внутри страницы с помощью компонента Bootstrap Nav

Плагин "ScrollSpy" применяется на сайтах, веб-страницы которого содержат огромное количество материала и пользователю трудно в нём ориентироваться. В таком случае разработчик может создать разделы на каждой страницы и с помощью плагина ScrollSpy отслеживать, в каком разделе остановился посетитель. В итоге у нас получится навигационное меню (nav), у которого будут подсвечиваться пункты по мере прокрутки страницы, тем самым подсказывая посетителю, в каком разделе он находится. Подсвечивающиеся пункты можно реализовать посредством добавления класса .active к пунктам навигационного меню (nav), основываясь на плагине "ScrollSpy", который будет отслеживать нахождения посетителя в том или ином разделе. Также с помощью навигационного меню можно будет переходить к соответствующим разделам страницы.

Добавить функциональность плагина "Scrollspy" в навигационное меню можно с помощью атрибутов data или сценариев на языке JavaScript.

Использование плагина Scrollspy с помощью атрибутов data

Для начала добавьте атрибут data-spy="scroll" к элементу, за которым вы хотите чтобы "scrollspy" наблюдал (как правило, это элемент body). Затем добавьте атрибут data-target с идентификатором (#id) или классом (.class) элемента-контейнера, который содержит навигационное меню (компонент nav). Для этого, чтобы это меню работало, вы должны иметь в основной части страницы разделы с идентификаторами, за которыми ScrollSpy будет следить, и они должны совпадать с атрибутом href пунктов навигационного меню, с помощью которых они ссылаются на эти разделы.

<body data-spy="scroll" data-target="#navbar-example">
  ...
  <!-- Навигационное меню -->
  <div class="navbar-example">
    <ul class="nav nav-tabs">
      <li class="active"><a href="#section1">1 Раздел</a></li>
      <li><a href="#section2">2 Раздел</a></li>
      <li><a href="#section3">3 Раздел</a></li>
    </ul>
  </div>

  <!-- Контент страницы, состоящий из разделов -->

  <h2 id="section1">1 Раздел</h2>
  <p><!--Содержание раздела --></p>

  <h4 id="section2">2 Раздел</h4>
  <p><!--Содержание раздела --></p>

  <h4 id="section3">3 Раздел</h4>
  <p><!--Содержание раздела --></p>

</body>

Использование плагина Scrollspy с помощью создания сценария на языке JavaScript

Вы можете вызвать "scrollspy" не только с помощью атрибутов data, но и с помощью сценария на языке JavaScript. В сценарии необходимо задать элемент, за которым необходимо наблюдать (например: body), а затем вызвать функцию .scrollspy(). Функции необходимо задать параметр "target", значением которого будет идентификатор или класс контейнера, в который помещено навигационное меню.

$('body').scrollspy({ target: '.navbar-example' })

Следующий пример демонстрирует использование плагина scrollspy с помощью атрибутов data

<!-- Контент страницы -->

<div data-spy="scroll" data-target="#navbar-example" data-offset="0" style="height:200px;overflow:auto; position: relative; border: 1px solid black; padding: 10px;">

  <h4 id="windows">Windows</h4>
  <p><!--Содержание раздела --></p>

  <h4 id="linux">Linux</h4>
  <p><!--Содержание раздела --></p>

  <h4 id="android">Android</h4>
  <p><!--Содержание раздела --></p>

  <h4 id="ios">iOS</h4>
  <p><!--Содержание раздела --></p>

  <h4 id="wphone">Windows Phone</h4>
  <p><!--Содержание раздела --></p>
</div>

<!-- Навигационное меню -->
<nav id="navbar-example" class="navbar navbar-default navbar-static" role="navigation">
  <div class="navbar-header">
    <button class="navbar-toggle" type="button" data-toggle="collapse" data-target=".navbar-scrollspy">
      <span class="sr-only">Toggle navigation</span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </button>
  </div>
  <div class="collapse navbar-collapse navbar-scrollspy">
    <!-- Пункты навигационного меню -->
    <ul class="nav navbar-nav">
      <li><a href="#windows">Windows</a></li
      <li><a href="#linux">Linux</a></li>
      <li><a href="#android">Android</a></li>
      <li><a href="#ios">iOS</a></li>
      <li><a href="#wphone">Windows Phone</a></li>
      </ul>
    </div>
</nav>
Bootstrap 3 - ScrollSpy

Параметр offset плагина ScrollSpy

У плагина "Scrollspy" есть один параметр offset, который можно установить с помощью атрибута data (например: data-offset="0") или с помощью JavaScript (например: $(".scroll-area").scrollspy({target: "#myNavbar", offset: 500})). Данный параметр предназначен для задания количества пикселей от верхнего края при расчете позиции прокрутки. По умолчанию, значения данного параметра равно 10.

Метод scrollspy('refresh')

При вызове метода "scrollspy" через JavaScript Вам необходимо вызвать метод .refresh для обновления объектной модели документа (DOM). Это полезный метод, если какие-то элементы DOM изменились, т.е. если вы добавили или удалили некоторые элементы из объектной модели документа HTML. Нижеприведенный код использует этот метод:

$('body').each(function () {
  var $spy = $(this).scrollspy('refresh')
});
Следующий пример демонстрирует использование метода .scrollspy('refresh'):
<!-- Контент страницы, состоящий из разделов -->
<div id="mySampleText" data-spy="scroll" data-target="#myScrollspy2" data-offset="0"
    style="height:200px;overflow:auto; position: relative;">
    <div class="section">
      <h4 id="html">HTML<small><a href="#" onclick="removeSection(this);">
          &times; Удалить эту секцию</a></small>
      </h4>
      <p>Содержимое раздела...</p>
    </div>
    <div class="section">
      <h4 id="css">CSS</h4>
      <p>Содержимое раздела...</p>
    </div>
    <div class="section">
      <h4 id="bootstrap3">Bootstrap 3<small><a href="#" onclick="removeSection(this);">
      &times; Удалить эту секцию</a></small>
      </h4>
      <p>Содержимое раздела...</p>
    </div>
</div>

<!-- Навигационное меню -->
<nav id="myScrollspy2" class="navbar navbar-default navbar-static" role="navigation">
    <div class="navbar-header">
      <button class="navbar-toggle" type="button" data-toggle="collapse"
          data-target=".navbar-scrollspy2">
          <span class="sr-only">Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
      </button>
    </div>
    <div class="collapse navbar-collapse navbar-scrollspy2">
      <ul class="nav navbar-nav">
          <li class="active"><a href="#html">HTML</a></li>
          <li><a href="#css">CSS</a></li>
          <li><a href="#bootstrap3">Bootstrap 3</a></li>
      </ul>
    </div>
</nav>

<!-- Скрипт на языке JavaScript -->
<script type="text/javascript">
    $(function(){
    removeSection = function(e) {
      $(e).parents(".section").remove();
      $("#mySampleText").each(function () {
          var $spy = $(this).scrollspy('refresh')
      });
    }
    $("#myScrollspy2").scrollspy();
});
</script>
Bootstrap 3 - Использование метода scrollspy refresh

Событие activate.bs.scrollspy плагина ScrollSpy

Плагин Bootstrap scrollspy включает в себя событие activate.bs.scrollspy, которое предназначено для перехвата состояния плагина scrollspy. Это событие срабатывает каждый раз, когда новый элемент активируется с помощью плагина scrollspy, который эти элементы отслеживает. Например: $('#myScrollspy').on('activate.bs.scrollspy', function () { // do something… })

Следующий пример демонстрирует использование события activate.bs.scrollspy:

<body data-spy="scroll" data-target="#myScrollspy">

<!-- Навигационное меню -->
<nav id="myScrollspy" class="navbar navbar-default navbar-static" role="navigation">
    <div class="navbar-header">
      <button class="navbar-toggle" type="button" data-toggle="collapse"
          data-target=".navbar-scrollspy">
          <span class="sr-only">Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
      </button>
    </div>
    <div class="collapse navbar-collapse navbar-scrollspy">
      <ul class="nav navbar-nav">
          <li class="active"><a href="#computer">Компьютер</a></li>
          <li><a href="#laptop">Ноутбук</a></li>
          <li><a href="#tablet">Планшет</a></li>
      </ul>
    </div>
</nav>

<!-- Основное содержимое -->
<div data-spy="scroll" data-target="#myScrollspy" data-offset="0"
    style="height:200px;overflow:auto; position: relative;">
    <div class="section">
      <h4 id="computer">Компьютер<small><a href="#" onclick="removeSection(this);">
          &times; Удалить эту секцию</a></small>
      </h4>
      <p>Содержимое секции...</p>
    </div>
    <div class="section">
      <h4 id="laptop">Ноутбук<small></small></h4>
      <p>Содержимое секции...</p>
    </div>
    <div class="section">
      <h4 id="tablet">Планшет<small><a href="#" onclick="removeSection(this);">
          &times; Удалить эту секцию</a></small>
      </h4>
      <p>Содержимое секции...</p>
    </div>
  </div>

<!-- Сценарий на языке JavaScript -->
<script type="text/javascript">
    $(function(){
      removeSection = function(e) {
      $(e).parents(".section").remove();
      $('[data-spy="scroll"]').each(function () {
          var $spy = $(this).scrollspy('refresh')
      });
    }
    $("#myScrollspy").scrollspy();
    $('#myScrollspy').on('activate.bs.scrollspy', function () {
      var currentItem = $(".nav li.active > a").text();
      alert("Сейчас вы находитесь - " + currentItem);
    })
});
</script>

</body>
Навигационное меню

Комментарии:

  1. Евгений
    02.09.2017, 09:13
    Здравствуйте. Не знаю точно, по этой ли это теме, но мне нужно, например, что бы при переходе по ссылке site.com/#popup на сайте при загрузке страницы открылся попала с id popup, не подскажите как реализовать?
    1. Александр Мальцев
      03.09.2017, 04:08
      Здравствуйте! Посмотрите этот комментарий.
    2. A
      08.08.2017, 14:03
      Почему не работает history и scrollspy?
      1. Александр Мальцев
        08.08.2017, 15:18
        А как они должны быть связаны? Scrollspy — это компонент, который на основании положения о прокрутке просто подсвечивает тот или иной пункт меню. Если вам нужна какая-то логика, то нужно её писать на JavaScript.
        1. A
          08.08.2017, 19:09
          codepen.io/SitePoint/full/GgOzwX
          Если запустить исходный код в браузере, то history в навигации работает или мне кажется. Нужно так же но чтобы компоненты лежали не в <body а в <div class=«scroll-area1»…
          Есть ли техничное стандартное решение? Велосипед сделать не проблема
          1. Александр Мальцев
            09.08.2017, 16:32
            Понял. Вы имеете виду про ссылку, которая ведёт на элемент, расположенный внутри этой страницы. Назовём её, например, 1. При нажатии на неё, она будет добавлена в history. И у вас стрелочка «Назад» станет активной. При нажатии ещё на какую-то ссылку (например, 2), она также будет добавлена в history. Если вы после этого нажмёте на стрелочку «Назад», то браузер перейдёт по ссылке 1. Но так как ссылка ведёт на эту же страницу, то браузер просто прокрутит контент страницы к элементу, соответствующему hash этой ссылке. Но, это случится только в том случае, если этот элемент не расположен в прокручиваемом элементе. Но, насколько понимаю, вы хотите именно это. Т.е. чтобы браузер прокрутил страницу, к контейнеру, в котором расположен этот элемент. А потом прокрутил ещё и его содержимое до этого элемента. Это браузер делать не будет. Если вам необходимо такой функционал, то его необходимо будет реализовывать самому, т.е. «городить велосипед». Не совсем понятно как это связано с ScrollSpy, он ведь никакого отношения к этому не имеет.
            1. A
              09.08.2017, 18:51
              Я хочу чтобы меню и контент лежали в разных scrollarea's и стрелочка back отрабатывала на предыдущее состояние. В примере этой работает если скролл в body Если скролл положить не в body то не работает Интуитивно понятно же что я хочу или нет:)))
              1. Александр Мальцев
                10.08.2017, 15:13
                Понятно, что вы хотите. Но, тут нет стандартного решения. Здесь необходимо писать JavaScript сценарий. Его написание будет зависеть от логики работы вашей страницы. Тем более что в JavaScript нет события, которое бы обрабатывала нажатие кнопки «Назад» или «Вперёд». Тут необходимо использовать событие hashchange.
                $(window).on('hashchange', function(){
                  //...
                });
                Его содержимое должно выполнять следующее:
                1. Как-то узнать, что изменения hash страницы связано с переходом по кнопки «Назад» или «Вперёд». Если это не связано с кликом по одной из кнопок, то прервать выполнение функции.
                2. Определить положения родительского элемента и соответственно позицию прокручиваемого элемента внутри него.
                3. Прокрутить страницу и содержимое прокручиваемого элемента до цели.
                1. A
                  10.08.2017, 16:24
                  Благодарю за помощь.
      2. Gleb
        14.12.2015, 14:47
        Здравствуйте, у меня следующий вопрос.

        Я так понял он закреплен в class=«nav» при прокрутке разделы подсвечиваются, у меня иная задача отключить подсветку разделов при прокрутке, но оставить при наведении. Каким образом можно реализовать?
        1. Александр Мальцев
          15.12.2015, 06:37
          Здравствуйте.
          В этом случае не используйте ScrollSpy.
        2. Николай
          11.01.2015, 12:31
          Можно ли как-то сделать ScrollSpy с плавной прокруткой страницы, а не резкими переходами?
          1. Александр Мальцев
            11.01.2015, 14:59
            Вы наверно имели в виду Affix, т.к. ScrollSpy используется для отслеживания положения прокрутки. Да, к элементу, для которого применён Affix наблюдается такой эффект, который происходит в момент открепления элемента от его текущего положения при прокрутке (из static в fixed) и в момент закрепления его (из fixed в static). Это всё связано с разным значением свойства top в 2 его положениях (static и fixed).

            Николай, если это возможно на сайте, то установите одинаковые значения top, тогда скачка не будет. Или хотя уменьшите эту разницу насколько возможно, тогда этот скачок будет меньше.

            Но если это не возможно, тогда можно только сгладить этот эффект с помощью анимации. Например, если у вас элемент в static имеет «top: 80px», а в fixed имеет «top: 100px», то эти 20px ни куда не денешь. И у вас возникает резкий переход в 20px видимый глазу. Например, анимацию можно сделать с помощью jquery.scrollTo или чего-нибудь другого.
          Войдите, пожалуйста, в аккаунт, чтобы оставить комментарий.