앵커 링크를 클릭 할 때 부드러운 스크롤


487

내 페이지에 몇 개의 하이퍼 링크가 있습니다. 사용자가 내 도움말 섹션을 방문 할 때 읽을 수있는 FAQ입니다.

앵커 링크를 사용하여 페이지를 앵커쪽으로 스크롤하여 사용자를 안내 할 수 있습니다.

스크롤을 부드럽게 만드는 방법이 있습니까?

그러나 그는 사용자 정의 JavaScript 라이브러리를 사용하고 있습니다. 아마도 jQuery는 이와 같은 것을 제공합니까?


최고의 답변을 검토해 주시겠습니까? 순수 CSS의 한 줄 솔루션은 모든 부피가 큰 JQuery와 제안 중 찾기 어려운 것입니다 : stackoverflow.com/a/51588820/1422553
Александр Киричек

답변:


1159

2018 년 4 월 업데이트 : 이제이 작업을 수행하는 기본 방법이 있습니다 .

document.querySelectorAll('a[href^="#"]').forEach(anchor => {
    anchor.addEventListener('click', function (e) {
        e.preventDefault();

        document.querySelector(this.getAttribute('href')).scrollIntoView({
            behavior: 'smooth'
        });
    });
});

이것은 현재 가장 최신 브라우저에서만 지원됩니다.


이전 브라우저 지원을 위해이 jQuery 기술을 사용할 수 있습니다.

$(document).on('click', 'a[href^="#"]', function (event) {
    event.preventDefault();

    $('html, body').animate({
        scrollTop: $($.attr(this, 'href')).offset().top
    }, 500);
});

그리고 여기 바이올린이 있습니다 : http://jsfiddle.net/9SDLw/


대상 요소에 ID가없고로 ID를 연결하는 경우 다음을 name사용하십시오.

$('a[href^="#"]').click(function () {
    $('html, body').animate({
        scrollTop: $('[name="' + $.attr(this, 'href').substr(1) + '"]').offset().top
    }, 500);

    return false;
});

성능을 향상 시키 려면 앵커를 클릭 할 때마다$('html, body') 실행되지 않도록 해당 선택기를 캐시해야합니다 .

var $root = $('html, body');

$('a[href^="#"]').click(function () {
    $root.animate({
        scrollTop: $( $.attr(this, 'href') ).offset().top
    }, 500);

    return false;
});

URL을 업데이트하려면 animate콜백 내에서 수행하십시오 .

var $root = $('html, body');

$('a[href^="#"]').click(function() {
    var href = $.attr(this, 'href');

    $root.animate({
        scrollTop: $(href).offset().top
    }, 500, function () {
        window.location.hash = href;
    });

    return false;
});

10
이것은 URL에서 #extension을 제거하여 back 기능을 중단하는 것으로 보입니다. 이 주위에 방법이 있습니까?
Fletch

2
@JosephSilber scrollTop: $(this.hash).offset().top대신에 그렇게하지 말아야 scrollTop: $(this.href).offset().top합니까?
Gregory Pakosz

4
@CreateSean -scrollTop: $(href).offset().top - 72
조셉 실버

5
html, body여기 에서 객체 를 캐싱하는 것은 불필요하며 클릭당 한 번만 선택기를 실행하는 것이 그리 많지는 않다고 주장합니다.

2
첫 번째 솔루션은 가장 가장 현대적인이 함께 오래된 브라우저에서이 동작을 지원하기 위해이 polyfill을 사용할 수있다 polyfill
에페

166

올바른 구문은 다음과 같습니다.

//Smooth scrolling with links
$('a[href*=\\#]').on('click', function(event){     
    event.preventDefault();
    $('html,body').animate({scrollTop:$(this.hash).offset().top}, 500);
});

// Smooth scrolling when the document is loaded and ready
$(document).ready(function(){
  $('html,body').animate({scrollTop:$(location.hash).offset().‌​top}, 500);
});

단순화 : 건조

function smoothScrollingTo(target){
  $('html,body').animate({scrollTop:$(target).offset().​top}, 500);
}
$('a[href*=\\#]').on('click', function(event){     
    event.preventDefault();
    smoothScrollingTo(this.hash);
});
$(document).ready(function(){
  smoothScrollingTo(location.hash);
});

설명 href*=\\#:

  • *그것은 #char를 포함하는 것과 일치한다는 것을 의미합니다 . 따라서 앵커 만 일치 합니다 . 이것의 의미에 대한 자세한 내용은 여기를 참조 하십시오
  • \\#CSS 선택기의 특수 문자 이기 때문에 이스케이프해야합니다.

8
앵커 URL 만 제공 하도록 변경 $('a')해야 $('a[href*=#]')했습니다
okliv

2
@okliv 예를 들어와 같은 자바 스크립트 링크와 같이 너무 많이 제공됩니다 <a href="javascript:$('#test').css('background-color', '#000')">Test</a>. $('a[href^=#]')해시 문자로 시작하는 모든 URL을 일치시키는 데 사용해야 합니다.
Martin Braun

3
또한 '#'은 특수 문자이며 다음과 같이 이스케이프해야합니다.a[href^=\\#]
QuinnFreedman

3
이로 인해 다른 페이지의 앵커 링크가 작동을 멈췄습니다. 조건부 if ($ ($ (this.hash) .selector) .length) {... 매끄러운 스크롤을 추가하여 해결했습니다. }
Liren

1
새 페이지로 처음 여행 할 때 어떻게 애니메이션을 적용 할 수 있습니까? 예를 들어 website.com/newpage/#section2를 클릭하십시오. 페이지를로드 한 다음 아래로 스크롤하고 싶습니다. 가능합니까?
Samyer

72

CSS3의 새로운 매력. 이것은이 페이지에 나열된 모든 방법보다 훨씬 쉽고 Javascript가 필요하지 않습니다. 아래 코드를 CSS에 입력하면 모든 갑자기 링크가 자신의 페이지 내부 위치를 가리키며 부드러운 스크롤 애니메이션이 생깁니다.

html{scroll-behavior:smooth}

그 후 div를 가리키는 링크는 해당 섹션으로 부드럽게 움직입니다.

<a href="#section">Section1</a>

편집 : 위의 태그에 대해 혼란스러워하는 사람들을 위해. 기본적으로 클릭 가능한 링크입니다. 그런 다음 웹 페이지 어딘가에 다른 div 태그를 넣을 수 있습니다

<div classname="section">content</div>

이와 관련하여 링크를 클릭 할 수 있으며 # 섹션으로 이동합니다.이 경우 섹션이라고하는 div입니다.

BTW, 나는 이것을 작동시키기 위해 몇 시간을 보냈다. 모호한 의견 섹션에서 해결책을 찾았습니다. 버그가 있었고 일부 태그에서는 작동하지 않습니다. 몸에서 일하지 않았다. CSS 파일의 html {}에 넣을 때 마침내 작동했습니다.


4
매우 편리하지만 단점이 있습니다.
Buzut

3
멋지지만 현재 Safari에서 지원되지 않으며 Explorer (03/2019)에서 지원되지 않기 때문에 조심하십시오.
Marco Romano

2
좋은 해결책, 적용 범위는 74,8 %로 ​​제한됩니다. 어쩌면 미래에
iepur1lla

1
놀랍습니다. 고마워
Mikkel Fennefoss 19 :

1
이것은 향후 몇 년 동안 가장 적절한 답변이 될 것입니다.
Nurul Huda

22
$('a[href*=#]').click(function(event){
    $('html, body').animate({
        scrollTop: $( $.attr(this, 'href') ).offset().top
    }, 500);
    event.preventDefault();
});

이것은 나를 위해 완벽하게 일했다


1
"event.preventDefault ();" "거짓을 돌려주십시오";
Andres Separ

유감스럽게도 anchor라는 페이지에서 작동하지 않고 부드럽게 표시되지 않습니다.
Kamlesh 2014

18

브라우저 위치 해시를 일치시키는 업데이트를 처리하는 기본 솔루션을 게시 한 사람이 아무도 없습니다. 여기있어:

let anchorlinks = document.querySelectorAll('a[href^="#"]')
 
for (let item of anchorlinks) { // relitere 
    item.addEventListener('click', (e)=> {
        let hashval = item.getAttribute('href')
        let target = document.querySelector(hashval)
        target.scrollIntoView({
            behavior: 'smooth',
            block: 'start'
        })
        history.pushState(null, null, hashval)
        e.preventDefault()
    })
}

학습서 참조 : http://www.javascriptkit.com/javatutors/scrolling-html-bookmark-javascript.shtml

고정 헤더가있는 사이트의 경우 scroll-padding-topCSS를 사용하여 오프셋을 제공 할 수 있습니다.


1
이 답변이 가장 마음에 듭니다. 그러나 오프셋을 제공 할 방법이 없습니다. 고정 헤더의 경우에 필요합니다.
bskool

Unfotunately, CSS 스크롤 행동 속성과 같은 가난한 지원 : developer.mozilla.org/en-US/docs/Web/CSS/...
드미트리 Nevzorov

15

CSS 만

html {
    scroll-behavior: smooth !important;
}

이것 만 추가하면됩니다. 이제 내부 링크 스크롤 동작이 스트림 흐름처럼 매끄 럽습니다.

참고 : 모든 최신 브라우저 ( Opera, Chrome, Firefox등)이 기능을 지원합니다.

자세한 내용은이 기사를 읽으십시오.


1
좋은! 이것이 왜 대답이 아닌가? 우리는 모든 자바 스크립트가 필요하지 않습니다!
Trevor de Koekkoek

1
훌륭하게 작동합니다.이 답변은 받아 들여야합니다.
무덤

브라우저 지원을 확인 여기
라이언 저우에게

1
그것은 매력처럼 작동합니다. js 필요 없음
Navbro

이것은 부드러운 스크롤을위한 최고의 솔루션입니다! 감사!
yehanny

10

이 일반적인 코드를 작성하는 것이 좋습니다.

$('a[href^="#"]').click(function(){

var the_id = $(this).attr("href");

    $('html, body').animate({
        scrollTop:$(the_id).offset().top
    }, 'slow');

return false;});

jquery-effet-smooth-scroll-defilement-fluide : 여기에서 아주 좋은 기사를 볼 수 있습니다


9
이것은 일반적인 것이 아니며 jQuery입니다.
AnrDaemon

6
$(function() {
  $('a[href*=#]:not([href=#])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });
});

공식 : http://css-tricks.com/snippets/jquery/smooth-scrolling/


1
이것은 단지 내부 페이지 앵커 링크 작동하는 것 같다,하지만 다른 페이지에서 앵커 링크는 예를 들어, 일을하지 않는 website.com/about-us/#who-we-are
rainerbrunotte

5

여기에는 이미 많은 좋은 답변이 있지만 빈 앵커를 제외해야 한다는 사실이 모두 빠져 있습니다 . 그렇지 않으면 빈 앵커를 클릭하자마자 해당 스크립트가 JavaScript 오류를 생성합니다.

제 생각에는 정답은 다음과 같습니다.

$('a[href*=\\#]:not([href$=\\#])').click(function() {
    event.preventDefault();

    $('html, body').animate({
        scrollTop: $($.attr(this, 'href')).offset().top
    }, 500);
});

4

JQuery 사용하기 :

$('a[href*=#]').click(function(){
  $('html, body').animate({
    scrollTop: $( $.attr(this, 'href') ).offset().top
  }, 500);
  return false;
});


3

주어진 대답은 효과가 있지만 발신 링크는 비활성화합니다. 보너스가 추가 된 버전 (스윙)과 나가는 링크를 존중하는 버전 아래.

$(document).ready(function () {
    $('a[href^="#"]').on('click', function (e) {
        e.preventDefault();

        var target = this.hash;
        var $target = $(target);

        $('html, body').stop().animate({
            'scrollTop': $target.offset().top
        }, 900, 'swing', function () {
            window.location.hash = target;
        });
    });
});

stop()그러나 URL crumb가 +1이면 예상대로 작동하지 않습니다. Back 버튼이 다시 표시되지 않습니다. 이는 애니메이션이 완료된 후 crumb가 URL에 설정되어 있기 때문입니다. URL에 부스러기가 없으면 더 좋습니다. 예를 들어 airbnb가하는 방식입니다.
Eric

3

HTML

<a href="#target" class="smooth-scroll">
    Link
</a>
<div id="target"></div>

또는 전체 URL로

<a href="https://somewebsite.com/#target" class="smooth-scroll">
    Link
</a>
<div id="target"></div>

jQuery

$j(function() {
    $j('a.smooth-scroll').click(function() {
        if (
                window.location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '')
            &&  window.location.hostname == this.hostname
        ) {
            var target = $j(this.hash);
            target = target.length ? target : $j('[name=' + this.hash.slice(1) + ']');
            if (target.length) {
                $j('html,body').animate({
                    scrollTop: target.offset().top - 70
                }, 1000);
                return false;
            }
        }
    });
});

3

요즘 최신 브라우저는 조금 더 빠릅니다. setInterval이 작동 할 수 있습니다. 이 기능은 요즘 Chrome과 Firefox에서 잘 작동합니다. (사파리에서는 약간 느리고 IE에는 신경 쓰지 않았습니다)

function smoothScroll(event) {
    if (event.target.hash !== '') { //Check if tag is an anchor
        event.preventDefault()
        const hash = event.target.hash.replace("#", "")
        const link = document.getElementsByName(hash) 
        //Find the where you want to scroll
        const position = link[0].getBoundingClientRect().y 
        let top = 0

        let smooth = setInterval(() => {
            let leftover = position - top
            if (top === position) {
                clearInterval(smooth)
            }

            else if(position > top && leftover < 10) {
                top += leftover
                window.scrollTo(0, top)
            }

            else if(position > (top - 10)) {
                top += 10
                window.scrollTo(0, top)
            }

        }, 6)//6 milliseconds is the faster chrome runs setInterval
    }
}

3

스크롤 동작을 사용 하여이 작업을 수행하는 CSS 방법이 있습니다. 다음 속성을 추가하십시오.

    scroll-behavior: smooth;

그게 다야. JS가 필요하지 않습니다.

a {
  display: inline-block;
  width: 50px;
  text-decoration: none;
}
nav, scroll-container {
  display: block;
  margin: 0 auto;
  text-align: center;
}
nav {
  width: 339px;
  padding: 5px;
  border: 1px solid black;
}
scroll-container {
  display: block;
  width: 350px;
  height: 200px;
  overflow-y: scroll;
  scroll-behavior: smooth;
}
scroll-page {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-size: 5em;
}
<nav>
  <a href="#page-1">1</a>
  <a href="#page-2">2</a>
  <a href="#page-3">3</a>
</nav>
<scroll-container>
  <scroll-page id="page-1">1</scroll-page>
  <scroll-page id="page-2">2</scroll-page>
  <scroll-page id="page-3">3</scroll-page>
</scroll-container>

추신 : 브라우저 호환성을 확인하십시오.


스크롤 동작을 사용해야하는 컨테이너 : smooth;
CraZyDroiD

의심스러운 경우 본문 태그 @CraZyDroiD
Santosh에

2

이것을 추가 :

function () {
    window.location.hash = href;
}

어떻게 든 수직 오프셋을 무효화합니다.

top - 72

Chrome이 아닌 Firefox 및 IE에서. 기본적으로 페이지는 오프셋을 기준으로 중지해야하는 지점으로 부드럽게 스크롤되지만 오프셋없이 페이지가 이동하는 위치로 이동합니다.

URL 끝에 해시를 추가하지만 뒤로 키를 누르면 맨 위로 돌아 가지 않고 URL에서 해시를 제거하고 앉아있는보기 창을 떠납니다.

내가 사용하는 전체 js는 다음과 같습니다.

var $root = $('html, body');
$('a').click(function() {
    var href = $.attr(this, 'href');
    $root.animate({
        scrollTop: $(href).offset().top - 120
    }, 500, function () {
        window.location.hash = href;
    });
    return false;
});

2

이 솔루션은 다른 페이지에 대한 앵커 링크를 끊지 않고 다음 URL에 대해서도 작동합니다.

http://www.example.com/dir/index.html
http://www.example.com/dir/index.html#anchor

./index.html
./index.html#anchor

기타

var $root = $('html, body');
$('a').on('click', function(event){
    var hash = this.hash;
    // Is the anchor on the same page?
    if (hash && this.href.slice(0, -hash.length-1) == location.href.slice(0, -location.hash.length-1)) {
        $root.animate({
            scrollTop: $(hash).offset().top
        }, 'normal', function() {
            location.hash = hash;
        });
        return false;
    }
});

아직 모든 브라우저에서 이것을 테스트하지는 않았습니다.


2

이를 통해 jQuery가 대상 해시를 쉽게 식별하고 언제 어디서 어디서 중지해야하는지 알 수 있습니다.

$('a[href*="#"]').click(function(e) {
    e.preventDefault();
    var target = this.hash;
    $target = $(target);

    $('html, body').stop().animate({
        'scrollTop': $target.offset().top
    }, 900, 'swing', function () {
        window.location.hash = target;
    });
});

2
$("a").on("click", function(event){
    //check the value of this.hash
    if(this.hash !== ""){
        event.preventDefault();

        $("html, body").animate({scrollTop:$(this.hash).offset().top}, 500);

        //add hash to the current scroll position
        window.location.hash = this.hash;

    }



});

2

테스트 및 검증 된 코드

<script>
jQuery(document).ready(function(){
// Add smooth scrolling to all links
jQuery("a").on('click', function(event) {

// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
  // Prevent default anchor click behavior
  event.preventDefault();

  // Store hash
  var hash = this.hash;

  // Using jQuery's animate() method to add smooth page scroll
  // The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
  jQuery('html, body').animate({
    scrollTop: jQuery(hash).offset().top
  }, 800, function(){

    // Add hash (#) to URL when done scrolling (default click behavior)
    window.location.hash = hash;
  });
} // End if
});
});
</script>

1

"/ xxxxx # asdf"및 "#asdf"href 앵커 모두에 대해이 작업을 수행했습니다.

$("a[href*=#]").on('click', function(event){
    var href = $(this).attr("href");
    if ( /(#.*)/.test(href) ){
      var hash = href.match(/(#.*)/)[0];
      var path = href.match(/([^#]*)/)[0];

      if (window.location.pathname == path || path.length == 0){
        event.preventDefault();
        $('html,body').animate({scrollTop:$(this.hash).offset().top}, 1000);
        window.location.hash = hash;
      }
    }
});

1

매끄러운 스크롤을 위해 여러 링크와 앵커에 구현 한 솔루션은 다음과 같습니다.

http://www.adriantomic.se/development/jquery-localscroll-tutorial/ 탐색 div에 탐색 링크가 설정되어 있고이 구조로 선언 된 경우 :

<a href = "#destinationA">

해당 앵커 태그 대상은 다음과 같습니다.

<a id = "destinationA">

그런 다음 문서 헤드에 이것을 넣으십시오.

    <!-- Load jQuery -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>

<!-- Load ScrollTo -->
<script src="http://flesler-plugins.googlecode.com/files/jquery.scrollTo-1.4.2-min.js"></script>

<!-- Load LocalScroll -->
<script src="http://flesler-plugins.googlecode.com/files/jquery.localscroll-1.2.7-min.js"></script>

<script type = "text/javascript">
 $(document).ready(function()
    {
        // Scroll the whole document
        $('#menuBox').localScroll({
           target:'#content'
        });
    });
</script>

@Adriantomic 덕분에


1

페이지에 div로 스크롤 할 수있는 간단한 버튼이 있고 맨 위로 이동 하여 뒤로 버튼 이 작동하려면 다음 코드를 추가하십시오.

$(window).on('hashchange', function(event) {
    if (event.target.location.hash=="") {
        window.scrollTo(0,0);
    }
});

이것은 해시 값을 읽고 Joseph Silbers 답변과 같이 스크롤하여 다른 div로 이동하도록 확장 할 수 있습니다.


1

offset () 함수가 요소의 위치를 ​​문서화하는 것을 잊지 마십시오. 따라서 부모를 기준으로 요소를 스크롤해야 할 때 이것을 사용해야합니다.

    $('.a-parent-div').find('a').click(function(event){
        event.preventDefault();
        $('.scroll-div').animate({
     scrollTop: $( $.attr(this, 'href') ).position().top + $('.scroll-div').scrollTop()
     }, 500);       
  });

요점은 scroll-div의 scrollTop을 가져 와서 scrollTop에 추가하는 것입니다. 그렇게하지 않으면 position () 함수는 항상 다른 위치 값을 제공합니다.


1

당신은 사용할 수 있습니다 window.scroll()behavior: smooth하고 top있는 앵커 태그는 뷰포트의 상단에있을 것입니다 보장 앵커 태그의 오프셋 (offset) 정상에 설정합니다.

document.querySelectorAll('a[href^="#"]').forEach(a => {
    a.addEventListener('click', function (e) {
        e.preventDefault();
        var href = this.getAttribute("href");
        var elem = document.querySelector(href)||document.querySelector("a[name="+href.substring(1, href.length)+"]");
        //gets Element with an id of the link's href 
        //or an anchor tag with a name attribute of the href of the link without the #
        window.scroll({
            top: elem.offsetTop, 
            left: 0, 
            behavior: 'smooth' 
        });
        //if you want to add the hash to window.location.hash
        //you will need to use setTimeout to prevent losing the smooth scrolling behavior
       //the following code will work for that purpose
       /*setTimeout(function(){
            window.location.hash = this.hash;
        }, 2000); */
    });
});

데모:

CSS 속성 scroll-behaviorsmooth(대부분의 최신 브라우저에서 지원)로 설정하면 Javascript가 필요하지 않습니다.


0

공유해 주셔서 감사합니다. Joseph Silber. 다음은 표준 동작을 유지하기 위해 약간 변경 한 ES6의 2018 솔루션입니다 (스크롤 맨 위로).

document.querySelectorAll("a[href^=\"#\"]").forEach((anchor) => {
  anchor.addEventListener("click", function (ev) {
    ev.preventDefault();

    const targetElement = document.querySelector(this.getAttribute("href"));
    targetElement.scrollIntoView({
      block: "start",
      alignToTop: true,
      behavior: "smooth"
    });
  });
});

0

브라우저 URL에 해시를 추가하는 동안 jquery와 애니메이션이 id 대신 지정된 이름으로 태그를 고정해야합니다. # 기호 앞에 이스케이프 백 슬래시가 붙지 않는 jquery에 대한 대부분의 답변에서 오류를 수정합니다. 불행히도 뒤로 버튼은 이전 해시 링크로 올바르게 돌아 가지 않습니다 ...

$('a[href*=\\#]').click(function (event)
{
    let hashValue = $(this).attr('href');
    let name = hashValue.substring(1);
    let target = $('[name="' + name + '"]');
    $('html, body').animate({ scrollTop: target.offset().top }, 500);
    event.preventDefault();
    history.pushState(null, null, hashValue);
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.