I have a site with the navbar fixed on top and 3 divs underneath in the main content area.
I'm trying to use scrollspy from the bootstrap framework.
I have it succesfully highlighting the different headings in the menu when you scroll past the divs.
I also have it so when you click the menu, it will scroll to the correct part of the page. However, the offset is incorrect (It's not taking into account the navbar, so I need to offset by about 40 pixels)
I see on the Bootstrap page it mentions an offset option but i'm not sure how to use it.
I'm also not what it means when it says you can use scrollspy with $('#navbar').scrollspy()
, I'm not sure where to include it so I didn't and everything seems to be working (except the offset).
I thought the offset might be the data-offset='10'
on the body tag, but it doesn't do anything for me.
I have a feeling that this is something really obvious and I'm just missing it. Any help?
My code is
... <!-- 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>
The optional data-bs-offset attribute specifies the number of pixels to offset from top when calculating the position of scroll. This is useful when you feel that the links inside the navbar changes the active state too soon or too early when jumping to the scrollable elements. Default is 10 pixels.
Automatically update Bootstrap navigation or list group components based on scroll position to indicate which link is currently active in the viewport.
Add data-spy="scroll" to the element that should be used as the scrollable area (often this is the <body> element). Then add the data-target attribute with a value of the id or the class name of the navigation bar ( . navbar ). This is to make sure that the navbar is connected with the scrollable area.
Bootstrap uses offset to resolve spying only, not scrolling. This means that scrolling to the proper place is up to you.
Try this, it works for me: add an event handler for the navigation clicks.
var offset = 80; $('.navbar li a').click(function(event) { event.preventDefault(); $($(this).attr('href'))[0].scrollIntoView(); scrollBy(0, -offset); });
I found it here: https://github.com/twitter/bootstrap/issues/3316
The trick, as Tim alluded to, is to take advantage of padding. So the problem is, your browser always wants to scroll your anchor to the exact top of the window. if you set your anchor where your text actually begins, it will be occluded by your menu bar. Instead, what you do is set your anchor to the container <section>
or <div>
tag's id, which the nav/navbar will automatically use. Then you have to set your padding-top
for the container to the amount offset you want, and the margin-top
for the container to the opposite of the padding-top
. Now your container's block and the anchor begin at the exact top of the page, but the content inside doesn't begin until below the menu bar.
If you're using regular anchors, you can accomplish the same thing by using negative margin-top in your container as above, but no padding. Then you put a regular <a target="...">
anchor as the first child of the container. Then you style the second child element with an opposite but equal margin-top
, but using the selector .container:first-child +
.
This all presumes that your <body>
tag already has its margin set to begin below your header, which is the norm (otherwise the page would render with occluded text right off the bat).
Here's an example of this in action. Anything on your page with an id can be linked to by tacking #the-elements-id onto the end of your URL. If you make all of your h tags ad dt tags with ids link-able (Like github does) with some sort of script that injects a little link to the left of them; adding the following to your CSS will take care of the nav-bar offset for you:
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; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With