Comment faire défiler jusqu'à un élément en utilisant JavaScript?

153

J'essaye de déplacer la page vers un <div>élément.

J'ai essayé le code suivant en vain:

document.getElementById("divFirst").style.visibility = 'visible';
document.getElementById("divFirst").style.display = 'block';
C ..
la source
1
visibilityet displaysont utilisés pour rendre les éléments (in) visibles. Voulez-vous faire défiler le div à l'écran?
Lekensteyn
Quel genre de concentration? Le même focus que vous avez lors de la tabulation dans les éléments du formulaire ou le focus dans le sens de mettre en évidence l'élément d'une manière ou d'une autre? La seule chose que vous faites est d'afficher l'élément, ce qui n'a aucun effet s'il est déjà affiché.
Felix Kling
Focus comme défilement dans la vue?
epascarello
12
el.scrollIntoView(true)
Blazemonger

Réponses:

124

Vous pouvez utiliser une ancre pour "focaliser" le div. C'est à dire:

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

puis utilisez le javascript suivant:

// the next line is required to work around a bug in WebKit (Chrome / Safari)
location.href = "#";
location.href = "#myDiv";
Nikoloff
la source
9
Chrome (WebKit) a un bogue qui empêche la page de défiler une fois l'ancre définie. Utilisation: location.href="#";location.href="#myDiv". L'utilisation id="myDiv"est préférable name="myDiv"et fonctionne aussi.
Lekensteyn
8
J'ai eu ce problème précis, mais le "correctif" WebKit me pose un problème dans FF 3.6.13. Cela fonctionne sans la ligne «#», mais si vous l'ajoutez, il va à «#» et ne tente jamais d'aller à «#myDiv». Je m'en tiendrai à la solution sans le "#", qui fonctionne pour moi ... woohoo!
TimFoolery
1
Cela ne fonctionne pas bien pour moi car cela ajoute tous ces événements de navigation à l'historique du navigateur et je ne peux pas facilement revenir à la page précédente
bikeman868
Je pense que «AnhSirk Dasarp» ci-dessous est une meilleure méthode pour faire défiler l'élément souhaité vers le haut de l'écran visible.
Curious101
Et si le scroller est dans un div interne?
Qian Chen
240

scrollIntoView fonctionne bien:

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

référence complète dans la documentation MDN:
https://developer.mozilla.org/en-US/docs/Web/API/Element.scrollIntoView

schpet
la source
11
@CameronMcCluskie ce n'est que l'étrange "scrollIntoViewOptions" (défilement fluide, etc.) qui a un support exclusif de Firefox. l'utilisation de base que j'ai dans ma réponse devrait fonctionner sur presque tout.
schpet
4
Je confirme qu'à partir du 16 avril, cela fonctionne également sous Opera et Chrome.
lvr123
2
Lorsque vous utilisez cette solution et que vous avez une barre de navigation fixe en haut, vous devez également en tenir compte. Une solution différente pourrait être plus appropriée comme windows.scrollTo (posX, posY) avec posY correctement calculé.
Manfred
2
A travaillé dans Firefox, Opera et Safari.
Jagdeep Singh
3
Voici une autre source (caniuse) pour la compatibilité du navigateur descrollIntoView
The Red Pea
100

votre question et les réponses sont différentes. Je ne sais pas si je me trompe, mais pour ceux qui recherchent sur Google et arrivent ici, ma réponse serait la suivante:

  1. Ma réponse sur stackoverflow
  2. Une question similaire

Ma réponse a expliqué:

voici un javascript simple pour cela

appelez ceci lorsque vous devez faire défiler l'écran jusqu'à un élément qui a id = "yourSpecificElementId"

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

c'est à dire. pour la question ci-dessus, si l'intention est de faire défiler l'écran vers le div avec l'ID 'divFirst'

le code serait: window.scroll(0,findPos(document.getElementById("divFirst")));

et vous avez besoin de cette fonction pour le travail:

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

l'écran défilera jusqu'à votre élément spécifique.

AnhSirk Dasarp
la source
12
Cette solution a l'avantage de ne pas jouer avec l'URL visible dans la barre de navigation du navigateur en ajoutant des ancres MyID.
Renaud Bompuis
2
Merci, je pense que cela devrait être la réponse acceptée, c'est java-script, pas HTML comme la réponse actuelle qui ne fonctionnerait pas pour moi, mais cela a fonctionné!
Steve Byrne
Autrement dit, si c'est le que windowvous souhaitez faire défiler, pas une zone de visualisation débordante
WebWanderer
1
Travaux après avoir changé [curtop]à curtopla fin
goldylucks
Si vous ne voulez pas qu'il pousse cet élément tout en haut de la page, mais que vous préférez plutôt qu'il défile de sorte que l'élément soit au centre de l'écran, soustrayez (window.screen.height/2)de findPos
Albert Renshaw
47

Pour Chrome et Firefox

J'ai regardé un peu là-dedans et j'ai trouvé celui-ci qui semble en quelque sorte le moyen le plus naturel de le faire. Bien sûr, c'est mon parchemin préféré maintenant. :)

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

Pour les supporters d'IE, Edge et Safari

Notez que ce window.scroll({ ...options })n'est pas pris en charge sur IE, Edge et Safari. Dans ce cas, il est probablement préférable d'utiliser element.scrollIntoView(). (Pris en charge sur IE 6). Vous pouvez très probablement (lire: non testé) transmettre des options sans aucun effet secondaire.

Ceux-ci peuvent bien sûr être enveloppés dans une fonction qui se comporte en fonction du navigateur utilisé.

Homme des cavernes
la source
3
Working like charme :)
midzer
1
C'est la seule solution qui a fonctionné pour moi avec Chrome.
wkille
1
Je voulais prendre votre solution, car il est possible d'affiner la position (dans mon cas y-80). Il semble, comme var element = document.getElementById ("Div"); manque dans votre exemple? De plus, cela ne fonctionne pas avec IE11. IE11 ne sait pas window.scrollY - nous devons utiliser window.pageYOffset à la place pour recevoir une valeur. Après avoir changé cela, j'ai eu diverses erreurs jquery (pour ne pas comprendre) (bien sûr - comme la plupart du temps - uniquement dans IE11. Par conséquent, j'ai implémenté document.getElementById ("divFirst"). ScrollIntoView (); puis $ (window ) .scrollTop ($ (window) .scrollTop () - 80); ce qui fonctionne avec tous les navigateurs.
FredyWenger
Non pris en charge sur Safari (passage des options àwindow.scroll
goldylucks
Merci pour les commentaires, je met à jour la réponse pour inclure la compatibilité du navigateur.
Caveman
8

Essaye ça:

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

par exemple @:

http://jsfiddle.net/Vgrey/

Chandu
la source
Je veux seulement souligner que la propriété DOM l'est element.tabIndexmais pas element.tabindex; le second fonctionne sur Firefox mais pas sur Chrome (du moins quand je l'ai essayé il y a quelque temps). Bien sûr, utilisé comme attribut HTML à la fois tabIndexet tabindextravail (et sur XHTML, tabindexdoit être utilisé)
Oriol
6

Pour faire défiler jusqu'à un élément donné, faites simplement cette solution javascript uniquement ci-dessous.

Utilisation simple:

EPPZScrollTo.scrollVerticalToElementById('signup_form', 20);

Objet moteur (vous pouvez jouer avec le filtre, les valeurs 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
la source
@codeWithMe Yap, cela ressemble plus à un code de type iOS, où la quantité réelle n'a pas d'importance, vous pouvez donc tout nommer après ce qu'il fait / contient. Je préfère cela à la brièveté.
Geri Borbás
5

Voici une fonction qui peut inclure un décalage facultatif pour ces en-têtes fixes. Aucune bibliothèque externe nécessaire.

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

Vous pouvez saisir la hauteur d'un élément à l'aide de JQuery et y faire défiler.

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

Mise à jour mars 2018

Faites défiler jusqu'à cette réponse sans utiliser JQuery

scrollIntoView('#answer-44786637', document.querySelector('.top-bar').offsetHeight)
HarlemÉcureuil
la source
5

Vous pouvez définir le focus sur l'élément. Cela fonctionne mieux quescrollIntoView

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

node.focus()

node.removeAttribute('tabindex')

ZhenyaUsenko
la source
Oh mec, tu m'as sauvé la journée. J'ai testé beaucoup de choses, mais celui-ci était la seule chose qui fonctionnait pour moi et il est pris en charge par tous les navigateurs. Btw j'ai créé une entrée et donné 1px hauteur et largeur et me suis concentré sur l'entrée.il fonctionne très bien. Merci
Martian.titan
5

La meilleure et la plus courte réponse à ce qui fonctionne même avec des effets d'animation:

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

Si vous avez une barre de navigation fixe, soustrayez simplement sa hauteur de la valeur supérieure, donc si la hauteur de votre barre fixe est de 70px, la ligne 2 ressemblera à:

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

Explication: La ligne 1 obtient la position de l'élément. La ligne 2 fait défiler jusqu'à la position de l'élément; behaviorla propriété ajoute un effet animé fluide

DAVID AJAYI
la source
Vraiment cool, mais ne fonctionne pas encore sur Safari et certains autres navigateurs. Fonctionne avec ce polyfill github.com/iamdustan/smoothscroll cependant. ;)
Íhor Mé
2

L'accent peut être mis uniquement sur les éléments interactifs ... Les Div ne représentent qu'une section logique de la page.

Vous pouvez peut-être définir les bordures autour de div ou changer sa couleur pour simuler un focus. Et oui, la visibilité n'est pas la concentration.

SM Kamran
la source
1

Je pense que si vous ajoutez un tabindex à votre div, il pourra obtenir le focus:

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

Je ne pense pas que ce soit valide, tabindex ne peut être appliqué qu'à une zone, un bouton, une entrée, un objet, une sélection et une zone de texte. Mais essayez-le.

Robin
la source
1
En HTML5, il tabindexexiste un «attribut principal», qui sont des «attributs globaux» (attributs communs à tous les éléments du langage HTML). Voir w3.org/TR/2011/WD-html-markup-20110113/global-attributes.html
Oriol
1

Similaire à la solution de @ caveman

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

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

Vous ne pouvez pas vous concentrer sur un div. Vous ne pouvez vous concentrer que sur un élément d'entrée de ce div. De plus, vous devez utiliser element.focus () au lieu de display ()

Andreï
la source
1
Vous pouvez rendre un <div>focusable si vous utilisez l' tabindexattribut. Voir dev.w3.org/html5/spec-author-view/editing.html#attr-tabindex
Oriol
0

Après avoir beaucoup cherché, c'est ce qui a finalement fonctionné pour moi:

  1. Trouvez / localisez div dans votre dom qui a une barre de défilement. Pour moi, cela ressemblait à ceci: "div class =" table_body table_body_div "scroll_top =" 0 "scroll_left =" 0 "style =" width: 1263px; hauteur: 499 px; "

  2. Je l'ai localisé avec ce xpath: // div [@ class = 'table_body table_body_div']

  3. JavaScript utilisé pour exécuter le défilement comme ceci: (JavascriptExecutor) driver) .executeScript ("arguments [0] .scrollLeft = arguments [1];", element, 2000);

2000 est le nombre de pixels que je voulais faire défiler vers la droite. Utilisez scrollTop au lieu de scrollLeft si vous souhaitez faire défiler votre div vers le bas.

Remarque: j'ai essayé d'utiliser scrollIntoView mais cela ne fonctionnait pas correctement car ma page Web avait plusieurs div. Cela fonctionnera si vous n'avez qu'une seule fenêtre principale où se trouve le focus. C'est la meilleure solution que j'ai rencontrée si vous ne voulez pas utiliser jQuery, ce que je ne voulais pas.

Anchal Agrawal
la source
0

Une méthode que j'utilise souvent pour faire défiler un conteneur jusqu'à son contenu.

/**
@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 vous souhaitez remplacer globalement, vous pouvez également faire:

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
la source
0

En raison du comportement "lisse" ne fonctionne pas dans Safari, Safari ios, Explorer. J'écris généralement une fonction simple en utilisant 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
la source
-1

Si vous souhaitez utiliser du html, vous pouvez simplement utiliser ceci:

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

et faites-en un lien html vers l'ID d'élément spécifique. Sa getElementByIdversion essentiellement html.

suryansh
la source
-3

essayez cette fonction

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

Passez l'identifiant div comme paramètre, cela fonctionnera Je l'utilise déjà

virendra rastogi
la source
de quelle bibliothèque $jprovient-il?
EoghanM
Je suppose que $ j fait référence à jQuery - la question indique qu'il a besoin de Javascript.
Cameron W.