¿Cómo me desplazo a un elemento usando JavaScript?

152

Estoy tratando de mover la página a un <div>elemento.

He intentado el siguiente código en vano:

document.getElementById("divFirst").style.visibility = 'visible';
document.getElementById("divFirst").style.display = 'block';
C..
fuente
1
visibilityy displayse usan para hacer que los elementos (in) sean visibles. ¿Desea desplazar el div en la pantalla?
Lekensteyn
¿Qué tipo de enfoque? ¿El mismo enfoque que tiene cuando se tabula a través de elementos de formulario o se enfoca en el sentido de resaltar el elemento de alguna manera? Lo único que debe hacer es mostrar el elemento, lo que no tiene efecto si ya se muestra.
Felix Kling
Enfoque como desplazamiento a la vista?
epascarello
12
el.scrollIntoView(true)
Blazemonger

Respuestas:

123

Puedes usar un ancla para "enfocar" el div. Es decir:

<div id="myDiv"></div>

y luego use el siguiente javascript:

// the next line is required to work around a bug in WebKit (Chrome / Safari)
location.href = "#";
location.href = "#myDiv";
Nikoloff
fuente
9
Chrome (WebKit) tiene un error que hace que la página no se desplace una vez que se establece el ancla. Uso: location.href="#";location.href="#myDiv". id="myDiv"Se prefiere usar name="myDiv"y también funciona.
Lekensteyn
8
Tuve este problema exacto, pero el "arreglo" de WebKit me causa un problema en FF 3.6.13. Funciona sin la línea "#", pero si la agrega, va a "#" y nunca intenta ir a "#myDiv". Me quedaré con la solución sin el "#", que funciona para mí ... ¡woohoo!
TimFoolery
1
Esto no funciona bien para mí porque agrega todos estos eventos de navegación al historial del navegador y no puedo volver fácilmente a la página anterior
bikeman868
Creo que 'AnhSirk Dasarp' a continuación es un mejor método para desplazar el elemento deseado a la parte superior de la pantalla visible.
Curioso101
¿Qué pasa si el desplazador está en un div interno?
Qian Chen
241

scrollIntoView funciona bien:

document.getElementById("divFirst").scrollIntoView();

referencia completa en los documentos de MDN:
https://developer.mozilla.org/en-US/docs/Web/API/Element.scrollIntoView

Schpet
fuente
11
@CameronMcCluskie es solo el extraño "scrollIntoViewOptions" (desplazamiento suave, etc.) que tiene soporte exclusivo para firefox. El uso básico que tengo en mi respuesta debería funcionar en casi cualquier cosa.
schpet
44
Confirmo, a partir del 16 de abril, también funciona en Opera y Chrome.
lvr123
2
Cuando utilice esta solución y tenga una barra de navegación fija en la parte superior, también debe tenerlo en cuenta. Una solución diferente podría ser más adecuada, como windows.scrollTo (posX, posY) con posY correctamente calculado.
Manfred
2
Trabajó en Firefox, Opera y Safari.
Jagdeep Singh
3
Aquí hay otra fuente (caniuse) para la compatibilidad del navegador descrollIntoView
The Red Pea
99

Su pregunta y las respuestas se ven diferentes. No sé si me equivoco, pero para aquellos que buscan en Google y llegan aquí, mi respuesta sería la siguiente:

  1. Mi respuesta en stackoverflow
  2. Una pregunta similar

Mi respuesta explicó:

aquí hay un javascript simple para eso

llame a esto cuando necesite desplazar la pantalla a un elemento que tenga id = "yourSpecificElementId"

window.scroll(0,findPos(document.getElementById("yourSpecificElementId")));

es decir. para la pregunta anterior, si la intención es desplazar la pantalla al div con el id 'divFirst'

el código sería: window.scroll(0,findPos(document.getElementById("divFirst")));

y necesitas esta función para trabajar:

//Finds y value of given object
function findPos(obj) {
    var curtop = 0;
    if (obj.offsetParent) {
        do {
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);
    return [curtop];
    }
}

la pantalla se desplazará a su elemento específico.

AnhSirk Dasarp
fuente
12
Esta solución tiene la ventaja de no jugar con la URL visible en la barra de navegación del navegador agregando anclas MyID.
Renaud Bompuis
2
Gracias, siento que esta debería ser la respuesta aceptada, es java-script, no HTML como la respuesta actual que no funcionaría para mí, ¡pero esto sí!
Steve Byrne
Es decir, si es lo windowque le gustaría desplazarse, no un área de visualización desbordante
WebWanderer
1
Funciona después de cambiar [curtop]al curtopfinal
goldylucks
Si no desea que coloque este elemento en la parte superior de la página, pero prefiere que se desplace para que el elemento esté en el centro de la pantalla, reste (window.screen.height/2)de findPos
Albert Renshaw
47

Para Chrome y Firefox

He estado investigando un poco esto y descubrí esto, que de alguna manera se siente como la forma más natural de hacerlo. Por supuesto, este es mi pergamino favorito personal ahora. :)

const y = element.getBoundingClientRect().top + window.scrollY;
window.scroll({
  top: y,
  behavior: 'smooth'
});

Para los partidarios de IE, Edge y Safari

Tenga en cuenta que window.scroll({ ...options })no es compatible con IE, Edge y Safari. En ese caso, lo más probable es que sea mejor usarlo element.scrollIntoView(). (Compatible con IE 6). Lo más probable es que puedas (leer: no probado) pasar opciones sin ningún efecto secundario.

Por supuesto, estos pueden incluirse en una función que se comporta según el navegador que se esté utilizando.

Cavernícola
fuente
3
Trabajando como encanto :)
midzer
1
Esta es la única solución que me funcionó con Chrome.
wkille
1
Quería tomar su solución, ya que es posible ajustar la posición (en mi caso, y-80). Parece, como var element = document.getElementById ("Div"); falta en tu ejemplo? Además, no funciona con IE11. IE11 no sabe window.scrollY: tenemos que usar window.pageYOffset en su lugar para recibir un valor. Después de cambiar eso, tuve varios errores de jquery (por no comprender), por supuesto, como la mayoría, solo en IE11. Por lo tanto, he implementado document.getElementById ("divFirst"). ScrollIntoView (); y luego $ (ventana ) .scrollTop ($ (ventana) .scrollTop () - 80); lo que funciona con todos los navegadores.
FredyWenger
No es compatible con Safari (opciones de paso awindow.scroll
goldylucks
Gracias por los comentarios, actualizo la respuesta para incluir la compatibilidad del navegador.
Hombre de las cavernas
8

Prueba esto:

var divFirst = document.getElementById("divFirst");
divFirst.style.visibility = 'visible'; 
divFirst.style.display = 'block';  
divFirst.tabIndex = "-1";  
divFirst.focus();

p.ej @:

http://jsfiddle.net/Vgrey/

Chandu
fuente
Solo quiero enfatizar que la propiedad DOM es element.tabIndexpero no element.tabindex; el segundo funciona en Firefox pero no en Chrome (al menos cuando lo probé hace algún tiempo). Por supuesto, se usa como un atributo HTML tanto tabIndexpara el tabindextrabajo (como para XHTML, tabindexdebe usarse)
Oriol
6

Para desplazarse a un elemento dado, acabo de hacer esta solución única de JavaScript a continuación.

Uso simple:

EPPZScrollTo.scrollVerticalToElementById('signup_form', 20);

Objeto del motor (puede jugar con el filtro, valores fps):

/**
 *
 * Created by Borbás Geri on 12/17/13
 * Copyright (c) 2013 eppz! development, LLC.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */


var EPPZScrollTo =
{
    /**
     * Helpers.
     */
    documentVerticalScrollPosition: function()
    {
        if (self.pageYOffset) return self.pageYOffset; // Firefox, Chrome, Opera, Safari.
        if (document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop; // Internet Explorer 6 (standards mode).
        if (document.body.scrollTop) return document.body.scrollTop; // Internet Explorer 6, 7 and 8.
        return 0; // None of the above.
    },

    viewportHeight: function()
    { return (document.compatMode === "CSS1Compat") ? document.documentElement.clientHeight : document.body.clientHeight; },

    documentHeight: function()
    { return (document.height !== undefined) ? document.height : document.body.offsetHeight; },

    documentMaximumScrollPosition: function()
    { return this.documentHeight() - this.viewportHeight(); },

    elementVerticalClientPositionById: function(id)
    {
        var element = document.getElementById(id);
        var rectangle = element.getBoundingClientRect();
        return rectangle.top;
    },

    /**
     * Animation tick.
     */
    scrollVerticalTickToPosition: function(currentPosition, targetPosition)
    {
        var filter = 0.2;
        var fps = 60;
        var difference = parseFloat(targetPosition) - parseFloat(currentPosition);

        // Snap, then stop if arrived.
        var arrived = (Math.abs(difference) <= 0.5);
        if (arrived)
        {
            // Apply target.
            scrollTo(0.0, targetPosition);
            return;
        }

        // Filtered position.
        currentPosition = (parseFloat(currentPosition) * (1.0 - filter)) + (parseFloat(targetPosition) * filter);

        // Apply target.
        scrollTo(0.0, Math.round(currentPosition));

        // Schedule next tick.
        setTimeout("EPPZScrollTo.scrollVerticalTickToPosition("+currentPosition+", "+targetPosition+")", (1000 / fps));
    },

    /**
     * For public use.
     *
     * @param id The id of the element to scroll to.
     * @param padding Top padding to apply above element.
     */
    scrollVerticalToElementById: function(id, padding)
    {
        var element = document.getElementById(id);
        if (element == null)
        {
            console.warn('Cannot find element with id \''+id+'\'.');
            return;
        }

        var targetPosition = this.documentVerticalScrollPosition() + this.elementVerticalClientPositionById(id) - padding;
        var currentPosition = this.documentVerticalScrollPosition();

        // Clamp.
        var maximumScrollPosition = this.documentMaximumScrollPosition();
        if (targetPosition > maximumScrollPosition) targetPosition = maximumScrollPosition;

        // Start animation.
        this.scrollVerticalTickToPosition(currentPosition, targetPosition);
    }
};
Geri Borbás
fuente
@codeWithMe Yap, es más como un código similar a iOS, donde la cantidad real no importa, por lo que puede seguir adelante y nombrar todo después de lo que hace / contiene. Prefiero eso a la brevedad.
Geri Borbás
5

Aquí hay una función que puede incluir un desplazamiento opcional para esos encabezados fijos. No se necesitan bibliotecas externas.

function scrollIntoView(selector, offset = 0) {
  window.scroll(0, document.querySelector(selector).offsetTop - offset);
}

Puede tomar la altura de un elemento usando JQuery y desplazarse hasta él.

var headerHeight = $('.navbar-fixed-top').height();
scrollIntoView('#some-element', headerHeight)

Actualización marzo 2018

Desplácese a esta respuesta sin usar JQuery

scrollIntoView('#answer-44786637', document.querySelector('.top-bar').offsetHeight)
Harlem Ardilla
fuente
5

Puede establecer el foco en elemento. Funciona mejor quescrollIntoView

node.setAttribute('tabindex', '-1')

node.focus()

node.removeAttribute('tabindex')

ZhenyaUsenko
fuente
Oh hombre, me salvaste el día. Probé muchas cosas, pero esta fue la única cosa que funcionó para mí y es compatible con todos los navegadores. Por cierto, creé una entrada y di 1px de alto y ancho y me centré en la entrada. Funciona muy bien. Gracias
Martian.titan
5

La mejor respuesta más corta que funciona incluso con efectos de animación:

var scrollDiv = document.getElementById("myDiv").offsetTop;
window.scrollTo({ top: scrollDiv, behavior: 'smooth'});

Si tiene una barra de navegación fija, simplemente reste su altura del valor superior, de modo que si la altura de su barra fija es 70px, la línea 2 se verá así:

window.scrollTo({ top: scrollDiv-70, behavior: 'smooth'});

Explicación: La línea 1 obtiene la posición del elemento. La línea 2 se desplaza a la posición del elemento; behaviorla propiedad agrega un efecto animado suave

DAVID AJAYI
fuente
Realmente genial, pero aún no funciona en Safari y algunos otros navegadores. Sin embargo, funciona con este polyfill github.com/iamdustan/smoothscroll . ;)
Íhor Mé
2

El enfoque se puede establecer solo en elementos interactivos ... Div solo representa una sección lógica de la página.

Quizás pueda establecer los bordes alrededor de div o cambiar su color para simular un foco. Y sí, Visiblity no es foco.

SM Kamran
fuente
1

Creo que si agrega un índice de tabulación a su div, podrá enfocarse:

<div class="divFirst" tabindex="-1">
</div>

Sin embargo, no creo que sea válido, tabindex se puede aplicar solo a un área, botón, entrada, objeto, selección y área de texto. Pero inténtalo.

Robin
fuente
1
En HTML5 tabindexes un "atributo central", que son "atributos globales" (atributos que son comunes a todos los elementos en el lenguaje HTML). Ver w3.org/TR/2011/WD-html-markup-20110113/global-attributes.html
Oriol
1

Similar a la solución de @ caveman

const element = document.getElementById('theelementsid');

if (element) {
    window.scroll({
        top: element.scrollTop,
        behavior: 'smooth',
    }) 
}
Excelencia Ilesanmi
fuente
0

Después de mirar mucho, esto es lo que finalmente funcionó para mí:

  1. Encuentra / localiza div en tu dom que tiene barra de desplazamiento. Para mí, se veía así: "div class =" table_body table_body_div "scroll_top =" 0 "scroll_left =" 0 "style =" width: 1263px; altura: 499 px; "

  2. Lo ubiqué con este xpath: // div [@ class = 'table_body table_body_div']

  3. Se utilizó JavaScript para ejecutar el desplazamiento de esta manera: (controlador JavascriptExecutor) .executeScript ("argumentos [0] .scrollLeft = argumentos [1];", elemento, 2000);

2000 es el no de píxeles que quería desplazar hacia la derecha. Use scrollTop en lugar de scrollLeft si desea desplazar su div hacia abajo.

Nota: Intenté usar scrollIntoView pero no funcionó correctamente porque mi página web tenía múltiples divs. Funcionará si solo tiene una ventana principal donde se encuentra el foco. Esta es la mejor solución que he encontrado si no quieres usar jQuery que no quería.

Anchal Agrawal
fuente
0

Un método que uso a menudo para desplazar un contenedor a su contenido.

/**
@param {HTMLElement} container : element scrolled.
@param {HTMLElement} target : element where to scroll.
@param {number} [offset] : scroll back by offset
*/
var scrollAt=function(container,target,offset){
    if(container.contains(target)){
        var ofs=[0,0];
        var tmp=target;
        while (tmp!==container) {
            ofs[0]+=tmp.offsetWidth;
            ofs[1]+=tmp.offsetHeight;
            tmp=tmp.parentNode;
        }
        container.scrollTop = Math.max(0,ofs[1]-(typeof(offset)==='number'?offset:0));
    }else{
        throw('scrollAt Error: target not found in container');
    }
};

si desea anular globalmente, también puede hacer:

HTMLElement.prototype.scrollAt=function(target,offset){
    if(this.contains(target)){
        var ofs=[0,0];
        var tmp=target;
        while (tmp!==this) {
            ofs[0]+=tmp.offsetWidth;
            ofs[1]+=tmp.offsetHeight;
            tmp=tmp.parentNode;
        }
        container.scrollTop = Math.max(0,ofs[1]-(typeof(offset)==='number'?offset:0));
    }else{
        throw('scrollAt Error: target not found in container');
    }
};
yorg
fuente
0

Debido al comportamiento "suave" no funciona en Safari, Safari ios, Explorer. Por lo general, escribo una función simple utilizando requestAnimationFrame

(function(){
    var start;
    var startPos = 0;

    //Navigation scroll page to element
    function scrollTo(timestamp, targetTop){
      if(!start) start = timestamp
      var runtime = timestamp - start
      var progress = Math.min(runtime / 700, 1)

      window.scroll(0, startPos + (targetTop * progress) )

      if(progress >= 1){
        return;
      }else {
        requestAnimationFrame(function(timestamp){
            scrollTo(timestamp, targetTop)
        })
      }
   };

  navElement.addEventListener('click', function(e){

    var target = e.target  //or this 
    var targetTop = _(target).getBoundingClientRect().top
    startPos = window.scrollY

    requestAnimationFrame(function(timestamp){
        scrollTo(timestamp, targetTop)
    })
  }

})();
Brad Vanderbush
fuente
-1

En caso de que quiera usar html, puede usar esto:

a href="samplewebsite.com/subdivision.html#id

y conviértalo en un enlace html al identificador de elemento específico. Es básicamente una getElementByIdversión html.

suryansh
fuente
-3

prueba esta función

function navigate(divId) {
$j('html, body').animate({ scrollTop: $j("#"+divId).offset().top }, 1500);
}

Pase el id de div como parámetro funcionará, ya lo estoy usando

virendra rastogi
fuente
lo que la biblioteca es $jde?
EoghanM
Supongo que $ j hace referencia a jQuery: la pregunta indica que necesita Javascript.
Cameron W.