페이지를로드 할 때 앵커 "점프"를 비활성화하는 방법은 무엇입니까?


110

나는 이것이 가능하지 않을 수도 있다고 생각하며 최선을 다해 설명 할 것입니다. 다음으로 제어되는 탭 (jquery 기반)이 포함 된 페이지가 있습니다.

이전 질문에서 다른 사용자가 제공 한대로이 코드를 사용하고 있습니다.

<script type="text/javascript">
    $(function() {

     $('html, body').animate({scrollTop:0}); // this is my "fix"

        var tabContent = $(".tab_content");
        var tabs = $("#menu li");
        var hash = window.location.hash;
     tabContent.not(hash).hide();
        if(hash=="") {
      $('#tab1').fadeIn();
     }
        tabs.find('[href=' + hash + ']').parent().addClass('active');

        tabs.click(function() {
            $(this).addClass('active').siblings().removeClass('active');
            tabContent.hide();
            var activeTab = $(this).find("a").attr("href");

            $(activeTab).fadeIn();
           return false;
        });

    });
</script>

이 코드는 "탭"페이지를 직접 방문 할 때 잘 작동합니다.

그러나 다른 페이지의 개별 탭에 연결해야합니다. 이렇게하려면 코드 window.location.hash에 적절한 탭이 표시됩니다.

페이지는 "return false"때문에 앵커로 "점프"하지 않습니다.

그러나이 이벤트는 클릭 이벤트에서만 트리거됩니다. 따라서 다른 페이지에서 "탭"을 방문하면 "점프"효과가 트리거됩니다. 이 문제를 해결하기 위해 자동으로 페이지 상단으로 스크롤하지만, 이런 일이 발생하지 않았 으면합니다.

페이지가로드 될 때 "return false"를 시뮬레이션하여 앵커 "점프"가 발생하지 않도록하는 방법이 있습니까?

이것이 충분히 명확하기를 바랍니다.

감사

답변:


143

수정 사항이 작동하지 않습니까? 질문을 올바르게 이해했는지 잘 모르겠습니다. 데모 페이지가 있습니까? 시도해 볼 수 있습니다.

if (location.hash) {
  setTimeout(function() {

    window.scrollTo(0, 0);
  }, 1);
}

편집 : Windows의 Firefox, IE 및 Chrome에서 테스트되고 작동합니다.
편집 2 : 블록 setTimeout()내부 로 이동 if, @vsync 소품.


2
영웅! 예, 내 "수정"은 작동했지만 페이지는 "스크롤"(내 코드에서 말한대로)하고 오히려 스크롤하지 않았습니다. 코드가 완벽하게 작동합니다. ScrollTo를 보지 않았습니다. 기능이 필요한가요? window.scrollTo (0, 0); 그냥 잘 작동하는 것 같습니다.
로스

3
나는없는 빈 페이지에서 Firefox에서 시도했지만 setTimeout항상 작동하지는 않았습니다. $(function() {어쨌든 jQuery에 있다면 아마 필요하지 않을 것 입니다. 실제로는 필요하지 않지만 location.hash브라우저가 아무것도 할 필요가 없도록 남겨 두는 것이 좋습니다. 또한 scrollTo가 무엇인지 상기시켜줍니다!
dave1010

2
오늘도 이와 같은 문제가있었습니다. 실제로 내 탐색 링크에 해시 (탭 이름 / href 값과 동일)를 추가해야했습니다. 내 탭에 1 자 접미사를 추가 한 다음 값을 window.location.hash와 비교할 때 1 자 (str.slice (0, -1))로 하위 문자열을 지정했습니다. 이렇게하면 해시가 다르고 점프가 발생하지 않습니다. .
개발자 10

1
if없습니다 내부, 외부해야한다. 또한 간격의 최소값은 약 10이므로 브라우저에 따라 0 또는 1은 10.과 동일합니다.
vsync 2014

2
이것은 브라우저가 해시 태그로 점프하는 것을 방지하지 않습니다. '점프'를 방지하기 위해 빈 해시 태그를 넣어야합니다. 여기 내 대답을 참조하십시오. stackoverflow.com/a/29823913/826194
Larzan

43

여기 내 대답을 참조하십시오 : Stackoverflow 답변

트릭은 해시 태그를 최대한 빨리 제거하고 자신의 용도로 값을 저장하는 것입니다.

코드의 해당 부분을 $ () 또는 $ (window) .load () 함수에 넣지 않는 것이 중요합니다. 너무 늦고 브라우저가 이미 태그로 이동했기 때문입니다.

// store the hash (DON'T put this code inside the $() function, it has to be executed 
// right away before the browser can start scrolling!
var target = window.location.hash,
    target = target.replace('#', '');

// delete hash so the page won't scroll to it
window.location.hash = "";

// now whenever you are ready do whatever you want
// (in this case I use jQuery to scroll to the tag after the page has loaded)
$(window).on('load', function() {
    if (target) {
        $('html, body').animate({
            scrollTop: $("#" + target).offset().top
        }, 700, 'swing', function () {});
    }
});

1
나는 정말 긴 목록이있는 div에서 max-height overflow-y를 사용하는 FF 버그에 부딪 쳤습니다. FF는 숨겨진 노드가 dom에있는 곳으로 스크롤합니다. 이것은 주석이 아닌 실제 코드의 상위 세 줄만 사용했으며 FireFox에 대한 내 문제를 수정했습니다.
JQII

12

어떤 탭에 있는지 추적하는 다른 방법이 있습니다. 아마도 쿠키 또는 숨겨진 필드의 값 등을 설정합니다.

페이지가로드되는 동안 점프하는 것을 원하지 않으면 해시 대신 다른 옵션 중 하나를 사용하는 것이 좋습니다. 해시를 선호하는 주된 이유는 정확히 원하는 것을 허용하기 때문입니다. '차단하고 싶어요.

또 다른 요점-해시 링크가 문서의 태그 이름과 일치하지 않으면 페이지가 점프하지 않으므로 해시를 계속 사용하려면 태그 이름이 다르게 지정되도록 콘텐츠를 조작 할 수 있습니다. 일관된 접두사를 사용하면 Javascript를 사용하여 그 사이를 이동할 수 있습니다.

도움이 되었기를 바랍니다.


2
좋은 점. JS / CSS를 끈 상태에서 페이지를 사용 가능 / 액세스 가능하도록 유지하는 것을 잊지 마십시오.
dave1010

12

dave1010의 솔루션을 사용했지만 $ (). ready 함수 안에 넣었을 때 약간 불안했습니다. 그래서 나는 이것을했다 : ($ (). ready 내부가 아님)

    if (location.hash) {               // do the test straight away
        window.scrollTo(0, 0);         // execute it straight away
        setTimeout(function() {
            window.scrollTo(0, 0);     // run it a bit later also for browser compatibility
        }, 1);
    }

10
  1. 주소에 http://site.com/#abc 해시가 있고 id = "abc"인 요소가 표시 <element id="abc" />되면 브라우저가 이동합니다 . 따라서 기본적으로 요소를 숨겨야합니다 .. 페이지에 id = hash로 표시된 요소가 없으면 브라우저가 점프하지 않습니다.<element id="anchor" style="display: none" />

  2. URL에서 해시를 확인한 다음 prrpopriate 요소 (기본적으로 숨겨져 있음)를 찾아 표시하는 스크립트를 만듭니다.

  3. onclick 이벤트를 링크에 바인딩하여 기본 "해시 유사 링크"동작을 비활성화하고 onclick 이벤트 return false;의 결과로 지정 합니다.

탭을 구현할 때 다음과 같이 작성했습니다.

    <script>
    $(function () {         
        if (location.hash != "") {
            selectPersonalTab(location.hash);
        }
        else {
            selectPersonalTab("#cards");
        }
    });

    function selectPersonalTab(hash) {
        $("#personal li").removeClass("active");
        $("a[href$=" + hash + "]").closest("li").addClass("active");
        $("#personaldata > div").hide();
        location.hash = hash;
        $(hash).show();
    }

    $("#personal li a").click(function (e) {
        var t = e.target;
        if (t.href.indexOf("#") != -1) {
            var hash = t.href.substr(t.href.indexOf("#"));
            selectPersonalTab(hash);
            return false;
        }
    });
</script>

6

어떤 답변도 저에게 충분하지 않습니다. 페이지가 닻을 내리고 일부 솔루션의 경우 맨 위로 이동하는 것을 보며 일부 답변은 전혀 작동하지 않으며 몇 년 동안 변경 될 수 있습니다. 내 기능이 누군가에게 도움이되기를 바랍니다.

/**
 * Prevent automatic scrolling of page to anchor by browser after loading of page.
 * Do not call this function in $(...) or $(window).on('load', ...),
 * it should be called earlier, as soon as possible.
 */
function preventAnchorScroll() {
    var scrollToTop = function () {
        $(window).scrollTop(0);
    };
    if (window.location.hash) {
        // handler is executed at most once
        $(window).one('scroll', scrollToTop);
    }

    // make sure to release scroll 1 second after document readiness
    // to avoid negative UX
    $(function () {
        setTimeout(
            function () {
                $(window).off('scroll', scrollToTop);
            },
            1000
        );
    });
}

지금까지 찾은 최고의 솔루션입니다. 그리고 실제로 많이 보았습니다.
MarkSkayff

감사합니다! 또한 몇 시간의 시도 후에 저에게 효과적이지만이 솔루션의 가장 좋은 부분은 해시를 제거 할 필요가 없다는 것입니다.
Chris Vecchio

스크롤러가 페이지로드시 이미 페이지 상단에있는 경우 작동하지 않습니다. 그러면 평소처럼 아래로 스크롤되고 페이지가 완료되면 맨 위로 이동합니다. 누구든지 이것이 사실인지 알고 있습니까?
robgha01

@ robgha01 함수가 가능한 한 빨리 실행되고 이벤트를 기다리지 않는지 확인하십시오. 이것은 잘못된 것입니다. $(document).ready(function () { preventAnchorScroll(); });, JavaScript의 맨 처음에 함수를 호출하십시오. 나는 지금 그것을 테스트했고 Chrome, Firefox 및 Opera에서 나를 위해 작동합니다.
kdmitry

4

더티 CSS는 앵커를 사용할 때마다 위로 스크롤되도록 수정합니다 (스크롤 점프에 앵커를 계속 사용하려는 경우에는 유용하지 않으며 딥 링크에 매우 유용함).

.elementsWithAnchorIds::before {
   content: "";
   display: block;
   height: 9999px;
   margin-top: -9999px; //higher thin page height
}

영리한 soooooo!
duhaime

3

받아 들여지는 대답은 잘 작동하지만 때로는 특히 큰 이미지가 포함 된 페이지에서 스크롤 막대가

 window.scrollTo(0, 0);

사용자에게 상당히 산만해질 수 있습니다.

결국 제가 정한 해결책은 실제로 매우 간단합니다. 대상에 사용 된 ID와 다른 ID를 사용하는 것입니다. location.hash

예 :

다음은 다른 페이지의 링크입니다.

<a href="/page/with/tabs#tab2">Some info found in tab2 on tabs page</a>

물론 tab2탭 페이지에 ID가있는 요소가있는 경우 로드시 창이 해당 요소로 이동합니다 .

따라서이를 방지하기 위해 ID에 무언가를 추가 할 수 있습니다.

<div id="tab2-noScroll">tab2 content</div>

그리고 당신은 추가 할 수 있습니다 "-noScroll"location.hash자바 스크립트에서 :

<script type="text/javascript">
    $(function() {

        var tabContent = $(".tab_content");
        var tabs = $("#menu li");
        var hash = window.location.hash;


     tabContent.not(hash + '-noScroll').hide();                           
        if(hash=="") {       //^ here
      $('#tab1-noScroll').fadeIn();
     }
        tabs.find('[href=' + hash + ']').parent().addClass('active');

        tabs.click(function() {
            $(this).addClass('active').siblings().removeClass('active');
            tabContent.hide();
            var activeTab = $(this).find("a").attr("href") + '-noScroll'; 
                                                               //^ and here

            $(activeTab).fadeIn();
           return false;
        });

    });
</script>

2

제 경우에는 CSS 팝업에 앵커 링크를 사용하기 때문에 다음과 같이 사용했습니다.

클릭시 pageYOffset을 먼저 저장 한 다음 ScrollTop을 다음과 같이 설정하십시오.

$(document).on('click','yourtarget',function(){
        var st=window.pageYOffset;
        $('html, body').animate({
                'scrollTop' : st
            });
});

다른 솔루션을 시도한 후 이것은 나를 위해 일한 것입니다. 제 경우에는 내가 함께 일하고 있던 웹 사이트에서 URL의 #을 사용하여 체크 아웃의 특정 섹션을로드했습니다. URL에서 해시에 대한 체크 아웃 기능을 수정하는 대신 방금 이것을 사용했습니다. 감사합니다
chris c

1

기능을 다시 실행하지 않고 UI 탭에 대한 방법을 찾은 것 같습니다. 지금까지 나는 어떤 문제도 발견하지 못했습니다.

    $( ".tabs" ).tabs();
    $( ".tabs" ).not(".noHash").bind("tabsshow", function(event, ui) { 
        window.location.hash = "tab_"+ui.tab.hash.replace(/#/,"");
        return false;
    });

    var selectedTabHash = window.location.hash.replace(/tab_/,"");
    var index = $( ".tabs li a" ).index($(".tabs li a[href='"+selectedTabHash+"']"));
    $( ".tabs" ).not(".noHash").tabs('select', index);

준비된 이벤트 내에서 모두. 해시 앞에 "tab_"이 추가되지만 클릭 할 때와 해시로 페이지가로드 될 때 모두 작동합니다.


1

이것은 부트 스트랩 v3에서 작동합니다.

$(document).ready(function() {
  if ($('.nav-tabs').length) {
    var hash = window.location.hash;
    var hashEl = $('ul.nav a[href="' + hash + '"]');
    hash && hashEl.tab('show');

    $('.nav-tabs a').click(function(e) {
      e.preventDefault();
      $(this).tab('show');
      window.location.hash = this.hash;
    });

    // Change tab on hashchange
    window.addEventListener('hashchange', function() {
      var changedHash = window.location.hash;
      changedHash && $('ul.nav a[href="' + changedHash + '"]').tab('show');
    }, false);
  }
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
<div class="container">
<ul class="nav nav-tabs">
  <li class="active"><a data-toggle="tab" href="#home">Home</a></li>
  <li><a data-toggle="tab" href="#menu1">Menu 1</a></li>
</ul>

<div class="tab-content">
  <div id="home" class="tab-pane fade in active">
    <h3>HOME</h3>
    <p>Some content.</p>
  </div>
  <div id="menu1" class="tab-pane fade">
    <h3>Menu 1</h3>
    <p>Some content in menu 1.</p>
  </div>
</div>
</div>


0

또 다른 접근법

페이지가 스크롤되었는지 확인한 다음 위치를 재설정하십시오.

var scrolled = false;

$(window).scroll(function(){
  scrolled = true;
});

if ( window.location.hash && scrolled ) {
  $(window).scrollTop( 0 );
}

Heres a demo


작동하지 않습니다 ... 초기로드가 하단에 있습니다 ... 새로 고침 후에도 상단에 유지됩니다
Martin Zvarík

0

setTimeoutFirefox 에서 위의 방법으로 많은 성공을 거두지 못했습니다 .

setTimeout 대신 onload 함수를 사용했습니다.

window.onload = function () {
    if (location.hash) {
        window.scrollTo(0, 0);
    }
};

불행히도 여전히 매우 결함이 있습니다.


onload는 사진을 포함하여 모든 것이 완전히로드 된 후에 실행되기 때문입니다. 물론 이런 방식으로 문제가 발생합니다
Martin Zvarík

0

나는 이러한 솔루션으로 일관된 성공을 거두지 못했습니다.

분명히 Javascript => reference ( http://forum.jquery.com/topic/preventing-anchor-jump 이전에 점프가 발생한다는 사실 때문입니다. )

내 해결책은 CSS를 사용하여 기본적으로 모든 앵커를 맨 위에 배치하는 것입니다.

.scroll-target{position:fixed;top:0;left:0;}

그런 다음 jquery를 사용하여 대상 앵커의 부모 또는 형제 (빈 em 태그 일 수 있음)로 스크롤합니다.

<a class="scroll-target" name="section3"></a><em>&nbsp</em>

URL이 해시로 입력 된 경우 스크롤하는 jquery 예제
(페이지가 창 / 탭에 이미로드되어 있지 않아야하며 다른 / 외부 소스의 링크를 다룹니다)

setTimeout(function() {
    if (window.location.hash) {               
        var hash = window.location.hash.substr(1);   
        var scrollPos = $('.scroll-target[name="'+hash+'"]').siblings('em').offset().top; 
        $("html, body").animate({ scrollTop: scrollPos }, 1000);    
    }
}, 1);

또한 페이지에있는 동안 앵커 클릭에 대한 기본값을 방지 한 다음 해당 대상으로 스크롤해야합니다.

<a class="scroll-to" href="#section3">section three</a>

및 jquery

$('a.scroll-to').click(function(){
    var target = $(this).attr('href').substr(1);
    var scrollPos = $('.scroll-target[name="'+target+'"]').siblings('em').offset().top; 
    $("html, body").animate({ scrollTop: scrollPos }, 1000);
    return false;
});

이 방법의 좋은 점은 앵커 태그 대상이며 CSS 위치가 맨 위에 있지만 구조적으로 관련 콘텐츠 옆에 남아 있다는 것입니다.

이는 검색 엔진 크롤러에 문제가 없음을 의미합니다.

건배,
그레이가 도움이 되길 바랍니다


0

클라이언트가 해시 변경 (이벤트 처리기 내부)에서 어떤 종류의 수직 스크롤을하지 않도록하려면 다음을 시도하십시오.

var sct = document.body.scrollTop;
document.location.hash = '#next'; // or other manipulation
document.body.scrollTop = sct;

(브라우저 다시 그리기)


0

이렇게하여 내 문제를 해결했습니다.

// navbar height 
var navHeigth = $('nav.navbar').height();    

// Scroll to anchor function
var scrollToAnchor = function(hash) {
  // If got a hash
  if (hash) {
    // Scroll to the top (prevention for Chrome)
    window.scrollTo(0, 0);
    // Anchor element
    var term = $(hash);

    // If element with hash id is defined
    if (term) {

      // Get top offset, including header height
      var scrollto = term.offset().top - navHeigth;

      // Capture id value
      var id = term.attr('id');
      // Capture name value
      var name = term.attr('name');

      // Remove attributes for FF scroll prevention
      term.removeAttr('id').removeAttr('name');
      // Scroll to element
      $('html, body').animate({scrollTop:scrollto}, 0);

      // Returning id and name after .5sec for the next scroll
      setTimeout(function() {
        term.attr('id', id).attr('name', name);
      }, 500);
    }
  }
};

// if we are opening the page by url
if (location.hash) {
  scrollToAnchor(location.hash);
}

// preventing default click on links with an anchor
$('a[href*="#"]').click(function(e) {
  e.preventDefault();
  // hash value
  var hash = this.href.substr(this.href.indexOf("#"));
  scrollToAnchor(hash);
});`
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.