La propiedad “history.scrollRestoration = manual” no evita que Safari restaure la posición del desplazamiento.
Supongamos que estableces window.history.scrollRestoration = "manual"
en una página web.
En Chrome/Firefox
Cada vez que haces clic en un enlace, la página se desplaza a la posición del elemento vinculado, y cada vez que retrocedes/avanzas a través del historial, la posición de desplazamiento permanece igual pero se actualiza la parte de fragmento de la URL (#sectionXYZ).
En Safari
Cada vez que haces clic en un enlace no sucede nada, y cada vez que retrocedes/avanzas a través del historial, la página se desplaza a la posición del elemento vinculado al fragmento de la página actual (#sectionXYZ).
Cuando digo “navegar a través del historial” me refiero a utilizar window.history.back()
, window.history.forward()
y window.history.go(N)
o utilizando los botones de volver/avanzar del navegador.
En el siguiente ejemplo hay 2 botones (azul y rojo) que agregarán 2 estados diferentes al historial cuando se hagan clic.
Intenta hacer clic varias veces y retroceder/avanzar a través del historial para replicar los comportamientos que describí.
¿Por qué Safari restaura la posición de desplazamiento de la página incluso cuando history.scrollRestoration
está establecido en manual
? ¿Existe alguna manera de evitar este comportamiento como lo hacen Chrome y Firefox?
html,body,div {
height: 100vh;
width: 100vw;
margin: 0;
overflow-x: hidden;
}
#nav {
display:flex;
justify-content:center;
position:fixed;
width: 100%;
height: 100px;
background: rgba(0,0,0,0.7);
}
nav > a {
display:grid;
justify-content:center;
align-items:center;
text-decoration:none;
color:white;
width: 30%;
height: 90%;
font-size:120%;
cursor:pointer;
}
#a1, #blue{
background-color:blue;
}
#a2, #red {
background-color:red;
}
<body>
<nav id = "nav">
<a id = "a1" href = "#blue">AZUL</a>
<a id = "a2" href = "#red">ROJO</a>
</nav>
<div id = "blue"></div>
<div id = "red"></div>
<script>
window.history.scrollRestoration = "manual";
window.addEventListener("popstate", () => {
console.log("blue: ", document.getElementById("blue").getBoundingClientRect());
console.log("red: ", document.getElementById("red").getBoundingClientRect());
});
document.getElementById("a1").addEventListener("click", () => window.history.pushState("blue", "", "#blue"));
document.getElementById("a2").addEventListener("click", () => window.history.pushState("red", "", "#red"));
</script>
</body>
davy.ai
¿Por qué Safari restaura la posición de desplazamiento de la página incluso cuando
history.scrollRestoration
se establece enmanual
? ¿Hay alguna forma de evitar este comportamiento como lo hacen Chrome y Firefox?En Safari, cuando
history.scrollRestoration
se establece enmanual
, todavía restaura la posición de desplazamiento de la página al navegar hacia atrás/adelante a través del historial. Esto se debe a que Safari considera que lascrollPosition
es parte del estado del historial, por lo que lo almacena y lo restaura junto con el resto del estado.Para evitar este comportamiento, se puede utilizar el método
history.replaceState()
para reemplazar el estado actual por uno nuevo que tenga una posición de desplazamientonull
. Esto eliminará efectivamente la posición de desplazamiento del estado de la historia, haciendo que Safari se comporte como Chrome y Firefox.Aquí hay un ejemplo de cómo modificar el fragmento de código original para evitar que Safari restaure la posición de desplazamiento:
La función
setNullScrollState()
crea un nuevo objeto de estado de la historia que es igual al actual, excepto que su propiedadscrollPosition
es un objeto con los valoresx: 0
ey: 0
, y reemplaza el estado actual por este nuevo usandohistory.replaceState()
. Cada vez que el usuario navega hacia atrás/adelante, se llama al controlador de eventospopstate
, que registra la posición de los elementosblue
yred
(con fines de demostración), y luego llama asetNullScrollState()
para restablecer la posición de desplazamiento a 0.