Làm cách nào để đặt bù đắp cho ScrollSpy trong Bootstrap?


98

Tôi có một trang web với thanh điều hướng được cố định ở trên và 3 dấu chia bên dưới trong vùng nội dung chính.

Tôi đang cố gắng sử dụng scrollspy từ khung khởi động.

Tôi đã làm nổi bật thành công các tiêu đề khác nhau trong menu khi bạn cuộn qua các div.

Tôi cũng có nó để khi bạn nhấp vào menu, nó sẽ cuộn đến phần chính xác của trang. Tuy nhiên, độ lệch không chính xác (Nó không tính đến thanh điều hướng, vì vậy tôi cần bù khoảng 40 pixel)

Tôi thấy trên trang Bootstrap có đề cập đến một tùy chọn bù trừ nhưng tôi không chắc cách sử dụng nó.

Tôi cũng không hiểu nó có nghĩa là gì khi nó nói rằng bạn có thể sử dụng scrollspy với $('#navbar').scrollspy(), tôi không chắc nên đưa nó vào đâu nên tôi đã không làm như vậy và mọi thứ dường như đang hoạt động (ngoại trừ phần bù đắp).

Tôi nghĩ phần bù đắp có thể là data-offset='10'trên body tag, nhưng nó không làm được gì cho tôi.

Tôi có cảm giác rằng đây là một điều gì đó thực sự hiển nhiên và tôi chỉ thiếu nó. Bất kỳ giúp đỡ?

Mã của tôi là

...
<!-- 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>

Tại sao bạn lại đưa ra một vị trí: liên quan đến div của bạn? Có lẽ đó là những gì gây ra điều này. Bạn có thể tạo jsfiddle bằng mã của mình để chúng tôi có thể xem trong quá trình thực hiện không?
periklis

Câu trả lời:


113

Bootstrap chỉ sử dụng offset để giải quyết gián điệp, không phải cuộn. Điều này có nghĩa là việc cuộn đến nơi thích hợp là tùy thuộc vào bạn.

Hãy thử điều này, nó phù hợp với tôi: thêm trình xử lý sự kiện cho các nhấp chuột điều hướng.

var offset = 80;

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

Tôi tìm thấy nó ở đây: https://github.com/twitter/bootstrap/issues/3316


3
Cảm ơn vì câu trả lời. Tôi đã mất một thời gian để nhận ra rằng bù đắp không ảnh hưởng đến việc cuộn. Điều này có nghĩa là bất kỳ ai sử dụng fixed-top đều cần phải điều chỉnh thủ công theo cách này.
Brian Smith

8
Để cập nhật phần băm của URL một cách thích hợp, hãy thêm window.location.hash = $(this).attr('href')vào chức năng này.
Stephen M. Harris

2
Cảm ơn! FWIW, việc đưa data-offset vào phần thân cũng rất quan trọng, vì người hỏi nói rằng nó không làm gì cả, nhưng nó cần thiết để theo dõi thích hợp. Nó có thể hữu ích để có một câu trả lời toàn diện.
mrooney

4
Năng động, giành chiến thắng: var navOffset = $('#navbar').height();scrollBy(0, -navOffset);
ahnbizcad

78

Bí quyết, như Tim ám chỉ, là tận dụng lợi thế của việc đệm. Vì vậy, vấn đề là, trình duyệt của bạn luôn muốn cuộn mỏ neo của bạn lên chính xác đầu cửa sổ. nếu bạn đặt neo nơi văn bản của bạn thực sự bắt đầu, nó sẽ được hiển thị trên thanh menu của bạn. Thay vào đó, những gì bạn làm là đặt liên kết của bạn thành id của vùng chứa <section>hoặc <div>thẻ, mà thanh điều hướng / điều hướng sẽ tự động sử dụng. Sau đó, bạn phải đặt của bạn padding-topcho vùng chứa đến mức bù đắp bạn muốn và margin-topcho vùng chứa đối diện vớipadding-top . Bây giờ khối của vùng chứa của bạn và mỏ neo bắt đầu ở đầu chính xác của trang, nhưng nội dung bên trong không bắt đầu cho đến bên dưới thanh menu.

Nếu bạn đang sử dụng neo thông thường, bạn có thể thực hiện điều tương tự bằng cách sử dụng margin-top phủ định trong vùng chứa của bạn như trên, nhưng không có phần đệm. Sau đó, bạn đặt một <a target="...">mỏ neo thông thường làm con đầu tiên của vùng chứa. Sau đó, bạn tạo kiểu cho phần tử con thứ hai với một phần tử đối lập nhưng bằng nhau margin-top, nhưng bằng cách sử dụng bộ chọn .container:first-child +.

Tất cả điều này giả định rằng <body>thẻ của bạn đã được đặt lề để bắt đầu bên dưới tiêu đề của bạn, đó là tiêu chuẩn (nếu không trang sẽ hiển thị với văn bản bị tắc ngay lập tức).

Đây là một ví dụ về điều này đang hoạt động. Bất kỳ thứ gì trên trang của bạn có id đều có thể được liên kết bằng cách gắn # the-Elements-id vào cuối URL của bạn. Nếu bạn tạo tất cả các thẻ h của mình là thẻ dt quảng cáo với id có thể liên kết ( Giống như github ) với một số loại tập lệnh chèn một liên kết nhỏ vào bên trái của chúng ; thêm phần sau vào CSS của bạn sẽ xử lý bù đắp thanh điều hướng cho bạn:

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
Thích kết hợp padding-top, negative margin-bottom (trên cùng một phần tử). Sau đó dễ dàng hơn với các js.
Eystein

Có vẻ như câu trả lời tốt nhất, nhưng tôi hơi bị lạc. Bất kỳ cơ hội của một ví dụ.
eddyparkinson

@eddyparkinson, đoán bạn đã tìm ra ngay bây giờ: Ví dụ: khi bạn có id của mình trên các hàng của bootstrap: .row [id] {padding-top: 60px; margin-top: -40px; } Đặt cái này vào tệp less của bạn: .row [id] {padding-top: 60px; margin-top: -40px; }
Klaaz

Không phải tham số bù đắp mặc định của bootstrap phải dành cho việc này? Có vẻ như một điều hiển nhiên phải bao gồm, và không cần phải dùng đến các giải pháp thay thế như thế này.
ahnbizcad

Điều này có hiệu quả thêm không gian trên div bạn đang nhắm mục tiêu không? Nếu bạn không muốn điều đó thì sao? Một khoảng cách thêm vô hình sẽ là lý tưởng.
ahnbizcad

10

Bạn có thể thay đổi độ lệch của cuộn giấy khi di chuyển bằng cách này (giả sử bạn đang theo dõi cơ thể):

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

Điều này cũng hoạt động nếu bạn cần thay đổi giá trị bù động. (Tôi thích scrollspy chuyển sang khi phần tiếp theo ở khoảng nửa sau cửa sổ, vì vậy tôi cần thay đổi độ lệch trong khi thay đổi kích thước cửa sổ.)


2
Cảm ơn vì điều này - hoạt động tốt với một chút điều chỉnh cho Bootstrap 3.0 $ ('body'). Data () ['bs.scrollspy']. Options.offset = newOffset; // Đặt giá trị bù mới $ ('body'). Data () ['bs.scrollspy']. Process (); // Buộc scrollspy tính toán lại các hiệu số cho mục tiêu của bạn $ ('body'). Scrollspy ('refresh'); // Làm mới cuộn giấy.
Sam

Tôi thấy rằng phương pháp này là tốt, nhưng nếu tôi muốn sử dụng nó để đặt độ lệch ngay từ đầu do có độ cao menu khác nhau thì $ ('body'). Data (). Scrollspy.options.offset (hoặc biến thể cho phiên bản 3.0) chưa được đặt. Có điều gì đó không đồng bộ về scrollspy mà tôi đang thiếu?
ness-EE

Kể từ Bootstrap 3.1.1, điều này sẽ xảy ra $('body').data()['bs.scrollspy'].options.offset. Hữu ích để kích hoạt scrollspy trên tải trang bằng cách sử dụngwindow.scrollBy(X,Y)
Meredith

8

Nếu bạn muốn chênh lệch 10, bạn sẽ ghi nhớ điều này trong đầu:

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

Thẻ body của bạn sẽ trông như thế này:

<body data-spy="scroll">

6
Điều đó không bù đắp nội dung, nó bù đắp điều hướng.
markus

Điều này sẽ hoạt động để làm nổi bật phần tử điều hướng chính xác chứ không phải vị trí nơi nhấp chuột dẫn đến (đây là câu hỏi áp phích ban đầu). Với điều đó đã nói, đây là những gì tôi đang tìm kiếm! Cảm ơn!
valin077

6

Từ sự cố bootstrap # 3316 :

[Điều này] chỉ nhằm mục đích sửa đổi các tính toán cuộn - chúng tôi không thay đổi nhấp chuột neo thực tế

Vì vậy, việc đặt offset chỉ ảnh hưởng đến nơi scrollspy nghĩ rằng trang được cuộn đến . Nó không ảnh hưởng đến việc cuộn khi bạn nhấp vào thẻ liên kết.

Sử dụng thanh điều hướng cố định có nghĩa là trình duyệt đang cuộn đến sai vị trí. Bạn có thể sửa lỗi này bằng 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);
});

Tuy nhiên, để đảm bảo rằng scrollspy làm nổi bật phần tử hiện tại chính xác, bạn vẫn cần đặt bù đắp:

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

Đây là bản demo hoàn chỉnh về JSFiddle .


Ngoài ra, bạn có thể đệm vào các thẻ liên kết của mình, theo gợi ý của các thủ thuật 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

Tôi nghĩ rằng phần bù đắp đó có thể làm gì đó với vị trí dưới cùng của phần.

Tôi đã khắc phục sự cố của mình - cũng giống như sự cố của bạn - bằng cách thêm

  padding-top: 60px;

trong phần khai báo cho phần bootstrap.css

Hy vọng rằng sẽ giúp!


"Khai báo cho phần" Bạn đặt mã này ở đâu?
ahnbizcad

1

Tôi đã thêm .vspacephần tử chiều cao 40px giữ neo trước mỗi h1phần tử của mình .

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

Trong CSS:

.vspace { height: 40px;}

Nó hoạt động tuyệt vời và không gian không chật chội.


1

Bootstrap 4 (bản cập nhật 2019)

Triển khai: Điều hướng cố định, cuộn cuộn và cuộn mượt mà

Đây là giải pháp từ @ wilfred-ômhes ở trên, chính xác là khắc phục vấn đề chồng chéo với Bootstrap Fixed Navbar bằng cách sử dụng CSS ':: before' để thêm một khối không hiển thị trước mỗi thẻ phần. Ưu điểm: bạn không bị chèn giữa các phần không cần thiết. Ví dụ: phần 3 có thể được đặt theo chiều dọc đối diện với phần 2 và nó vẫn sẽ cuộn đến vị trí chính xác chính xác ở đầu phần 3.

Lưu ý bên cạnh: việc đặt độ lệch scrollspy trong thẻ script đã không gây ra điều gì xảy ra ($ ('# navbar'). Scrollspy ({offset: 105});) và cố gắng điều chỉnh độ lệch trong khối hoạt ảnh vẫn dẫn đến hậu quả bị lệch hoạt hình.

index.html

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

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

Tín dụng: @ wilfred-ômhes ở trên và nguồn gốc từ người dùng @mnot tại https://github.com/twbs/bootstrap/issues/1768


cảm ơn bạn! ugh, tôi đã vật lộn với điều này trong một giờ, LOL!
Nexus

0

Tôi gặp sự cố với các giải pháp của acjohnson55 và Kurt UXD. Cả hai đều hoạt động để nhấp vào một liên kết đến hàm băm, nhưng phần bù cuộn giấy vẫn không chính xác.

Tôi đã đưa ra giải pháp sau:

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

Và CSS tương ứng:

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

Bạn sẽ cần thay thế padding / margin 40px bằng chiều cao của thanh điều hướng và id của anchor.

Trong thiết lập này, tôi thậm chí có thể quan sát hiệu ứng của việc đặt giá trị cho thuộc tính bù đắp dữ liệu. Nếu tìm thấy các giá trị lớn cho độ lệch dữ liệu trong khoảng 100-200 dẫn đến một hành vi được mong đợi hơn (chuyển đổi cụm cuộn - "" sẽ xảy ra nếu tiêu đề nằm ở giữa màn hình).

Tôi cũng thấy rằng scrollspy rất nhạy cảm với các lỗi như thẻ div không được đóng (điều này khá rõ ràng), vì vậy http://validator.w3.org/check là bạn của tôi ở đây.

Theo ý kiến ​​của tôi, scrollspy hoạt động tốt nhất với toàn bộ các phần mang ID neo, vì các phần tử neo thông thường không dẫn đến hiệu ứng mong đợi khi cuộn ngược lại (chuyển đổi scrollspy- "cuối cùng xảy ra ngay sau khi bạn nhấn vào phần tử neo, ví dụ như tiêu đề của bạn, nhưng tại thời điểm đó, bạn đã cuộn qua nội dung mà người dùng mong đợi thuộc về tiêu đề theo).


0

Nếu bạn tình cờ gặp câu hỏi này (giống như tôi đã làm) qua Google và vẫn đang tìm cách thay đổi động độ lệch của scrollspy. Bây giờ tôi đang đính kèm một liên kết đến một giải pháp phù hợp với tôi.

Hãy xem bài đăng này tôi đã thực hiện trong một chủ đề khác . Điều này chứa một đoạn mã về cách bạn có thể thay đổi giá trị offset theo chương trình và phản ứng động với các thay đổi (ví dụ: nếu thanh điều hướng thay đổi về kích thước).

Bạn không cần phải mày mò các bản sửa lỗi CSS mà thay vào đó là đặt mức bù đắp mà bạn hiện cần tùy thuộc vào các sự kiện nhất định.


-1

Bạn cũng có thể mở bootstap-offset.jsvà sửa đổi

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

ở đó.


1
Khoảng cách cuộn không bù đắp nội dung, nó bù đắp điều hướng.
markus

-1

Chỉ cần đặt:

data-offset="200"

data-offsettheo mặc định là "50" và tương đương với 10px, vì vậy chỉ cần tăng data-offsetvà vấn đề của bạn đã được giải quyết.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.