developer tip

scrollIntoView 너무 멀리 스크롤

copycodes 2020. 11. 19. 21:39
반응형

scrollIntoView 너무 멀리 스크롤


div가있는 테이블 행을 포함하는 스크롤 막대가 데이터베이스에서 동적으로 생성되는 페이지가 있습니다. 각 표 행은 동영상 플레이어 옆의 YouTube 재생 목록에서 볼 수있는 것과 같은 링크처럼 작동합니다.

사용자가 페이지를 방문하면 해당 옵션이 스크롤 div의 맨 위로 이동해야합니다. 이 기능이 작동 중입니다. 문제는 그것이 너무 멀리 가고 있다는 것입니다. 그들이 켜져있는 옵션처럼 약 10px가 너무 높습니다. 따라서 페이지를 방문하고 URL을 사용하여 선택한 옵션을 식별 한 다음 해당 옵션을 스크롤 div의 맨 위로 스크롤합니다. 참고 : 이것은 창의 스크롤 막대가 아니라 스크롤 막대가있는 div입니다.

이 코드를 사용하여 선택한 옵션을 div의 맨 위로 이동합니다.

var pathArray = window.location.pathname.split( '/' );

var el = document.getElementById(pathArray[5]);

el.scrollIntoView(true);

div의 맨 위로 이동하지만 약 10 픽셀이 너무 멀어집니다. 누구든지 그것을 고치는 방법을 알고 있습니까?


약 10px이면 포함하는 div의 스크롤 오프셋을 다음과 같이 수동으로 조정할 수 있다고 생각합니다 .

el.scrollIntoView(true);
document.getElementById("containingDiv").scrollTop += 10;

두 단계로 수행 할 수 있습니다.

el.scrollIntoView(true);
window.scrollBy(0, -10); // Adjust scrolling with a negative value here

절대 방법으로 위치 앵커

이를 수행하는 또 다른 방법은 오프셋으로 스크롤하는 대신 페이지에서 원하는 위치에 앵커를 정확히 배치하는 것입니다. 각 요소를 더 잘 제어 할 수 있으며 (예 : 특정 요소에 대해 다른 오프셋을 원하는 경우) 브라우저 API 변경 / 차이에 더 저항 할 수 있습니다.

<div id="title-element" style="position: relative;">
  <div id="anchor-name" style="position: absolute; top: -100px; left: 0" />
</div>

이제 오프셋은 요소에 대해 -100px로 지정됩니다. 코드 재사용을 위해이 앵커를 생성하는 함수를 생성하거나 React와 같은 최신 JS 프레임 워크를 사용하는 경우 앵커를 렌더링하는 구성 요소를 생성하여이를 수행하고 각 요소에 대한 앵커 이름과 정렬을 전달합니다. 동일하지 않습니다.

그런 다음 사용하십시오.

const element = document.getElementById('anchor-name')
element.scrollIntoView({ behavior: 'smooth', block: 'start' });

100px의 오프셋으로 부드러운 스크롤을 위해.


적절한 위치로 부드럽게 스크롤

정확한 y 좌표를 얻고 사용window.scrollTo({top: y, behavior: 'smooth'})

const id = 'profilePhoto';
const yOffset = -10; 
const element = document.getElementById(id);
const y = element.getBoundingClientRect().top + window.pageYOffset + yOffset;

window.scrollTo({top: y, behavior: 'smooth'});

이것은 Chrome에서 나를 위해 작동합니다 (부드러운 스크롤링과 타이밍 해킹 없음)

요소를 이동하고 스크롤을 시작한 다음 뒤로 이동합니다.

요소가 이미 화면에있는 경우 눈에 보이는 "팝핑"이 없습니다.

pos = targetEle.style.position;
top = targetEle.style.top;
targetEle.style.position = 'relative';
targetEle.style.top = '-20px';
targetEle.scrollIntoView({behavior: 'smooth', block: 'start');
targetEle.style.top = top;
targetEle.style.position = pos;

옵션을 사용할 수도 있습니다.element.scrollIntoView()

el.scrollIntoView(
  { 
    behavior: 'smooth', 
    block: 'start' 
  },
);

대부분의 브라우저가 지원하는


이전 답변을 바탕으로 Angular5 프로젝트에서 이것을 수행하고 있습니다.

시작 :

// el.scrollIntoView(true);
el.scrollIntoView({
   behavior: 'smooth',
   block: 'start'
});
window.scrollBy(0, -10); 

그러나 이것은 몇 가지 문제를 일으키고 다음과 같이 scrollBy ()에 대한 setTimeout이 필요했습니다.

//window.scrollBy(0,-10);
setTimeout(() => {
  window.scrollBy(0,-10)
  }, 500);

MSIE11 및 Chrome 68+에서 완벽하게 작동합니다. 나는 FF에서 테스트하지 않았습니다. 500ms는 제가 할 수있는 가장 짧은 지연이었습니다. 부드러운 스크롤이 아직 완료되지 않았기 때문에 때때로 아래로 내려가는 데 실패했습니다. 자신의 프로젝트에 맞게 조정하십시오.

이 간단하지만 효과적인 솔루션 을 위해 Fred727 에게 +1하십시오 .


DOM에서 모두 동일한 수준에 있고 클래스 이름이 "scroll-with-offset"인 div로 스크롤하려는 경우이 CSS가 문제를 해결합니다.

.scroll-with-offset {    
  padding-top: 100px;
  margin-bottom: -100px;
}

페이지 상단으로부터의 오프셋은 100px입니다. block : 'start'에서 의도 한 대로만 작동합니다.

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

What's happening is that the divs' top point is at the normal location but their inner contents start 100px below the normal location. That's what padding-top:100px is for. margin-bottom: -100px is to offset the below div's extra margin. To make the solution complete also add this CSS to offset the margins/paddings for the top-most and bottom-most divs:

.top-div {
  padding-top: 0;
}
.bottom-div {
  margin-bottom: 0;
}

I've got this and it works brilliantly for me:

// add a smooth scroll to element
scroll(el) {
el.scrollIntoView({
  behavior: 'smooth',
  block: 'start'});

setTimeout(() => {
window.scrollBy(0, -40);
}, 500);}

Hope it helps.


My main idea is creating a tempDiv above the view which we want to scroll to. It work well without lagging in my project.

scrollToView = (element, offset) => {
    var rect = element.getBoundingClientRect();
    var targetY = rect.y + window.scrollY - offset;

    var tempDiv;
    tempDiv = document.getElementById("tempDiv");
    if (tempDiv) {
        tempDiv.style.top = targetY + "px";
    } else {
        tempDiv = document.createElement('div');
        tempDiv.id = "tempDiv";
        tempDiv.style.background = "#F00";
        tempDiv.style.width = "10px";
        tempDiv.style.height = "10px";
        tempDiv.style.position = "absolute";
        tempDiv.style.top = targetY + "px";
        document.body.appendChild(tempDiv);
    }

    tempDiv.scrollIntoView({ behavior: 'smooth', block: 'start' });
}

Example using

onContactUsClick = () => {
    this.scrollToView(document.getElementById("contact-us"), 48);
}

Hope it help


Most simple solution that works for me:

 $('html, body').animate({ scrollTop: $(yourElement).offset().top - 20}, 800);

Based on the answer of Arseniy-II: I had the Use-Case where the scrolling entity was not window itself but a inner Template (in this case a div). In this scenario we need to set an ID for the scrolling container and get it via getElementById to use its scrolling function:

<div class="scroll-container" id="app-content">
  ...
</div>
const yOffsetForScroll = -100
const y = document.getElementById(this.idToScroll).getBoundingClientRect().top;
const main = document.getElementById('app-content');
main.scrollTo({
    top: y + main.scrollTop + yOffsetForScroll,
    behavior: 'smooth'
  });

Leaving it here in case someone faces a similar situation!

참고URL : https://stackoverflow.com/questions/24665602/scrollintoview-scrolls-just-too-far

반응형