Como rolar para um elemento usando JavaScript?

152

Estou tentando mover a página para um <div>elemento.

Eu tentei o próximo código sem sucesso:

document.getElementById("divFirst").style.visibility = 'visible';
document.getElementById("divFirst").style.display = 'block';
C ..
fonte
1
visibilitye displaysão usados ​​para tornar os elementos (in) visíveis. Deseja rolar a div na tela?
Lekensteyn
Que tipo de foco? O mesmo foco que você tem ao percorrer os elementos do formulário ou se concentrar no sentido de destacar o elemento de alguma forma? A única coisa que você faz é exibir o elemento, o que não terá efeito se ele já estiver sendo exibido.
Felix Kling
Focar como rolagem na visualização?
22411 epascarello
12
el.scrollIntoView(true)
Blazemonger

Respostas:

123

Você pode usar uma âncora para "focalizar" a div. Ou seja:

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

e use o seguinte javascript:

// the next line is required to work around a bug in WebKit (Chrome / Safari)
location.href = "#";
location.href = "#myDiv";
Nikoloff
fonte
9
O Chrome (WebKit) possui um bug que faz com que a página não role depois que a âncora estiver definida. Use: location.href="#";location.href="#myDiv". id="myDiv"É preferível usar name="myDiv"e também funciona.
Lekensteyn 15/02
8
Eu tive esse problema exato, mas a "correção" do WebKit causa um problema para mim no FF 3.6.13. Funciona sem a linha "#", mas se você a adicionar, ela será direcionada para "#" e nunca tentará ir para "#myDiv". Vou ficar com a solução sem o "#", que está funcionando para mim ... woohoo!
TimFoolery 21/02
1
Isso não funciona bem para mim, porque acrescenta todos estes eventos de navegação para o histórico do navegador e eu não posso facilmente voltar à página anterior
bikeman868
Eu acho que 'AnhSirk Dasarp' abaixo é um método melhor para rolar o elemento desejado para o topo da tela visível.
precisa saber é o seguinte
E se o scroller estiver em uma div interna?
Qian Chen
241

scrollIntoView funciona bem:

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

referência completa nos documentos MDN:
https://developer.mozilla.org/en-US/docs/Web/API/Element.scrollIntoView

schpet
fonte
11
@CameronMcCluskie, é apenas o estranho "scrollIntoViewOptions" (rolagem suave, etc) que possui suporte exclusivo ao Firefox. o uso básico que tenho na minha resposta deve funcionar em quase tudo.
schpet 17/07/2015
4
Confirmo que, a partir de 16 de abril, ele também funciona com o Opera e o Chrome.
precisa saber é o seguinte
2
Ao usar esta solução e você tem uma barra de navegação fixa na parte superior, é necessário considerar isso também. Uma solução diferente pode ser mais adequada, como windows.scrollTo (posX, posY), com o posY calculado corretamente.
Manfred
2
Trabalhou no Firefox, Opera e Safari.
Jagdeep Singh
3
Aqui está uma outra fonte (caniuse) para compatibilidade do navegador descrollIntoView
The Red Pea
99

sua pergunta e as respostas parecem diferentes. Não sei se estou enganado, mas para aqueles que pesquisam e chegam aqui, minha resposta seria a seguinte:

  1. Minha resposta no stackoverflow
  2. Uma pergunta semelhante

Minha resposta explicou:

aqui está um javascript simples para isso

chame isso quando precisar rolar a tela para um elemento que tenha id = "yourSpecificElementId"

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

ie para a pergunta acima, se a intenção é rolar a tela para a div com o ID 'divFirst'

o código seria: window.scroll(0,findPos(document.getElementById("divFirst")));

e você precisa desta função para o trabalho:

//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];
    }
}

a tela será rolada para o seu elemento específico.

AnhSirk Dasarp
fonte
12
Esta solução tem a vantagem de não mexer com o URL visível na barra de navegação do navegador adicionando âncoras MyID.
Renaud Bompuis
2
Obrigado, acho que essa deve ser a resposta aceita, pois é java-script, não HTML, como a resposta atual que não funcionaria para mim, mas funcionou!
Steve Byrne
Isto é, se é o windowque você gostaria de se deslocar, não é uma área de visualização-ing estouro
WebWanderer
1
Obras depois de mudar [curtop]para curtopno final
goldylucks
Se você não deseja que ele empurre esse elemento para o topo da página, mas prefere rolar para que o elemento fique no centro da tela, subtraia (window.screen.height/2)de findPos
Albert Renshaw
47

Para Chrome e Firefox

Eu estive analisando um pouco isso e descobri um que parece ser a maneira mais natural de fazer isso. Claro, este é o meu pergaminho favorito agora. :)

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

Para apoiadores do IE, Edge e Safari

Observe que window.scroll({ ...options })não há suporte no IE, Edge e Safari. Nesse caso, é mais provável que seja melhor usar element.scrollIntoView(). (Suportado no IE 6). Você pode provavelmente (ler: não testado) passar opções sem nenhum efeito colateral.

É claro que eles podem ser agrupados em uma função que se comporta de acordo com o navegador que está sendo usado.

homem das cavernas
fonte
3
Trabalhando como charme :)
midzer
1
Esta é a única solução que funcionou para mim com o Chrome.
Wkille
1
Eu queria pegar sua solução, pois é possível ajustar a posição (no meu caso, y-80). Parece, como var element = document.getElementById ("Div"); está faltando no seu exemplo? Além disso, ele não funciona com o IE11. O IE11 não conhece window.scrollY - precisamos usar window.pageYOffset para receber um valor. Depois que mudei isso, tive vários erros de jquery (sem compreender) (é claro - principalmente - apenas no IE 11.) Portanto, implementei document.getElementById ("divFirst"). ScrollIntoView (); e então $ (window ) .scrollTop ($ (window) .scrollTop () - 80); o que funciona com todos os navegadores.
FredyWenger
Não suportado no Safari (passando opções parawindow.scroll
goldylucks 21/07/19
Obrigado pelos comentários, atualizo a resposta para incluir compatibilidade com o navegador.
Caveman
8

Tente o seguinte:

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

por exemplo @:

http://jsfiddle.net/Vgrey/

Chandu
fonte
Eu só quero enfatizar que a propriedade DOM é, element.tabIndexmas não element.tabindex; o segundo funciona no Firefox, mas não no Chrome (pelo menos quando tentei há algum tempo). Claro, usado como um atributo HTML tanto tabIndexe tabindextrabalho (e em XHTML, tabindexdeve ser utilizado)
Oriol
6

Para rolar para um determinado elemento, criei esta solução apenas em javascript abaixo.

Uso simples:

EPPZScrollTo.scrollVerticalToElementById('signup_form', 20);

Objeto do mecanismo (você pode mexer no filtro, nos valores de 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
fonte
@codeWithMe Yap, é mais como um código semelhante ao iOS, onde a quantidade real não importa, então você pode prosseguir e nomear tudo depois do que ela contém / contém. Eu prefiro isso à falta.
Geri Borbás
5

Aqui está uma função que pode incluir um deslocamento opcional para esses cabeçalhos fixos. Nenhuma biblioteca externa é necessária.

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

Você pode pegar a altura de um elemento usando JQuery e rolar para ele.

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

Atualização março de 2018

Role até esta resposta sem usar o JQuery

scrollIntoView('#answer-44786637', document.querySelector('.top-bar').offsetHeight)
HarlemSquirrel
fonte
5

Você pode definir o foco como elemento. Funciona melhor quescrollIntoView

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

node.focus()

node.removeAttribute('tabindex')

ZhenyaUsenko
fonte
Oh cara, você salvou meu dia. Testou muitas coisas, mas essa foi a única coisa que funcionou para mim e é compatível com todos os navegadores. Btw eu criei uma entrada e deu 1px altura e largura e me concentrei na entrada.é funciona muito bem. Obrigado
Martian.titan
5

A melhor e mais curta resposta que funciona mesmo com efeitos de animação:

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

Se você tiver uma barra de navegação fixa, basta subtrair a altura do valor superior. Portanto, se a altura da barra fixa for 70 px, a linha 2 será semelhante a:

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

Explicação: A linha 1 faz com que a posição do elemento role a linha 2 para a posição do elemento; behaviorA propriedade adiciona um efeito animado suave

DAVID AJAYI
fonte
Muito legal, mas ainda não funciona no Safari e em outros navegadores. No entanto, funciona com este polyfill github.com/iamdustan/smoothscroll . ;)
Íhor Mé 30/11/19
2

O foco pode ser definido apenas em elementos interativos ... Div apenas representa uma seção lógica da página.

Talvez você possa definir as bordas em torno de div ou alterar sua cor para simular um foco. E sim, Visiblity não é foco.

SM Kamran
fonte
1

Eu acho que se você adicionar um tabindex ao seu div, ele será capaz de obter foco:

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

Porém, não acho que seja válido, o tabindex pode ser aplicado apenas a uma área, botão, entrada, objeto, seleção e área de texto. Mas dá-lhe uma chance.

Robin
fonte
1
No HTML5, tabindexhá um "atributo principal", que é "atributos globais" (atributos comuns a todos os elementos na linguagem HTML). Consulte w3.org/TR/2011/WD-html-markup-20110113/global-attributes.html
Oriol
1

Semelhante à solução de @ caveman

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

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

Você não pode se concentrar em uma div. Você pode focar apenas em um elemento de entrada nessa div. Além disso, você precisa usar element.focus () em vez de display ()

Andrey
fonte
1
Você pode tornar um <div>foco se estiver usando o tabindexatributo Veja dev.w3.org/html5/spec-author-view/editing.html#attr-tabindex
Oriol
0

Depois de olhar muito ao redor, foi o que finalmente funcionou para mim:

  1. Encontre / localize div em seu domínio, que possui barra de rolagem. Para mim, ficou assim: "div class =" table_body table_body_div "scroll_top =" 0 "scroll_left =" 0 "style =" width: 1263px; altura: 499px; "

  2. Eu o localizei com este xpath: // div [@ class = 'table_body table_body_div']

  3. Utilizava JavaScript para executar rolagem como esta: driver (JavascriptExecutor)) .executeScript ("argumentos [0] .scrollLeft = argumentos [1];", elemento, 2000);

2000 é o número de pixels que eu queria rolar para a direita. Use scrollTop em vez de scrollLeft se desejar rolar sua div para baixo.

Nota: Tentei usar o scrollIntoView, mas não funcionou corretamente porque minha página da web tinha vários divs. Funcionará se você tiver apenas uma janela principal onde o foco está. Esta é a melhor solução que encontrei se você não quiser usar o jQuery que eu não queria.

Anchal Agrawal
fonte
0

Um método que costumo usar para rolar um contêiner para o seu conteúdo.

/**
@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');
    }
};

se você deseja substituir globalmente, também pode:

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
fonte
0

Devido ao comportamento "suave" não funciona no Safari, Safari ios, Explorer. Normalmente, escrevo uma função simples 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
fonte
-1

Caso você queira usar o html, você pode apenas usar o seguinte:

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

e crie um link html para o ID do elemento específico. Sua getElementByIdversão basicamente html.

suryansh
fonte
-3

tente esta função

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

Passe o div id como parâmetro ele vai funcionar já estou usando ele

virendra rastogi
fonte
de que biblioteca é $j?
EoghanM
Eu assumo as referências $ j jQuery - a pergunta afirma que precisa de Javascript.
Cameron W.Fev