새로 고침시 자동 브라우저 스크롤 방지


95

페이지 a로 이동하여 스크롤 한 다음 새로 고침하면 페이지를 떠난 지점에서 새로 고침됩니다. 이것은 훌륭하지만 URL에 앵커 위치가있는 페이지에서도 발생합니다. 예를 들어 링크를 클릭하고 http://example.com/post/244#comment5주변을 둘러 본 후 페이지를 새로 고치면 앵커에 있지 않고 페이지가 점프합니다. 자바 스크립트로 이것을 방지하는 방법이 있습니까? 그래서 당신이 항상 앵커로 이동하는 것은 중요하지 않습니다.


jQuery 솔루션이 괜찮습니까 아니면 일반 js를 원하십니까?
mrtsherman

답변:


16

이 솔루션은 브라우저 동작의 변경으로 인해 더 이상 권장되지 않습니다. 다른 답변을 참조하십시오.

기본적으로 앵커가 사용되면 창 스크롤 이벤트에 바인딩합니다. 첫 번째 스크롤 이벤트는 브라우저가 수행하는 자동 위치 조정에 속해야한다는 생각입니다. 이것이 발생하면 우리는 우리 자신의 위치를 ​​변경하고 바운드 이벤트를 제거합니다. 이는 후속 페이지 스크롤이 시스템을 지루하게하는 것을 방지합니다.

$(document).ready(function() {
    if (window.location.hash) { 
        //bind to scroll function
        $(document).scroll( function() {
            var hash = window.location.hash
            var hashName = hash.substring(1, hash.length);
            var element;

            //if element has this id then scroll to it
            if ($(hash).length != 0) {
                element = $(hash);
            }
            //catch cases of links that use anchor name
            else if ($('a[name="' + hashName + '"]').length != 0)
            {
                //just use the first one in case there are multiples
                element = $('a[name="' + hashName + '"]:first');
            }

            //if we have a target then go to it
            if (element != undefined) {
                window.scrollTo(0, element.position().top);
            }
            //unbind the scroll event
            $(document).unbind("scroll");
        });
    }

});

내가 생각해야 할 사용 사례 중 하나는 자동 스크롤이 발생하기 전에 사용자가 페이지를 스크롤하는 경우입니다. 자동 스크롤링은 페이지가 완전히로드 된 후에 만 ​​발생합니다. 사용자가 이전에 스크롤하면 자동 스크롤이 취소됩니다. 따라서 사용자 시작 스크롤과 브라우저 시작을 구별하는 방법이 필요합니다. 나는 이것을하는 방법을 모르지만, 내가 기억하는대로 그것은 가능하다.
mrtsherman

1
부야! 이것은 재미있는 심야 문제였습니다. 그래도 내 책상에서 잠들 때 당신 잘못이라고 상사에게 말하고 있어요. 방금 return 문을 제거하기 위해 빠르게 변경했습니다. 이것은 스크롤 이벤트에 대해 추가 한 바인딩 해제를 방해했습니다.
mrtsherman

처음에는 작은 기본 예제 파일에서이 작업을 확인하여 확인했습니다. 제대로 작동하는지 확인한 후에는 내 프로젝트에서 작동하지 않는 방식에 당황했습니다. 제거 프로세스를 통해 CSS 파일에서 오류를 일으키는 단일 스타일 선언을 찾았습니다. 그것은 외부 글꼴의 적용이었습니다. 코드를 함수로 래핑하고 이제 doc.ready 핸들러 내에서 $ (window) .load () 핸들러로 전달합니다. 이제 작동하도록 이음새가 생깁니다 (약간의 초기 페이지 깜박임). 코드 감사합니다! 이것이 확실한 해결책인지 알려주세요.
ThomasReggi

1
페이지가로드 된 후로드되는 콘텐츠가있는 경우 작동하지 않습니다. 예 : 배너로 ajax에서 채워질 2div가 있습니다.
Decebal

@FlashThunder- "작동하지 않음"을 정의 할 수 있습니까? 콘솔 메시지를 게시 하시겠습니까?
mrtsherman

151

Chrome에서는 scrollTop을 0으로 강제 설정하더라도 첫 번째 스크롤 이벤트 이후에 점프합니다.

다음과 같이 스크롤을 바인딩해야합니다.

$(window).on('beforeunload', function() {
    $(window).scrollTop(0);
});

따라서 브라우저는 새로 고침 전 처음에 있다고 믿도록 속입니다.


5
스크롤링을 엉망으로 만들고 싶지 않은 경우 허용되는 답변보다 훨씬 유용합니다.
Dan Abramov 2013 년

2
이것은 Chrome 33에서 작업을 수행하지 않습니다. 새 페이지를로드하기 전에 맨 위로 스크롤된다는 의미입니다. 그러나 브라우저는 여전히 이전 스크롤 위치를 기억하고 해당 위치로 동일한 자동 스크롤을 수행합니다.
Haralan Dobrev

1
Chrome 36, Firefox 30 및 IE 11에서 테스트되었습니다. 잘 작동합니다!
Fizzix

24
비 jQuery 구현의 경우 : window.onbeforeunload = function(){ window.scrollTo(0,0); }
ProfNandaa 2014

5
'언로드'대신 '베포 른로드'이벤트를 선택한 이유는 무엇입니까? 내 테스트에 따르면 마지막 페이지는 브라우저에서 페이지를 실제로 언로드하기 전에 맨 위로 이동하는 것을 방지 할 수 있습니다.
Aleksandr Zonov

74

자동 스크롤 복원을 비활성화하려면이 태그를 헤드 섹션에 추가하면됩니다.

<script>history.scrollRestoration = "manual"</script>

IE에서는 지원하지 않습니다. 브라우저 호환성.


3
IE / Edge에서 사용할 수 있다면 이것이 가장 좋은 대답입니다. 여기에서 구현하도록 투표 할 수 있습니다. wpdev.uservoice.com/forums/257854-microsoft-edge-developer/…
The Chewy

4
이것은 2019 년의 정답이 될 것입니다. 다른 어떤 방법도 100 % 작동하지 않습니다.
Limbo

2
이것이 최선의 해결 책임을 확인할 수 있습니다. 여기에있는 다른 솔루션은 Mobile Safari에서 작동하지 않으며 버벅 거릴 수 있습니다. 이것은 완벽하게 작동합니다.
user3330820

20

몇 번의 실패 후에 마침내 나는 트릭을 할 수있었습니다. anzobeforeunload사용자가 페이지를 다시로드하거나 링크를 클릭 할 때 페이지가 맨 위로 이동하도록하므로 여기에서 정확 합니다. 그렇게하는 unload것이 분명한 방법입니다.

$(window).on('unload', function() {
   $(window).scrollTop(0);
});

자바 스크립트 방식 ( ProfNandaa 에게 감사 드립니다 ) :

window.onunload = function(){ window.scrollTo(0,0); }

수정 : 2015 년 7 월 16 일

unload이벤트 에도 불구하고 Firefox에는 점프 문제가 여전히 있습니다 .


3
이 솔루션은 beforeunload새로 고침 및 앵커 클릭시 페이지 상단으로 이동하는 것을 방지하기 때문에 솔루션 보다 훨씬 낫습니다 .
BradGreens

@BradGreens 최신 Chrome에서는 사용자가 다른 탭으로 전환 할 때도 onunload 이벤트가 트리거되며 이는 예상치 못한 일입니다. onbeforeunload는 여전히 유효한 해결 방법입니다.
Telvin Nguyen

@TelvinNguyen 이것에 대한 자원을 줄 수 있습니까? 나는 이것을 Google 크롬 72에서 테스트했으며 여전히 잘 작동합니다.
Janaka Dombawela

@JanakaDombawela 내가 말한 것 : 문제를 일으키는 새 탭 이동이 잘못되었습니다. 그러나이 예제에서 이벤트 onunload가 jQuery 1.9.1과 jQuery 1.8.3을 사용해도 제대로 트리거되지 않음을 알 수 있습니다. onunload는 신뢰할 수 없습니다. jsfiddle.net/6s4jhdug/3(1.8.3 ) jsfiddle.net/frt45ue9(1.9.1 )
Telvin Nguyen

3

다음은보다 일반적인 접근 방식입니다. 브라우저가 스크롤 (또는 보이는 것처럼 맨 위로 점프)하는 것을 방지하는 대신 페이지의 이전 위치를 복원합니다. 즉, localStorage에 페이지의 현재 y 오프셋을 기록하고 페이지가로드되면이 위치로 스크롤합니다.

function storePagePosition() {
  var page_y = window.pageYOffset;
  localStorage.setItem("page_y", page_y);
}


window.addEventListener("scroll", storePagePosition);


var currentPageY;

try {
  currentPageY = localStorage.getItem("page_y");

  if (currentPageY === undefined) {
    localStorage.setItem("page_y") = 0;
  }

  window.scrollTo( 0, currentPageY );
} catch (e) {
    // no localStorage available
}

2

페이지가 맨 위에로드되도록 끝에 #을 입력 할 수 있습니다.

매우 간단하기 때문에 모든 브라우저, 모바일 및 데스크톱에서 작동합니다.

$(document).ready(function() {
var url = window.location.href;
console.log(url);
if( url.indexOf('#') < 0 ) {
    window.location.replace(url + "#");
} else {
    window.location.replace(url);
}

});

// 마지막에 #이있는 페이지를로드합니다.


내 서버에서 직접 시도하면 마술처럼 작동합니다. 그러나 내 cms가 마크 업 오류를 제공합니다. 그게 뭔지 모르겠어요.
alice

1
당신은 워드 프레스의 변화를 사용하는 경우 $ jQuery를위한
Herzling

1

이것은 나를 위해 작동합니다.

    //Reset scroll top

    history.scrollRestoration = "manual"

    $(window).on('beforeunload', function(){
          $(window).scrollTop(0);
    });

-2

할 수 있어야합니다.

Onload, window.location.hash값이 있는지 확인하십시오 . 그렇다면 해시 값과 일치하는 ID를 가진 요소를 가져옵니다. 요소의 위치 (offsetTop / offsetLeft에 대한 재귀 호출)를 찾은 다음 해당 값을 window.scrollTo(x, y)메서드에 전달합니다 .

페이지를 원하는 요소로 스크롤해야합니다.


3
이것은 브라우저가 자동 스크롤을 수행하는 것을 막지는 않습니다. 이것이 바로이 질문에 관한 것입니다.
Haralan Dobrev
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.