Tengo un bloque que aparece después de desplazarme 200 px en la página.
const navShareLink = document.getElementById('navShareLink'); document.addEventListener('scroll', function(e) { if(window.scrollY > 200 && window.innerWidth > 576) { navShareLink.style.display = "block"; } else { navShareLink.style.display = "none"; } });
.article-wrapper { min-height: 200vh; } .article-wrapper p:first-of-type { margin-top: 0; } footer { min-height: 100vh; background-color: #eee; } .sidemenu-shares { z-index: 999; display: flex; flex-direction: column; align-items: center; height: 100%; justify-content: center; position: fixed; top: 0; right: 0; flex-wrap: nowrap; gap: 40px; } .rectangle { z-index: 998; transition: opacity 0.5s; padding: 5px; height: 106px; width: 23px; background-color: rgba(0, 0, 0, 0.1); border-radius: 24px; }
<div class="article-wrapper"> <div class="sidemenu-shares"> <div id="navShareLink" class="rectangle"> </div> </div> <div class="main-banner"> <h1>Title</h1> </div> <div>Main content...</div> <div>Main content...</div> <div>Main content...</div> <div>Main content...</div> <div>Main content...</div> <div>Main content...</div> <div>Main content...</div> <div>Main content...</div> <div>Main content...</div> </div> <footer> Footer... </footer>
Pero cuando llega al final de la página donde está el pie de página, necesito que se oculte para que no se suba al pie de página.
Es fácil de hacer si la página tiene la misma altura, pero para mí puede ser 2500 px o 5000 px
¿Es posible de alguna manera contar los píxeles en orden inverso, pero no desde el principio de la página, sino digamos 300px desde el final?
Traté de obtener la altura de toda la página y restar 300
Usé document.documentElement.scrollHeight
. Pensé que obtendría un valor digital como 4500, pero al final obtengo el resultado de este valor en una ventana emergente cuando abro la página.
Alternativamente, de alguna manera puedo ocultar este bloque cuando toca el pie de página, ¿es posible hacerlo de alguna manera?
Esta API le permite observar elementos en su página e invocar código en función de su posición en relación con su ventana gráfica actual.
Ejemplo:
const callback = (entries, observer) => { entries.forEach(entry => { // Each entry describes an intersection change for one observed // target element: // entry.boundingClientRect // entry.intersectionRatio // entry.intersectionRect // entry.isIntersecting <- This is what you usually look out for // entry.rootBounds // entry.target // entry.time if (entry.isIntersecting) { document.getElementById('navShareLink').style.display = 'none'; }); };
const options = { root: document.body, // This specifies a margin around the target (basically changes the size of the target) - can be negative rootMargin: '0px 0px 0px 0px', // This specifies how much of the target needs to be in the viewport to qualify as 'intersecting' (1 === 100%) threshold: 1.0 } const observer = new IntersectionObserver(callback, options);
const target = document.querySelector('footer'); observer.observe(target);
Un observador puede observar un número arbitrario de objetivos. Por lo general, es la forma más eficiente de manejar este tipo de cosas.
Los controladores de eventos de desplazamiento generalmente se activan con mucha frecuencia y, por lo tanto, son bastante ineficientes. Si usa controladores de desplazamiento, al menos debería eliminarlos .
No entendí muy bien lo que quieres, pero en caso de que quieras que la barra lateral sea pegajosa y cuando bajes al pie de página está arriba de ese bloque, tienes que sacar el código de la barra lateral de div class="main-content" como eso
/* The important part: */ .sidebar { float: right; position: sticky; top: 8px; /* This should match the top margin/padding on the body */ } /* Cosmetics for the demo: */ .main-content { min-height: 200vh; } .main-content p:first-of-type { margin-top: 0; } .sidebar { width: 25vw; min-height: 25vh; background-color: #a00; } footer { min-height: 100vh; background-color: #eee; } html { margin: 0; padding: 0; } body { margin: 0; padding: 8px; }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <!-- here sidebar --> <div class="sidebar"> Sidebar... </div> <div class="main-content"> <div>Main content...</div> <div>Main content...</div> <div>Main content...</div> <div>Main content...</div> <div>Main content...</div> </div> <footer> Footer... </footer> </body> </html>
Para resolver esto, necesitamos obtener las propiedades apropiadas de los elementos clave:
document.body.scrollHeight
: aquí html tiene la barra de desplazamiento y el cuerpo se desborda. scrollHeight da la altura de todo el documento con desbordamiento.footer.offsetHeight
- altura real del pie de página.wrapper.getBoundingClientRect().y
- esto da la posición y del contenedor cuando nos desplazamos hacia abajo. Es negativo porque el envoltorio sube.Las matemáticas restantes son simples:
var sideMenu, footer, wrapper, nsl; document.addEventListener("DOMContentLoaded", init, false); function check() { var range = document.body.scrollHeight - footer.offsetHeight; var position = (nsl.offsetHeight + nsl.getBoundingClientRect().y - wrapper.getBoundingClientRect().y).toFixed(1); nsl.innerText = '\n Range: ' + range + '\n Position: ' + position; if (window.scrollY > 200 && (range > position)) { nsl.style.visibility = "visible"; } else { nsl.style.visibility = "hidden"; } }; function init() { sideMenu = document.getElementById('sideMenu'); footer = document.getElementById('footer'); wrapper = document.getElementById('wrapper'); nsl = document.getElementById('navShareLink'); window.onscroll = check; check(); }
.article-wrapper { min-height: 200vh; position: relative; top: 0; left: 0; } .article-wrapper p:first-of-type { margin-top: 0; } footer { min-height: 100vh; background-color: lightskyblue; } .sidemenu-shares { z-index: 999; display: flex; flex-direction: column; align-items: center; height: 100%; justify-content: center; position: fixed; top: 0; right: 0; flex-wrap: nowrap; gap: 40px; } .rectangle { z-index: 998; transition: opacity 0.5s; padding: 5px; height: 106px; width: 123px; background-color: rgba(200, 0, 0, 0.1); border-radius: 24px; } .content { height: 50px; border: 1px dotted gray; }
<div id="wrapper" class="article-wrapper"> <div id='sideMenu' class="sidemenu-shares"> <div id="navShareLink" class="rectangle"> </div> </div> <div class="main-banner"> <h1>Title</h1> </div> <div class='content'>Main content...</div> <div class='content'>Main content...</div> <div class='content'>Main content...</div> <div class='content'>Main content...</div> <div class='content'>Main content...</div> <div class='content'>Main content...</div> <div class='content'>Main content...</div> <div class='content'>Main content...</div> <div class='content'>Main content...</div> </div> <footer id='footer'> Footer... </footer>
Compruebe la salida en el modo de página completa.