Scrollintoview() Causing the Whole Page to Move

ScrollIntoView() causing the whole page to move

You could use scrollTop instead of scrollIntoView():

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

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

If there's more than one scrollable element that you want to scroll, you'll need to change the scrollTop of each one individually, based on the offsetTops of the intervening elements. This should give you the fine-grained control to avoid the problem you're having.

EDIT: offsetTop isn't necessarily relative to the parent element - it's relative to the first positioned ancestor. If the parent element isn't positioned (relative, absolute or fixed), you may need to change the second line to:

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

scrollIntoView whole page shifting down

There is related question to that

You could use scrollTo function of the parent element to scroll to specific child element.

Example

const { useState, useEffect, useRef } = React;

const App = () => {

const [list, setList] = useState([]);

const [keywords, setKeywords] = useState([]);

const refs = useRef(null);

const parentRef = useRef(null);



useEffect(() => {

const newList = Array(25).fill(0).map((pr, index) => String.fromCharCode(65 + index));

const newKeywords = newList.flatMap(pr => [pr, ...newList.map(npr => pr + npr)]);



refs.current = newList.reduce((acc, letter) => {

acc[letter] = React.createRef();

return acc;

}, {});



setList(newList);

setKeywords(newKeywords);

}, [])



const onClick = ({target: {dataset: {letter}}}) => {

const element = refs.current[letter].current;

const parent = parentRef.current;



const onScroll = () => {

const relativeTop = window.scrollY > parent.offsetTop ? window.scrollY : parent.offsetTop



parent.scrollTo({

behavior: "smooth",

top: element.offsetTop - relativeTop

});

}



window.removeEventListener("scroll", onScroll);

window.addEventListener("scroll", onScroll);



onScroll();



/*

element.scrollIntoView({

behavior: "smooth",

block: "start",

inline: "start",

})

*/

}



const tryAssignRef = (letter) => {

return list.indexOf(letter) > -1 ? {ref: refs.current[letter]} : {};

}

/// ...{ref: {refs.current['A']}}

return <div className="container">

<div className="header">

</div>

<div className="body">

<div className="left">

<div className="letters">{list.map(pr => <div className="letter" onClick={onClick} data-letter={pr} key={pr}>{pr}</div>)}</div>

<div ref={parentRef} className="keywords">{keywords.map(pr => <div {...tryAssignRef(pr)} key={pr}>{pr}</div>)}</div>

</div>

<div className="right">

</div>

</div>

</div>

}

ReactDOM.render(

<App />,

document.getElementById('root')

);
.container, .body, .left {

display: flex;

}

.container {

flex-direction: column;

}

.header {

flex: 0 0 100px;

border: 1px solid black;

}

.body {

height: 1000px;

}

.left {

flex: 1;

}

.right {

flex: 2;

}

.left {

justify-content: space-between;

}

.letter {

padding: 2px 0;

cursor: pointer;

}

.letters, .keywords {

padding: 0 10px;

}

.keywords {

overflow-y: scroll;

}
<script src="https://unpkg.com/react/umd/react.development.js"></script>

<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>

<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

<div id="root"></div>

scrollIntoView() shifting the complete page

Just call scrollIntoView() with the parameter false to indicate that it should not be scrolled to the top.

See the description for Element.scrollIntoView() on MDN for more info.

The reason why the JSFiddle page is scrolled down is that scrollIntoView() scrolls all scrollable ancestor elements to display the element you called scrollIntoView() on. And because the <body> of the page is actually higher than the viewport but only scrolling is hidden via overflow: hidden;, it scrolls the page down trying to align the p element with the top.

Here's a simple example of this behavior:

File scroll.html:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Main page</title>
<style type="text/css">
html, body {
height: 120%;
width: 100%;
overflow: hidden;
}

header {
height: 100px;
width: 100%;
background-color: yellow;
}

iframe {
height: 100px;
width: 300px;
}
</style>
</head>
<body>
<header></header>
<iframe src="scroll2.html"></iframe>
</body>
</html>

File scroll2.html:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Scrolling <iframe></title>
<script type="text/javascript">
function scrollLastParagraphIntoView() {
var lastParagraph = document.getElementById("p10");
lastParagraph.scrollIntoView();
}
</script>
</head>
<body>
<button onclick="scrollLastParagraphIntoView()">Scroll last paragraph into view</button>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
<p>Paragraph 3</p>
<p>Paragraph 4</p>
<p>Paragraph 5</p>
<p>Paragraph 6</p>
<p>Paragraph 7</p>
<p>Paragraph 8</p>
<p>Paragraph 9</p>
<p id="p10">Paragraph 10</p>
</body>
</html>

When you click the Scroll last paragraph into view button, the whole page will be scrolled so that the paragraph is displayed at the top of the viewport.

Javascript scrollIntoView only in immediate parent

I think you're looking for a combination of scrollTop and scrollHeight. You can use the first to set where you want the div to scroll to, and the second to get the height of all the info in the div:

var scrollyDiv = document.getElementById("container");

scrollyDiv.scrollTop = scrollyDiv.scrollHeight

setInterval(() => {

var textnode = document.createElement("P");

textnode.innerHTML = "Whatever"

scrollyDiv.appendChild(textnode);

scrollyDiv.scrollTop = scrollyDiv.scrollHeight

}, 1000)
#container {

height: 200px;

overflow-y: scroll;

}

#big-content {

height: 400px;

background-color: green;

}
<div id="container">

<div id="big-content"></div>

<p>The bottom</p>

</div>


Related Topics



Leave a reply



Submit