Desplácese suavemente a div específico al hacer clic

94

Lo que estoy tratando de hacer es que si hace clic en un botón, se desplace hacia abajo (suavemente) a un div específico en la página.

Lo que necesito es que si haces clic en el botón, se desplaza suavemente hasta el div 'segundo'.

.first {
    width: 100%;
    height: 1000px;
    background: #ccc;
}

.second {
    width: 100%;
    height: 1000px;
    background: #999;
}
<div class="first"><button type="button">Click Me!</button></div>
<div class="second">Hi</div>

Erik Fischer
fuente
Puede probar este complemento. Aunque este es mucho más fácil de usar. Básicamente, solo tiene que vincular el archivo JS en el encabezado y cambiar su marcado de manera adecuada para que funcione.
joshrathke
1
esto debería ayudarlo :: stackoverflow.com/questions/3432656/…
Sudhir Bastakoti

Respuestas:

178

hacer:

$("button").click(function() {
    $('html,body').animate({
        scrollTop: $(".second").offset().top},
        'slow');
});

Jsfiddle actualizado

Sudhir Bastakoti
fuente
¿Estás usando javaScript aquí o jQuery?
1
@FahadUddin su jQuery.
Sudhir Bastakoti
@SudhirBastakoti: ¿Por qué JsFiddle no ha incluido la biblioteca jquery en esa página?
@Sudhir Bastakoti, pero muchos usuarios se quejan de que el desplazamiento no es fluido.
Maulik
40

Hay muchos ejemplos de desplazamiento suave utilizando bibliotecas JS como jQuery, Mootools, Prototype, etc.

El siguiente ejemplo está en JavaScript puro. Si no tiene jQuery / Mootools / Prototype en la página o no desea sobrecargar la página con bibliotecas JS pesadas, el ejemplo será de ayuda.

http://jsfiddle.net/rjSfP/

Parte HTML:

<div class="first"><button type="button" onclick="smoothScroll(document.getElementById('second'))">Click Me!</button></div>
<div class="second" id="second">Hi</div>

Parte CSS:

.first {
    width: 100%;
    height: 1000px;
    background: #ccc;
}

.second {
    width: 100%;
    height: 1000px;
    background: #999;
}

Parte JS:

window.smoothScroll = function(target) {
    var scrollContainer = target;
    do { //find scroll container
        scrollContainer = scrollContainer.parentNode;
        if (!scrollContainer) return;
        scrollContainer.scrollTop += 1;
    } while (scrollContainer.scrollTop == 0);

    var targetY = 0;
    do { //find the top of target relatively to the container
        if (target == scrollContainer) break;
        targetY += target.offsetTop;
    } while (target = target.offsetParent);

    scroll = function(c, a, b, i) {
        i++; if (i > 30) return;
        c.scrollTop = a + (b - a) / 30 * i;
        setTimeout(function(){ scroll(c, a, b, i); }, 20);
    }
    // start scrolling
    scroll(scrollContainer, scrollContainer.scrollTop, targetY, 0);
}
nico
fuente
Estoy usando esto y funciona muy bien. Sin embargo, ¿cómo hago que el desplazamiento sea más lento?
jamescampbell
¿Alguna idea de cómo agregar desplazamiento para la barra de navegación fija en este código? Aquí hay un ejemplo que hice violín
Plavookac
3
Sigue siendo útil después de 5 años
Owaiz Yusufi
9

Jugué un poco con la respuesta de Nico y me sentí nervioso. Investigué un poco y encontré window.requestAnimationFramecuál es una función que se llama en cada ciclo de repintado. Esto permite una animación más limpia. Todavía estoy tratando de perfeccionar los buenos valores predeterminados para el tamaño del paso, pero para mi ejemplo, las cosas se ven bastante bien con esta implementación.

var smoothScroll = function(elementId) {
    var MIN_PIXELS_PER_STEP = 16;
    var MAX_SCROLL_STEPS = 30;
    var target = document.getElementById(elementId);
    var scrollContainer = target;
    do {
        scrollContainer = scrollContainer.parentNode;
        if (!scrollContainer) return;
        scrollContainer.scrollTop += 1;
    } while (scrollContainer.scrollTop == 0);

    var targetY = 0;
    do {
        if (target == scrollContainer) break;
        targetY += target.offsetTop;
    } while (target = target.offsetParent);

    var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP,
                                 (targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS);

    var stepFunc = function() {
        scrollContainer.scrollTop =
            Math.min(targetY, pixelsPerStep + scrollContainer.scrollTop);

        if (scrollContainer.scrollTop >= targetY) {
            return;
        }

        window.requestAnimationFrame(stepFunc);
    };

    window.requestAnimationFrame(stepFunc);
}
Ned Rockson
fuente
1
@Alfonso Ver arriba. Esta es simplemente una versión optimizada del código de nico en una respuesta anterior.
Ned Rockson
@NedRockson No funciona para mí da el mensaje de consola "Uncaught TypeError: No se puede leer la propiedad 'parentNode' de null" pero el código de nico está funcionando. ¿Qué debo hacer para poder aplicar una animación limpia?
Kartik Watwani
@KartikWatwani Eso significa que en la lectura de línea scrollContainer = scrollContainer.parentNode, scrollContainer es nulo. Esto probablemente signifique que no está pasando lo correcto elementIdal llamar a esta función. También es posible que esté ejecutando este script en una página donde ese elementId no existe.
Ned Rockson
@NedRockson Si elementIdhubiera estado equivocado, habría recibido el mismo error en el caso del ejemplo de @nico, pero en ese caso, el desplazamiento funciona, pero no sin problemas.
Kartik Watwani
Usar en requestAnimationFramelugar de setTimeoutes el camino a seguir. setTimeoutno debe usarse para animaciones.
tsnkff
2

Tomé la versión de Ned Rockson y la ajusté para permitir desplazamientos hacia arriba también.

var smoothScroll = function(elementId) {
  var MIN_PIXELS_PER_STEP = 16;
  var MAX_SCROLL_STEPS = 30;
  var target = document.getElementById(elementId);
  var scrollContainer = target;
  do {
    scrollContainer = scrollContainer.parentNode;
    if (!scrollContainer) return;
    scrollContainer.scrollTop += 1;
  } while (scrollContainer.scrollTop === 0);

  var targetY = 0;
  do {
    if (target === scrollContainer) break;
    targetY += target.offsetTop;
  } while (target = target.offsetParent);

  var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP,
    Math.abs(targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS);

  var isUp = targetY < scrollContainer.scrollTop;

  var stepFunc = function() {
    if (isUp) {
      scrollContainer.scrollTop = Math.max(targetY, scrollContainer.scrollTop - pixelsPerStep);
      if (scrollContainer.scrollTop <= targetY) {
        return;
      }
    } else {
        scrollContainer.scrollTop = Math.min(targetY, scrollContainer.scrollTop + pixelsPerStep);

      if (scrollContainer.scrollTop >= targetY) {
        return;
      }
    }

    window.requestAnimationFrame(stepFunc);
  };

  window.requestAnimationFrame(stepFunc);
};
Marek Lisý
fuente
2

Puede usar CSS básico para lograr un desplazamiento suave

html {
  scroll-behavior: smooth;
}
Sardorbek Khalimov
fuente
0

Ned Rockson básicamente responde a esta pregunta. Sin embargo, hay un defecto fatal en su solución. Cuando el elemento de destino está más cerca de la parte inferior de la página que la altura de la ventana gráfica, la función no alcanza su declaración de salida y atrapa al usuario en la parte inferior de la página. Esto se resuelve simplemente limitando el recuento de iteraciones.

var smoothScroll = function(elementId) {
    var MIN_PIXELS_PER_STEP = 16;
    var MAX_SCROLL_STEPS = 30;
    var target = document.getElementById(elementId);
    var scrollContainer = target;
    do {
        scrollContainer = scrollContainer.parentNode;
        if (!scrollContainer) return;
        scrollContainer.scrollTop += 1;
    } while (scrollContainer.scrollTop == 0);

    var targetY = 0;
    do {
        if (target == scrollContainer) break;
        targetY += target.offsetTop;
    } while (target = target.offsetParent);

    var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP,
                                 (targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS);

    var iterations = 0;
    var stepFunc = function() {
        if(iterations > MAX_SCROLL_STEPS){
            return;
        }
        scrollContainer.scrollTop =
            Math.min(targetY, pixelsPerStep + scrollContainer.scrollTop);

        if (scrollContainer.scrollTop >= targetY) {
            return;
        }

        window.requestAnimationFrame(stepFunc);
    };

    window.requestAnimationFrame(stepFunc);
}
Programador pasivo
fuente