Як встановити зміщення для ScrollSpy в Bootstrap?


98

У мене є сайт з фіксованим наверхом на верхній панелі та 3 дівами внизу в основній області вмісту.

Я намагаюся використовувати scrollspy з рамок завантаження.

У мене це вдало підкреслює різні заголовки в меню, коли ви прокручуєте повз діви.

У мене також є, тому коли ви натискаєте меню, воно прокручується до потрібної частини сторінки. Однак зсув є неправильним (це не враховує навібар, тому мені потрібно компенсувати приблизно 40 пікселів)

Я бачу на сторінці Bootstrap, вона згадує варіант зміщення, але я не впевнений, як ним користуватися.

Я також не значу $('#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>

Чому ви даєте позицію: стосовно ваших дівок? Можливо, це і є причиною цього. Чи можете ви створити jsfiddle зі своїм кодом, щоб ми могли бачити в дії?
перикліс

Відповіді:


113

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/isissue/3316


3
Дякую за відповідь. Займав мене досить довго, щоб зрозуміти, що зміщення не впливає на прокрутку. Це означає, що всі, хто використовує фіксовану верхівку, повинні вручну регулюватися таким чином.
Брайан Сміт

8
Щоб належним чином оновити хеш-розділ URL-адреси, додайте window.location.hash = $(this).attr('href')до цієї функції.
Стівен М. Харріс

2
Дякую! FWIW також має значення зміщення даних в тілі, оскільки заявник каже, що нічого не робить, але це потрібно для належного шпигування. Це може допомогти отримати вичерпну відповідь.
mrooney

4
Динамічний виграш: var navOffset = $('#navbar').height();іscrollBy(0, -navOffset);
ahnbizcad

78

Трюк, як нагадав Тім, полягає в тому, щоб скористатися перевагами. Отже, проблема полягає в тому, що ваш браузер завжди хоче прокрутити якір до точної вершини вікна. якщо ви встановите якір там, де фактично починається ваш текст, він буде закритий рядком меню. Натомість те, що ви робите, - це встановити якір на ідентифікатор контейнера <section>або <div>тегу, який автоматично використовуватиме navi / navbar. Тоді вам доведеться встановити ваш padding-topконтейнер на потрібну компенсацію, а margin-topдля контейнера - на протилежну від padding-top. Тепер блок вашого контейнера та прив'язка починаються в точній частині сторінки, але вміст всередині не починається, поки не знаходиться рядок меню.

Якщо ви користуєтеся звичайними якорями, ви можете зробити те ж саме, використовуючи негативний запас у верхній частині контейнера, як вище, але без прокладки. Потім ви ставите звичайний <a target="...">якір як першу дитину контейнера. Потім ви стилюєте другий дочірній елемент з протилежним, але рівним margin-top, але використовуючи селектор .container:first-child +.

Це все передбачає, що для вашого <body>тегу вже встановлено поле, яке починається нижче заголовка, що є нормою (інакше сторінка відображатиметься із окклюдованим текстом прямо з bat).

Ось приклад цього в дії. Все, що є на вашій сторінці, має ідентифікатор, можна пов’язати, натиснувши # the-elements-id в кінці вашої URL-адреси. Якщо ви робите всі свої теги h теги ad dt з ідентифікаторами, що мають посилання ( як це робить github ), з якимсь сценарієм, який вводить трохи посилання зліва від них ; додавши до CSS наступне, подбає про зміщення смуги навігації для вас:

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;
}

9
Любіть комбінований верх, негативне поле від нижнього (на тому ж елементі) комбо. Легше тоді возитися з js.
Ейстейн

Схоже, найкраща відповідь, але я трохи загубився. Будь-який шанс прикладу.
eddyparkinson

@eddyparkinson, напевно, ви зрозуміли це прямо зараз: Наприклад, коли у вас є ідентифікатор у рядках завантажувальної програми: .row [id] {padding-top: 60px; margin-top: -40px; } Помістіть це у вашому менш файлі: .row [id] {padding-top: 60px; margin-top: -40px; }
Клаас

Хіба для цього не повинен бути встановлений параметр зсуву за замовчуванням для завантажувача? Здається, що така очевидна річ включати, і не доведеться вдаватися до подібних обхідних шляхів.
ahnbizcad

Це ефективно додає додатковий простір у div, на який ви орієнтуєтесь? Що робити, якщо ви цього не хочете? Невидимий додатковий інтервал був би ідеальним.
ahnbizcad

10

Ви можете змінити зміщення скролі-шпигуна на ходу за допомогою цього (якщо припустити, що ви шпигуєте за тілом):

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

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


2
Дякую за це - чудово працює з невеликим налаштуванням для Bootstrap 3.0 $ ('body'). Data () ['bs.scrollspy']. Options.offset = newOffset; // Встановити новий зсув $ ('body'). Data () ['bs.scrollspy']. Process (); // Змусити scrollspy перерахувати зсуви до цілей $ ('body'). Scrollspy ('refresh'); // Оновити прокрутку.
Сем

Я виявив, що цей метод хороший, але якщо я хочу використовувати його для встановлення зрушення з самого початку через наявність різної висоти меню, $ ('body'). Data (). Scrollspy.options.offset (або варіант для версії 3.0) ще не встановлений. Чи є щось асинхронне у scrollspy, чого мені не вистачає?
ness-EE

Станом на Bootstrap 3.1.1 так і має бути $('body').data()['bs.scrollspy'].options.offset. Корисно для запуску scrollspy на завантаженні сторінки, використовуючиwindow.scrollBy(X,Y)
Meredith

8

Якщо ви хочете змістити 10, ви покладете це на голову:

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

Ваш тег тіла буде виглядати приблизно так:

<body data-spy="scroll">

6
Це не компенсує вміст, а компенсує навігацію.
markus

Це допоможе виділити правильний елемент елемента наві, а не місце, куди веде клацання (що є оригінальним питанням плакатів). З урахуванням сказаного, саме це я шукав! Дякую!
valin077

6

З випуску завантажувального номера № 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; 
}

1

Я думаю, що зміщення може щось робити з нижньою позицією розділу.

Я вирішив своє питання - те саме, що і ваше - додавши

  padding-top: 60px;

в декларації до розділу в bootstrap.css

Сподіваюся, що це допомагає!


що таке "декларація для розділу" Де ви ставите цей код?
ahnbizcad

1

Я додав .vspaceелемент висотою 40 пікселів, який тримає якір перед кожним із моїх h1елементів.

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

У CSS:

.vspace { height: 40px;}

Це чудово працює, і простір не забивається.


1

Bootstrap 4 (оновлення 2019 року)

Реалізація: фіксований Nav, Scrollspy та Smooth Scroll

Це рішення від @ wilfred-hughes вище, воно точно виправляє проблему перекриття з Bootstrap Fixed Navbar, використовуючи CSS ':: before', щоб додати не відображений блок перед кожним тегом розділу. Перевага: у вас не виникає зайвих накладок між своїми секціями. Наприклад, розділ 3 може бути розташований вертикально праворуч проти розділу 2, і він все ще прокручуватиметься до правильного положення у верхній частині розділу 3.

Бічна примітка: встановлення зсуву scrollspy в тезі сценарію нічого не сталося ($ ('# navbar'). Scrollspy ({offset: 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/isissue/1768


1
спасибі! тьфу, я боровся з цим протягом години, LOL!
Nexus

0

У мене були проблеми з рішеннями 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;
  }
}

Вам потрібно буде замінити накладку / запас 40 пікселів на висоту набіру та ідентифікатор якоря.

У цій настройці я навіть можу спостерігати ефект встановлення значення для атрибута зміщення даних. Якщо знаходять великі значення для зміщення даних приблизно 100-200, це призведе до більш очікуваної поведінки ("scrollspy-" перемикач "відбудеться, якщо заголовок буде посередині екрану).

Я також виявив, що scrollspy дуже чутливий до помилок, таких як незакриті теги div (що цілком очевидно), тому http://validator.w3.org/check був моїм другом тут.

На мою думку, scrollspy найкраще працює з цілими секціями, що містять ідентифікатор якоря, оскільки звичайні елементи якоря не призводять до очікуваних ефектів при прокрутці назад (перемикач scrollspy - врешті-решт відбувається, як тільки ви потрапите на елемент якоря, наприклад, ваш заголовок, але на той час ви вже прокручували вміст, до якого користувач розраховує належати відповідно до заголовка).


0

Якщо ви натрапили на це запитання (як я) через Google і все ще шукаєте спосіб динамічно змінити зміщення scrollspy. Зараз я додаю посилання на рішення, яке працювало на мене.

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

Вам не потрібно повозитися з виправленнями CSS, а скоріше встановити зрушення, яке вам потрібно в залежності від певних подій.


-1

Ви також можете відкривати bootstap-offset.jsта змінювати

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

там.


1
Зсув scrollspy не компенсує вміст, він зміщує nav.
markus

-1

Просто встановіть:

data-offset="200"

data-offsetза замовчуванням "50", що еквівалентно 10 пікселів, тому просто збільште, data-offsetі ваша проблема вирішена.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.