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 offsetTop
s 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
Console.Log() Shows the Changed Value of a Variable Before the Value Actually Changes
Getting JavaScript Object Key List
Merge Two Array of Objects Based on a Key
How to Post a File from a Form With Axios
Jquery Drag/Resize with CSS Transform Scale
How to Concatenate and Minify Multiple CSS and JavaScript Files with Grunt.Js (0.3.X)
Is It Not Possible to Stringify an Error Using Json.Stringify
Black and White Text Based on Background Image with CSS
Toggle Visibility Property of Div
Chrome: Timeouts/Interval Suspended in Background Tabs
How to Get Element by Class in JavaScript
How to Use Setinterval and Clearinterval
Difference Between Variable Declaration Syntaxes in JavaScript (Including Global Variables)
Iterating Over Result of Getelementsbyclassname Using Array.Foreach
Use :Hover to Modify the CSS of Another Class