39 votes

jQuery scrollTop() ne semble pas fonctionner dans Safari ou Chrome (Windows)

J'ai une configuration simple qui permet de charger une fenêtre de type "aide" et de la faire défiler jusqu'à un point particulier de la page. Le code ressemble plus ou moins à ceci :

var target = /* code */;
target.offsetParent().scrollTop(target.offset().top - fudgeValue);

La cible du défilement et la valeur d'atténuation sont déterminées par quelques indications données sur la page, et je n'ai aucun problème avec cette partie du mécanisme. Dans Firefox et IE8, le code ci-dessus fonctionne exactement comme je le souhaite : la boîte de défilement (dans ce cas, le corps de la page) fait défiler correctement les éléments contenus jusqu'au bon point dans la fenêtre lorsqu'on lui demande de le faire.

Dans Chrome et Safari, cependant, l'appel à scrollTop() ne fait apparemment rien du tout. Tous les chiffres sont corrects, la cible fait référence à la bonne chose (et la fonction offsetParent() est bien l'élément body), mais il ne se passe rien du tout. D'après ce que j'ai pu voir en cherchant sur Google, c'est censé fonctionner. Y a-t-il un problème avec le moteur de rendu sous Safari et Chrome ?

Il s'agit de jQuery 1.3.2 si cela compte.

Page de test : http://gutfullofbeer.net/scrolltop.html

46voto

Carl Points 429

J'ai rencontré ce problème dans safari et chrome (Mac) et j'ai découvert que .scrollTop fonctionnait dans les cas suivants $("body") mais pas $("html, body") Cependant, FF et IE fonctionnent dans l'autre sens. Une simple détection du navigateur résout le problème :

if($.browser.safari) bodyelem = $("body")
else bodyelem = $("html,body")

bodyelem.scrollTop(100)

La valeur du navigateur jquery pour chrome est safari, il suffit donc de faire une détection sur ce dernier.

J'espère que cela aidera quelqu'un

23voto

Shog9 Points 82052

Oui, il semble qu'il y ait un bug dans Chrome quand il s'agit de modifier la body en essayant d'en faire un offsetParent. Comme solution de contournement, je vous suggère d'ajouter simplement un autre div pour envelopper la balise #content et faire que défilement :

html, body { height: 100%; padding: 0; } 
html { width: 100%; background-color: #222; overflow: hidden; margin: 0; } 
body 
{ 
   width: 40em; margin: 0px auto; /* narrow center column layout */
   background-color: white; 
   position: relative; /* allow positioning children relative to this element */
} 
#scrollContainer /* wraps #content, scrolls */
{ 
  overflow: auto; /* scroll! */
  position:absolute; /* make offsetParent */
  top: 0; height: 100%; width: 100%; /* fill parent */
} 
#header 
{ 
  position: absolute; 
  top: 0px; height: 50px; width: 38.5em; 
  background-color: white; 
  z-index: 1; /* sit above #content in final layout */
} 
#content { padding: 5px 14px 50px 5px;  }

Testé dans FF 3.5.5, Chrome 3.0.195.33, IE8
Démonstration en direct

17voto

Parhs Points 611
 $("body,html,document").scrollTop($("#map_canvas").position().top);

Cela fonctionne pour Chrome 7 ,IE6,IE7,IE8,IE9,FF 3.6 ,Safari 5

2012 UPATE
c'est toujours bon mais j'ai dû l'utiliser à nouveau. parfois la position ne fonctionne pas donc c'est l'alternative.

$("body,html,document").scrollTop($("#map_canvas").offset().top);

9voto

pengkai Points 71

Le statut de support du navigateur est le suivant :

IE8, Firefox, Opera : $("html")

Chrome, Safari : $("body")

Donc ça marche :

bodyelem = $.browser.safari ? $("body") : $("html") ;
bodyelem.animate( {scrollTop: 0}, 500 );

7voto

molokoloco Points 1626

Pour le parchemin : "html" ou "body" pour le paramètre "setter". (dépend du navigateur)... 'window' pour le getter ...

Un jsFiddle pour tester est ici : http://jsfiddle.net/molokoloco/uCrLa/

var $window = $(window), // Set in cache, intensive use !
    $document = $(document),
    $body = $('body'),
    scrollElement = 'html, body',
    $scrollElement = $();

var isAnimated = false;

// Find scrollElement
// Inspired by http://www.zachstronaut.com/posts/2009/01/18/jquery-smooth-scroll-bugs.html
$(scrollElement).each(function(i) {
    // 'html, body' for setter... window for getter... 
    var initScrollTop = parseInt($(this).scrollTop(), 10);
    $(this).scrollTop(initScrollTop + 1);
    if ($window.scrollTop() == initScrollTop + 1) {
        scrollElement = this.nodeName.toLowerCase(); // html OR body
        return false; // Break
    }
});
$scrollElement = $(scrollElement);

// UTILITIES...
var getHash = function() {
        return window.location.hash || '';
    },
    setHash = function(hash) {
        if (hash && getHash() != hash) window.location.hash = hash;
    },
    getWinWidth = function() {
        return $window.width();
    },
    // iphone ? ((window.innerWidth && window.innerWidth > 0) ? window.innerWidth : $window.width());
    getWinHeight = function() {
        return $window.height();
    },
    // iphone ? ((window.innerHeight && window.innerHeight > 0) ? window.innerHeight : $window.height());
    getPageWidth = function() {
        return $document.width();
    },
    getPageHeight = function() {
        return $document.height();
    },
    getScrollTop = function() {
        return parseInt($scrollElement.scrollTop() || $window.scrollTop(), 10);
    },
    setScrollTop = function(y) {
        $scrollElement.stop(true, false).scrollTop(y);
    },
    myScrollTo = function(y, newAnchror) { // Call page scrolling to a value (like native window.scrollBy(x, y)) // Can be flooded
        isAnimated = true; // kill waypoint AUTO hash
        var duration = 360 + (Math.abs(y - getScrollTop()) * 0.42); // Duration depend on distance...
        if (duration > 2222) duration = 0; // Instant go !! ^^
        $scrollElement.stop(true, false).animate({
            scrollTop: y
        }, {
            duration: duration,
            complete: function() { // Listenner of scroll finish...
                if (newAnchror) setHash(newAnchror); // If new anchor
                isAnimated = false;
            }
        });
    },
    goToScreen = function(dir) { // Scroll viewport page by paginette // 1, -1 or factor
        var winH = parseInt((getWinHeight() * 0.75) * dir); // 75% de la hauteur visible comme unite
        myScrollTo(getScrollTop() + winH);
    };

myScrollTo((getPageHeight() / 2), 'iamAMiddleAnchor');

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X