전체 페이지를 이동시키는 ScrollIntoView ()


110

ScrollIntoView ()를 사용하여 목록에서 강조 표시된 항목을보기로 스크롤합니다. 아래로 스크롤하면 ScrollIntoView (false)가 완벽하게 작동합니다. 그러나 위로 스크롤하면 ScrollIntoView (true)로 인해 전체 페이지가 의도 한대로 약간 이동합니다. ScrollIntoView (true)를 사용할 때 전체 페이지 이동을 피하는 방법이 있습니까?

내 페이지의 구조는 다음과 같습니다.

#listOfDivs {
  position:fixed;
  top:100px;
  width: 300px;
  height: 300px;
  overflow-y: scroll;
}

<div="container">
    <div="content"> 
         <div id="listOfDivs"> 
             <div id="item1"> </div>
             <div id="item2"> </div>
             <div id="itemn"> </div>
         </div>
    </div>
</div>

listOfDivs는 ajax 호출에서 제공됩니다. 모바일 사파리 사용.

미리 도와 주셔서 감사합니다!


1
문제가 무엇인지 정확히 알 수 있도록 JSFiddle을 제공 할 수 있습니까?
Robert Koritnik

답변:


115

scrollTop대신 사용할 수 있습니다 scrollIntoView().

var target = document.getElementById("target");
target.parentNode.scrollTop = target.offsetTop;

jsFiddle : http://jsfiddle.net/LEqjm/

스크롤하려는 스크롤 가능한 요소가 두 개 이상 있는 경우 중간 요소의에 scrollTop따라 각 offsetTop요소를 개별적 으로 변경해야합니다 . 이렇게하면 문제가 발생하지 않도록 세밀한 제어가 가능합니다.

편집 : offsetTop은 반드시 부모 요소와 관련이있는 것은 아니며 첫 번째 위치에있는 조상과 관련이 있습니다. 부모 요소의 위치가 지정되지 않은 경우 (상대, 절대 또는 고정) 두 번째 줄을 다음과 같이 변경해야 할 수 있습니다.

target.parentNode.scrollTop = target.offsetTop - target.parentNode.offsetTop;

3
참고로, 이것은 부모가 페이지 상단에있을 때만 작동합니다. 당신은 아마 그것을 만들어야합니다target.parentNode.scrollTop = target.offsetTop - target.parentNode.offsetTop
Phil

2
offsetTop은 가장 가까운 위치에있는 부모에 상대적이므로 부모 노드에가있는 경우 position: relative오프셋을 빼서는 안됩니다. 하지만 대부분의 경우에 맞습니다.
Brilliand

2
다음은 js 바이올린입니다 : jsfiddle.net/LEqjm/258 은 ScrollIntoView 부적절한 동작도 보여줍니다.
Rafi

1
@Brilliand에 대한 아이디어를 주셔서 감사합니다 position: relativeprent 사업부에 : 그것은 정말 문제를 해결
알렉스 쥬 코브 스키에게

크롬에서 작동하지만 IE에서 약간 더 스크롤되어 텍스트 내용을 맨 위에서 숨 깁니다. 사전에 모든 솔루션 @Phil, 감사합니다
Soniya

123

다음과 같이 수정했습니다.

element.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' })

참조 : https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView


1
감사합니다. 나는 블록의 사용을 이해하지 못했고 그것을 읽을 때의 가치입니다. 이제 문제가 해결
되었으므로

3
"가장 가까운"은 무엇을 의미합니까? 편집 : 여기에서 답을 찾았습니다 : stackoverflow.com/a/48635751/628418
Sammi

이것은 내 문제를 해결했습니다. 우리 웹 앱에서 이런 일이 발생하는 것을 한동안 지켜 봤지만 재현을 잠그기가 어려웠습니다. 새로운 기능을 추가 한 후 매번 발생했으며 block : 'nearest'매개 변수 가 누락 된이 호출을 추적 할 수있었습니다 .
roskelld 19

블록 값이 의미하는 바를 정의했다면 시작과 가장 가까운 ... 모든 시행 착오.
Bae

Chrome에서는 작동하지만 Edge에서는 작동하지 않습니다.
Michael

13
var el = document.querySelector("yourElement");
window.scroll({top: el.offsetTop, behavior: 'smooth'});

또는 사용할 수 있습니다top: el['offsetTop']
Junior Mayhé

이것은 나를 위해 가장 잘 작동합니다. 그러나 파이어 폭스에서는 여전히 약간 버그가 있습니다. 때때로 요소가 멈 춥니 다. 가장자리와 크롬에 좋습니다.
마크

9

나도이 문제가 있었고, 그것을 해결하기 위해 많은 시간을 보냈다. 내 결심이 여전히 일부 사람들에게 도움이되기를 바랍니다.

내 수정 사항은 다음과 같습니다.

  • 크롬의 경우 : 변경 .scrollIntoView().scrollIntoView({block: 'nearest'}) (@jfrohn에게 감사)로 .
  • Firefox의 경우 : overflow: -moz-hidden-unscrollable;이동하는 컨테이너 요소에 적용 하십시오.
  • 다른 브라우저에서는 테스트되지 않았습니다.

8

scrollIntoViewIfNeeded()...로 놀아 보세요. 브라우저에서 지원하는지 확인하세요.


1
그게 무슨 일인지 몰랐 습니다. 있다 polyfill
mpen

문서에서는 표준이 아니지만 잘 작동한다고 언급했습니다. 우리는 그것을 사용해야합니까?
Shyam Kumar

8

ScrollIntoView- http : //jsfiddle.net/LEqjm/258/의 부적절한 동작을 표시하는 방법을 추가했습니다. [댓글이어야하지만 평판이 충분하지 않습니다.]

$("ul").click(function() {
    var target = document.getElementById("target");
if ($('#scrollTop').attr('checked')) {
    target.parentNode.scrollTop = target.offsetTop;    
} else {
        target.scrollIntoView(!0);
}
});

7
jQuery 질문이 아닙니다.
seangates

6

jQuery 플러그인 scrollintoview()은 유용성을 높입니다.

기본 DOM 구현 대신 움직임을 애니메이션하고 원치 않는 효과가없는 플러그인을 사용할 수 있습니다. 기본값으로 사용하는 가장 간단한 방법은 다음과 같습니다.

$("yourTargetLiSelector").scrollintoview();

어쨌든 모든 세부 사항을 읽을 수있는 이 블로그 게시물로 이동하여 결국 플러그인의 GitHub 소스 코드 를 볼 수 있습니다.

이 플러그인은 가장 가까운 스크롤 가능한 상위 요소를 자동으로 검색하고 선택한 요소가 보이는 뷰 포트 안에 있도록 스크롤합니다. 요소가 이미 뷰포트에 있다면 당연히 아무것도하지 않습니다.


19
@Brilliand : 물론 사실이지만 그렇다고해서 그들이 그것을 사용하지 않거나 사용하기를 꺼린다는 의미는 아닙니다. 내가하는 일은 대안을 제공하는 것뿐입니다. 그것이 그들이 취할 길인지 아닌지를 결정하는 것은 OP에 있습니다. 아마도 그들은 처음에 jQuery 사용을 고려하지 않았을 것입니다.
Robert Koritnik 2012-06-21

그 OP는 jQuery가 완전히 무관하다는 것을 구체적으로 언급하지 않았습니다. @RobertKoritnik의 대답은 나를 완벽하게 제공했습니다.
Dave Land

1
덧붙여서, Bing은 검색 결과에서 "scrollintoview로 스크롤되지 않도록 상위 요소 유지"에 대한 코드 샘플을 표시하고 있습니다. :-)
Dave Land

2

Brilliant의 아이디어를 사용하여 요소가 현재 표시되지 않는 경우에만 (수직) 스크롤하는 솔루션이 있습니다. 아이디어는 뷰포트의 경계 상자와 브라우저 창 좌표 공간에 표시 할 요소를 가져 오는 것입니다. 표시되는지 확인하고 표시되지 않는 경우 필요한 거리만큼 스크롤하여 요소가 뷰포트의 상단 또는 하단에 표시되도록합니다.

    function ensure_visible(element_id)
    {
        // adjust these two to match your HTML hierarchy
        var element_to_show  = document.getElementById(element_id);
        var scrolling_parent = element_to_show.parentElement;

        var top = parseInt(scrolling_parent.getBoundingClientRect().top);
        var bot = parseInt(scrolling_parent.getBoundingClientRect().bottom);

        var now_top = parseInt(element_to_show.getBoundingClientRect().top);
        var now_bot = parseInt(element_to_show.getBoundingClientRect().bottom);

        // console.log("Element: "+now_top+";"+(now_bot)+" Viewport:"+top+";"+(bot) );

        var scroll_by = 0;
        if(now_top < top)
            scroll_by = -(top - now_top);
        else if(now_bot > bot)
            scroll_by = now_bot - bot;
        if(scroll_by != 0)
        {
            scrolling_parent.scrollTop += scroll_by; // tr.offsetTop;
        }
    }

2

@Jesco게시물에 더 많은 정보를 추가합니다 .

  • Element.scrollIntoViewIfNeeded() non-standard WebKit methodChrome, Opera, Safari 브라우저 용.
    요소가 이미 브라우저 창의 보이는 영역 내에 있으면 스크롤이 발생하지 않습니다 .
  • Element.scrollIntoView() 메서드는 호출 된 요소를 브라우저 창의 표시 영역으로 스크롤합니다.

mozilla.org scrollIntoView()링크 에서 아래 코드를 시도하십시오 . 브라우저 를 식별하기위한 게시

var xpath = '//*[@id="Notes"]';
ScrollToElement(xpath);

function ScrollToElement(xpath) {
    var ele = $x(xpath)[0];
    console.log( ele );

    var isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);
    if (isChrome) { // Chrome
        ele.scrollIntoViewIfNeeded();
    } else {
        var inlineCenter = { behavior: 'smooth', block: 'center', inline: 'start' };
        ele.scrollIntoView(inlineCenter);
    }
}

2

내 맥락에서 그는 고정 도구 모음을 화면 밖으로 밀거나 앱솔루트 버튼 옆에 입력합니다.

가장 가까운 풀을 사용합니다.

const element = this.element.nativeElement;
const table = element.querySelector('.table-container');
table.scrollIntoView({
  behavior: 'smooth', block: 'nearest'
});

1

나는 같은 문제가 있었는데 페이지 transform:translateY에 배치 한 CSS 를 제거하여 해결했습니다 footer.

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