I'm attempting to create a grid system where the items in the grid can be moved programatically. When moving a grid item on the Y axis (by updating its grid-row
property), the document scrolls to keep the item in the same visual location on in the viewport.
This is both undesirable and confusing. I would like the page to remain in its current location and only move the item down on the page.
I have made a very minimal example of this behaviour. If you scroll the viewport down slightly so that the top of the grid item is occluded by the top of the viewport, then press upon the +
next to Y:
, you will likely experience this issue. Curiously the page does not scroll horizontally when increasing the X
position.
(It might be a good idea to run the snippet below in full screen to experience the issue)
let y = 0;
let x = 0;
const item = document.getElementById("item");
const plusY = document.getElementById("plusY");
const minusY = document.getElementById("minusY");
const plusX = document.getElementById("plusX");
const minusX = document.getElementById("minusX");
const updatePosition = (newY, newX) => {
if (newY < 0) {
newY = 9;
}
y = Math.abs(newY) % 10;
if (newX < 0) {
newX = 9;
}
x = Math.abs(newX) % 10;
item.style = `grid-column: ${x + 1} / span 1; grid-row: ${y + 1} / span 1`;
};
plusY.addEventListener("click", () => {
updatePosition(y + 1, x);
});
minusY.addEventListener("click", () => {
updatePosition(y - 1, x);
});
plusX.addEventListener("click", () => {
updatePosition(y, x + 1);
});
minusX.addEventListener("click", () => {
updatePosition(y, x - 1);
});
*,
*:before,
*:after {
box-sizing: border-box;
}
body {
background-color: black;
color: white;
}
#grid {
padding: 20px;
background-color: white;
display: grid;
width: 885px;
height: 885px;
gap: 5px;
grid-template-columns: repeat(10, 80px);
grid-template-rows: repeat(10, 80px);
}
#item {
border: 1px solid black;
grid-column: 1 / span 1;
grid-row: 1 / span 1;
color: black;
}
.buttons {
display: flex;
justify-content: center;
width: 800px;
}
<html>
<body>
<div id="grid">
<div id="item">Test</div>
</div>
<div class="buttons">
Y:
<button id="plusY">+</button>
<button id="minusY">-</button>
</div>
<div class="buttons">
X:
<button id="plusX">+</button>
<button id="minusX">-</button>
</div>
<div style="width: 4000px; height: 2000px"></div>
</body>
</html>
This issue occurs in both Chrome and Firefox, but strangely not within Safari.
Can this issue be quashed, have I misconfigured CSS grid in some manner, or have I come across a strange browser bug?
Assistance would be much appreciated, I'm incredibly stumped and use of CSS grid was to be a very important part of the project that I was working on when I came across this issue.
webstrand of the cascading-style-sheets Discord has pointed me in the right direction!
The issue appears to have been with scroll anchoring! He linked this page on the topic, which mentions both a way to determine what element is being used as a scroll anchor. In this case I determined that the text was being used to scroll anchor.
Utilising the suggested overflow-anchor: none;
CSS property upon the grid or the items has stopped the unexpected scrolling!