Bootstrap에서 ScrollSpy의 오프셋을 어떻게 설정합니까?


98

메인 콘텐츠 영역에 navbar가 상단에 고정되고 아래에 3div가있는 사이트가 있습니다.

부트 스트랩 프레임 워크에서 scrollspy를 사용하려고합니다.

div를지나 스크롤 할 때 메뉴에서 다른 제목을 성공적으로 강조 표시했습니다.

또한 메뉴를 클릭하면 페이지의 올바른 부분으로 스크롤됩니다. 그러나 오프셋이 잘못되었습니다 (탐색 막대를 고려하지 않았으므로 약 40 픽셀만큼 오프셋해야 함)

난에 표시되는 부트 스트랩 페이지 는 오프셋 옵션을 언급하지만 난 확실히 그것을 사용하는 방법을 모르겠어요.

나는 또한 scrollspy와 함께 사용할 수 있다고 말했을 때 의미하는 바가 $('#navbar').scrollspy()아니며 포함해야 할 위치가 확실하지 않아 모든 것이 작동하는 것 같습니다 (오프셋 제외).

오프셋이 data-offset='10'본문 태그에 있을 수 있다고 생각 했지만 아무런 효과가 없습니다.

나는 이것이 정말로 명백한 것 같은 느낌이 들었고 나는 그것을 놓치고 있습니다. 도움이 필요하세요?

내 코드는

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

div에 상대적인 포지션을 제공하는 이유는 무엇입니까? 아마도 이것이 원인 일 것입니다. 코드를 사용하여 jsfiddle을 생성하여 실제 작업을 볼 수 있습니까?
periklis

답변:


113

부트 스트랩은 오프셋을 사용하여 스크롤링이 아닌 감시 만 해결합니다. 이것은 적절한 위치로 스크롤하는 것은 당신에게 달려 있음을 의미합니다.

이것을 시도해보십시오. 내비게이션 클릭에 대한 이벤트 핸들러를 추가하십시오.

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


3
답변 해주셔서 감사합니다. 오프셋이 스크롤링에 영향을주지 않는다는 것을 깨닫는 데 꽤 오랜 시간이 걸렸습니다. 즉, 고정 상단을 사용하는 사람은 누구나 이러한 방식으로 수동으로 조정해야합니다.
Brian Smith

8
URL의 해시 섹션을 적절하게 업데이트하려면 window.location.hash = $(this).attr('href')이 함수에 추가하십시오 .
Stephen M. Harris

2
감사! FWIW, 데이터 오프셋을 본문에 넣는 것도 중요합니다. 질문자는 아무 일도하지 않는다고 말하지만 적절한 스파이를 위해서는 필요합니다. 포괄적 인 답변을하는 것이 도움이 될 수 있습니다.
mrooney 2013 년

4
동적 승리 : var navOffset = $('#navbar').height();그리고scrollBy(0, -navOffset);
ahnbizcad 2015 년

78

Tim이 언급했듯이 트릭은 패딩을 활용하는 것입니다. 따라서 문제는 브라우저가 항상 앵커를 창의 정확한 상단으로 스크롤하기를 원한다는 것입니다. 텍스트가 실제로 시작하는 위치에 앵커를 설정하면 메뉴 막대에 의해 가려집니다. 대신 nav / navbar가 자동으로 사용할 컨테이너 <section>또는 <div>태그의 ID로 앵커를 설정합니다 . 그럼 당신은 당신을 설정해야 할 padding-top금액에 컨테이너 원하는 오프셋과 margin-top받는 사람 컨테이너에 대한 반대padding-top. 이제 컨테이너의 블록과 앵커는 페이지의 정확한 상단에서 시작되지만 내부의 콘텐츠는 메뉴 막대 아래까지 시작되지 않습니다.

일반 앵커를 사용하는 경우 위와 같이 컨테이너에서 네거티브 margin-top을 사용하여 동일한 작업을 수행 할 수 있지만 패딩은 없습니다. 그런 다음 <a target="...">컨테이너의 첫 번째 자식으로 일반 앵커 를 넣습니다 . 그런 다음 두 번째 자식 요소의 스타일은 반대이지만 같지만 margin-top선택기를 사용합니다 .container:first-child +.

이 모든 것은 <body>태그에 이미 헤더 아래에서 시작하도록 여백이 설정되어 있다고 가정합니다 . 이는 표준입니다 (그렇지 않으면 페이지가 방망이에서 막힌 텍스트로 렌더링됩니다).

여기에 실제 동작의 예가 있습니다. URL 끝에 # the-elements-id를 붙이면 ID가있는 페이지의 모든 항목에 연결할 수 있습니다. 모든 h 태그 ad dt 태그를 ids로 링크 가능하게 만들면 ( 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
padding-top, negative margin-bottom (동일한 요소) 콤보를 좋아합니다. js로 더 쉽게 엉망이됩니다.
Eystein

정답 인 것 같지만 조금 길을 잃었습니다. 예의 기회.
eddyparkinson 2014

@eddyparkinson, 당신이 지금 알아 낸 것 같군요 : 예, 부트 스트랩의 행에 ID가있을 때 : .row [id] {padding-top : 60px; 여백-상단 : -40px; } 이것을 적은 파일에 넣으십시오. .row [id] {padding-top : 60px; 여백-상단 : -40px; }
Klaaz

부트 스트랩의 기본 오프셋 매개 변수가이를위한 것이 아닙니까? 포함하는 것이 분명한 것처럼 보이며 이와 같은 해결 방법에 의존 할 필요가 없습니다.
ahnbizcad

이렇게하면 목표로하는 div에 추가 공간이 효과적으로 추가됩니까? 원하지 않는다면? 보이지 않는 여분의 간격이 이상적입니다.
ahnbizcad

10

다음과 같이 즉석에서 scrollspy의 오프셋을 변경할 수 있습니다 (몸을 감시한다고 가정).

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'); // scrollspy를 새로 고칩니다.
Sam

이 방법이 좋지만 메뉴 높이가 다르기 때문에 처음부터 오프셋을 설정하는 데 사용하려면 $ ( '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)
메러디스

8

10의 오프셋을 원하면 이것을 머리에 넣으십시오.

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

본문 태그는 다음과 같습니다.

<body data-spy="scroll">

6
콘텐츠를 오프셋하지 않고 탐색을 오프셋합니다.
markus 2013

이것은 클릭이 이끄는 위치 (원래 포스터 질문)가 아닌 올바른 탐색 요소를 강조하는 데 작동합니다. 그렇게 말하면서 이것이 내가 찾고 있던 것입니다! 감사!
valin077 2015-06-18

6

에서 부트 스트랩 문제 # 3316 :

[This]는 스크롤 계산을 수정하기위한 것입니다. 실제 앵커 클릭은 이동하지 않습니다.

따라서 오프셋 설정 은 scrollspy가 페이지가 스크롤되었다고 생각하는 위치 에만 영향을 미칩니다 . 그것은 스크롤에 영향을주지 않습니다 당신은 앵커 태그를 클릭 할 때.

고정 된 navbar를 사용하면 브라우저가 잘못된 위치로 스크롤됩니다. 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

.vspaceh1요소 앞에 앵커를 들고있는 40px 높이의 요소를 추가했습니다 .

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

CSS에서 :

.vspace { height: 40px;}

훌륭하게 작동하고 공간이 꽉 막히지 않습니다.


1

부트 스트랩 4 (2019 업데이트)

구현 : Fixed Nav, Scrollspy 및 Smooth Scrolling

이것은 위의 @ wilfred-hughes의 해결책으로, CSS ':: before'를 사용하여 각 섹션 태그 앞에 표시되지 않는 블록을 추가하여 Bootstrap Fixed Navbar의 겹침 문제를 정확하게 수정합니다. 장점 : 섹션 사이에 불필요한 패딩이 생기지 않습니다. 예를 들어 섹션 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 및 https://github.com/twbs/bootstrap/issues/1768의 @mnot 사용자의 원본 소스


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

40px 패딩 / 여백을 navbar의 높이와 앵커의 ID로 바꿔야합니다.

이 설정에서는 data-offset 속성 값을 설정하는 효과도 관찰 할 수 있습니다. 100-200 정도의 데이터 오프셋에 대해 큰 값을 찾으면 더 예상되는 동작으로 이어집니다 (표제가 화면 중앙에 있으면 scrollspy- "switch"가 발생합니다).

또한 scrollspy가 닫히지 않은 div 태그와 같은 오류에 매우 민감하다는 것을 발견했습니다 (아주 분명함). 그래서 http://validator.w3.org/check 는 여기 내 친구였습니다.

내 생각에 scrollspy는 앵커 ID를 포함하는 전체 섹션에서 가장 잘 작동합니다. 일반 앵커 요소는 뒤로 스크롤 할 때 예상되는 효과로 이어지지 않기 때문입니다 (스크롤 스파이- "스위치"는 결국 앵커 요소 (예 : 제목)에 도달하자마자 발생하지만 이때 사용자가 해당 제목에 속할 것으로 예상하는 콘텐츠를 이미 스크롤했습니다.


0

Google을 통해이 질문을 우연히 발견하고 여전히 scrollspy의 오프셋을 동적으로 변경하는 방법을 찾고 있습니다. 이제 나를 위해 일한 솔루션에 대한 링크를 첨부하고 있습니다.

다른 스레드에서 만든게시물을 살펴보십시오 . 여기에는 오프셋 값을 프로그래밍 방식으로 변경하고 변경 사항에 동적으로 반응하는 방법에 대한 스 니펫이 포함되어 있습니다 (예 : navbar 크기가 변경되는 경우).

CSS 수정을 다룰 필요가 없지만 특정 이벤트에 따라 현재 필요한 오프셋을 설정합니다.


-1

또한 열고 bootstap-offset.js수정할 수 있습니다.

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

그곳에.


1
scrollspy 오프셋은 콘텐츠를 오프셋하지 않고 탐색을 오프셋합니다.
markus 2013

-1

그냥 설정 :

data-offset="200"

data-offset기본값은 "50"이고 10px에 해당하므로 늘리면 data-offset문제가 해결됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.