Как установить смещение для ScrollSpy в Bootstrap?

У меня есть сайт с навигационной панелью, установленной сверху, и 3 divs внизу в основной области содержимого.

Я пытаюсь использовать scrollspy из фреймворка bootstrap.

У меня он успешно выделяет различные заголовки в меню, когда вы прокручиваете div div.

У меня также есть это, поэтому, когда вы нажимаете меню, оно будет прокручиваться до нужной части страницы. Однако неверно смещение (это не учитывает навигационную панель, поэтому мне нужно компенсировать примерно 40 пикселей)

Я вижу на странице Bootstrap в ней упоминается опция смещения, но я не уверен, как ее использовать.

Я тоже не то, что это означает, когда говорится, что вы можете использовать scrollspy с $('#navbar').scrollspy(), я не уверен, где его включить, поэтому я не сделал и все, кажется, работает (кроме смещения).

Я думал, что смещение может быть data-offset='10' в теге body, но для меня это ничего не делает.

У меня такое ощущение, что это что-то действительно очевидное, и я просто пропустил его. Любая помощь?

Мой код

...
<!-- note: the data-offset doesn't do anything for me -->
<body data-spy="scroll" data-offset="20">
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
    <div class="container">
    <a class="brand" href="#">VIPS</a>
    <ul class="nav">
        <li class="active">
             <a href="#trafficContainer">Traffic</a>
        </li>
        <li class="">
        <a href="#responseContainer">Response Times</a>
        </li>
        <li class="">
        <a href="#cpuContainer">CPU</a>
        </li>
      </ul>
    </div>
</div>
</div>
<div class="container">
<div class="row">
    <div class="span12">
    <div id="trafficContainer" class="graph" style="position: relative;">
    <!-- graph goes here -->
    </div>
    </div>
</div>
<div class="row">
    <div class="span12">
    <div id="responseContainer" class="graph" style="position: relative;">
    <!-- graph goes here -->
    </div>
    </div>
</div>
<div class="row">
    <div class="span12">
    <div id="cpuContainer" class="graph" style="position: relative;">
    <!-- graph goes here -->
    </div>
    </div>
</div>
</div>

...
<script src="assets/js/jquery-1.7.1.min.js"></script>
<script src="assets/js/bootstrap-scrollspy.js"></script>
</body>
</html>

Ответ 1

Bootstrap использует смещение, чтобы разрешить только шпионаж, а не прокрутку. Это означает, что прокрутка в нужное место зависит от вас.

Попробуйте это, он работает для меня: добавьте обработчик событий для кликов навигации.

var offset = 80;

$('.navbar li a').click(function(event) {
    event.preventDefault();
    $($(this).attr('href'))[0].scrollIntoView();
    scrollBy(0, -offset);
});

Я нашел его здесь: https://github.com/twitter/bootstrap/issues/3316

Ответ 2

Трюк, о котором говорил Тим, заключается в том, чтобы воспользоваться дополнением. Поэтому проблема заключается в том, что ваш браузер всегда хочет прокрутить якорь до точной вершины окна. если вы установите свой якорь там, где ваш текст на самом деле начинается, он будет закрыт вашей панелью меню. Вместо этого вы устанавливаете привязку к тегу id контейнера <section> или <div>, который автоматически использует nav/navbar. Затем вы должны установить padding-top для контейнера в нужное количество и margin-top для контейнера в противоположность padding-top. Теперь ваш контейнерный блок и якорь начинаются с точной вершины страницы, но содержимое внутри не начинается до строки меню.

Если вы используете обычные якоря, вы можете выполнить одно и то же, используя отрицательный край верхнего края в вашем контейнере, как указано выше, но без заполнения. Затем вы помещаете обычный якорь <a target="..."> в качестве первого дочернего элемента контейнера. Затем вы создаете второй дочерний элемент с противоположным, но равным margin-top, но используя селектор .container:first-child +.

Все это предполагает, что тэг <body> уже имеет свой маркер, установленный для начала ниже вашего заголовка, что является нормой (иначе страница будет отображать с окклюдированным текстом с места в карьер).

Вот пример этого в действии. Все, что есть на вашей странице с идентификатором, можно связать, привязав идентификатор # the-elements-id к концу вашего URL-адреса. Если вы делаете все свои h теги ad dt с идентификаторами ссылок ids (Как и github) с своего рода script, который вводит небольшую ссылку слева от них; добавив следующее в ваш CSS, вы позаботитесь о смещении nav-bar для вас:

body {
    margin-top: 40px;/* make room for the nav bar */
}

/* make room for the nav bar */
h1[id],
h2[id],
h3[id],
h4[id],
h5[id],
h6[id],
dt[id]{
    padding-top: 60px;
    margin-top: -40px;
}

Ответ 3

Вы можете изменить смещение scrollspy на лету с этим (предполагая, что вы следите за телом):

offsetValue = 40;
$('body').data().scrollspy.options.offset = offsetValue;
// force scrollspy to recalculate the offsets to your targets
$('body').data().scrollspy.process();

Это также работает, если вам нужно динамически изменять значение смещения. (Мне нравится, когда scrollspy переключается, когда следующий раздел находится примерно на полпути окна, поэтому мне нужно изменить смещение во время изменения размера окна.)

Ответ 4

Если вы хотите смещение 10, вы бы поставили это в свою голову:

<script>
  $('#navbar').scrollspy({
    offset: 10
  });
</script>

Твой тег тела будет выглядеть так:

<body data-spy="scroll">

Ответ 5

Из начальной загрузки № 3316:

[Это] предназначено только для изменения расчетов прокрутки - мы не сдвигаем фактический щелчок привязки

Таким образом, установка смещения влияет только на , когда scrollspy считает, что страница прокручена до. не влияет на прокрутку при нажатии на тег привязки.

Использование фиксированной панели навигации означает, что браузер прокручивает в неправильное место. Вы можете исправить это с помощью JavaScript:

var navOffset = $('.navbar').height();

$('.navbar li a').click(function(event) {
    var href = $(this).attr('href');

    // Don't let the browser scroll, but still update the current address
    // in the browser.
    event.preventDefault();
    window.location.hash = href;

    // Explicitly scroll to where the browser thinks the element
    // is, but apply the offset.
    $(href)[0].scrollIntoView();
    window.scrollBy(0, -navOffset);
});

Однако, чтобы scrollspy выделил правильный текущий элемент, вам все равно нужно установить смещение:

<body class="container" data-spy="scroll" data-target=".navbar" data-offset="70">

Здесь полная демонстрация JSFiddle.


В качестве альтернативы, вы можете добавить свои теги привязки, как предложено в хитростях CSS.

a[id]:before { 
  display: block; 
  content: " ";
  // Use the browser inspector to find out the correct value here.
  margin-top: -285px; 
  height: 285px; 
  visibility: hidden; 
}

Ответ 6

Я думаю, что смещение может сделать что-то с нижней позицией секции.

Я исправил свою проблему - то же, что и ваш, добавив

  padding-top: 60px;

в объявлении для раздела в bootstrap.css

Надеюсь, что это поможет!

Ответ 7

Я добавил элемент 40px-height .vspace, удерживающий якорь перед каждым из моих элементов h1.

<div class="vspace" id="gherkin"></div>
<div class="page-header">
  <h1>Gherkin</h1>
</div>

В CSS:

.vspace { height: 40px;}

Он отлично работает, и пространство не забивается.

Ответ 8

Bootstrap 4 (обновление 2019 года)

Реализация: исправлена навигация, прокрутка и плавная прокрутка

Это решение из @wilfred-hughes выше, оно точно устраняет проблему с перекрытием с помощью фиксированной навигационной панели Bootstrap с помощью CSS ":: before" для добавления не отображаемого блока перед каждым тегом раздела. Преимущество: вы не получите ненужных отступов между разделами. Например, раздел 3 можно расположить вертикально вверх против раздела 2, и он все равно будет прокручиваться до точного правильного положения вверху раздела 3.

Примечание: установка смещения scrollspy в теге script не привела ни к чему ($ ('# navbar'). Scrollspy ({   смещение: 105 });) и попытки отрегулировать смещение в блоке анимации все же привели к смещению пост-анимации.

index.html

<section id="section1" class="my-5">
...
<section id="section2" class="my-5">
...
<section id="section3" class="my-5">
...

позже в index.html...

 <script>
      // Init Scrollspy
      $('body').scrollspy({ target: '#main-nav' });

      // Smooth Scrolling
      $('#main-nav a').on('click', function(event) {
        if (this.hash !== '') {
          event.preventDefault();

          const hash = this.hash;

          $('html, body').animate(
            {
              scrollTop: $(hash).offset().top
            },
            800,
            function() {
              window.location.hash = hash;
            }
          );
        }
      });
    </script>

style.css:

// Solution to Fixed NavBar overlapping content of the section.  Apply to each navigable section.
// adjust the px values to your navbar height
// Source: https://github.com/twbs/bootstrap/issues/1768
#section1::before,
#section2::before,
#section3::before {
  display: block;
  content: ' ';
  margin-top: -105px;
  height: 105px;
  visibility: hidden;
}

body {
  padding-top: 105px;
}

Кредит: @wilfred-hughes выше и оригинальный источник от пользователя @mnot на https://github.com/twbs/bootstrap/issues/1768

Ответ 9

У меня были проблемы с решениями acjohnson55 и Kurt UXD. Оба работали для клика по ссылке на хеш, но смещение scrollspy все еще не корректно.

Я придумал следующее решение:

<div class="anchor-outer">
  <div id="anchor">
    <div class="anchor-inner">
      <!-- your content -->
    </div>
  </div>
</div>

И соответствующий CSS:

body {
  padding-top:40px;
}

.anchor-outer {
  margin-top:-40px;
}

.anchor-inner {
  padding-top:40px;
}

@media (max-width: 979px) {
  body {
    padding-top:0px;
  }

  .anchor-outer {
    margin-top:0px;
  }

  .anchor-inner {
    padding-top:0px;
  }
}

@media (max-width: 767px) {
  body {
    padding-top:0px;
  }

  .anchor-outer {
    margin-top:0px;
  }

  .anchor-inner {
    padding-top:0px;
  }
}

Вам потребуется заменить 40px padding/margin высотой вашего навигатора и идентификатором вашего якоря.

В этой настройке я могу даже наблюдать эффект установки значения для атрибута смещения данных. Если найти большие значения для смещения данных около 100-200, приведет к более ожидаемому поведению (переключатель scrollspy - "произойдет", если заголовок будет около середины экрана).

Я также обнаружил, что scrollspy очень чувствительна к ошибкам, таким как закрытые теги div (что совершенно очевидно), поэтому http://validator.w3.org/check был моим другом здесь.

По моему мнению, scrollspy лучше всего работает с целыми секциями, несущими идентификатор привязки, поскольку обычные элементы привязки не приводят к ожидаемым эффектам при прокрутке назад (переключатель scrollspy "в конце концов происходит, как только вы нажимаете на элемент привязки, например, ваш заголовок, но в то время вы уже прокрутили содержимое, которое пользователь ожидает от соответствующего заголовка).

Ответ 10

Вы также можете открыть bootstap-offset.js и изменить

$.fn.scrollspy.defaults = {
  offset: 10
}

есть.

Ответ 11

Просто установите:

data-offset="200"

data-offset по умолчанию равен "50", и это эквивалентно 10px, поэтому просто увеличьте data-offset и ваша проблема будет решена.