简体   繁体   English

jQuery scrollTop()似乎不适用于Safari或Chrome(Windows)

[英]jQuery scrollTop() doesn't seem to work in Safari or Chrome (Windows)

I've got a simple setup to allow a "help"-style window to be loaded and scrolled to a particular point on the page. 我有一个简单的设置,允许加载“帮助”式窗口并滚动到页面上的特定点。 More or less the code looks like this: 或多或少的代码看起来像这样:

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

The target of the scroll and the fudge value are determined by a couple of hints dropped on the page, and I'm having no problems with that part of this mechanism anywhere. 滚动的目标和软糖值由页面上的一些提示确定,我对这个机制的任何部分都没有任何问题。 In Firefox and IE8, the above code works exactly like I want: the scrolled box (in this case, the page body) correctly scrolls the contained stuff to the right point in the window when it's told to do so. 在Firefox和IE8中,上面的代码与我想要的完全一样:滚动框(在这种情况下,页面正文)正确地将包含的东西滚动到窗口中的正确位置,当它被告知这样做时。

In Chrome and Safari, however, the call to scrollTop() apparently does nothing at all. 但是,在Chrome和Safari中,对scrollTop()的调用显然什么都不做。 All the numbers are OK, and the target refers to the right thing (and the offsetParent() is indeed the body element), but nothing at all happens. 所有数字都没问题,目标指的是正确的东西(而offsetParent()确实是正文元素),但什么都没发生。 As far as I can tell from googling around, this is supposed to work. 据我所知,谷歌搜索,这应该是有效的。 Is there something funny about the renderer under Safari and Chrome? Safari和Chrome下的渲染器有什么有趣的吗?

This is jQuery 1.3.2 if that matters. 如果重要的话,这是jQuery 1.3.2。

Test page: http://gutfullofbeer.net/scrolltop.html 测试页面: http//gutfullofbeer.net/scrolltop.html

I was having this problem in Safari and Chrome (Mac) and discovered that .scrollTop would work on $("body") but not $("html, body") , FF and IE however works the other way round. 我在Safari和Chrome(Mac)中遇到了这个问题,并发现.scrollTop可以在$("body")上工作,但不是$("html, body") ,但是FF和IE却是相反的。 A simple browser detect fixes the issue: 一个简单的浏览器检测修复了该问题:

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

bodyelem.scrollTop(100)

The jQuery browser value for Chrome is Safari, so you only need to do a detect on that. Chrome的jQuery浏览器值是Safari,因此您只需对其进行检测即可。

Hope this helps someone. 希望这有助于某人。

Yeah, there appears to be a bug in Chrome when it comes to modifying the body , trying to make it into an offsetParent . 是的,在修改body时,Chrome中似乎存在一个错误,试图将其变成offsetParent As a work-around, I suggest you simply add another div to wrap the #content div, and make that scroll: 作为一个变通办法,我建议你只需添加另一个div来包裹#content股利,并作出滚动:

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

Tested in FF 3.5.5, Chrome 3.0.195.33, IE8 测试了FF 3.5.5,Chrome 3.0.195.33,IE8

Live demonstration: 现场演示:

 $(function() { $('#header').find('button').click(function(ev) { var button = $(this), target = $('div.' + button.attr('class')); var scroll = target.offsetParent().scrollTop(); target.offsetParent().scrollTop(target.offset().top + scroll - 50); }); }); 
 html, body { height: 100%; padding: 0; } html { width: 100%; background-color: #222; overflow: hidden; margin: 0; } body { width: 40em; margin: 0px auto; background-color: white; position: relative; } #scrollContainer { overflow: auto; position:absolute; top: 0; height: 100%; width: 100%; } #header { position: absolute; top: 0px; height: 50px; width: 38.5em; background-color: white; z-index: 1; } #content { padding: 5px 14px 50px 5px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <div id='header'> Header Box <button class='A'>A</button> <button class='B'>B</button> <button class='C'>C</button> </div> <div id='scrollContainer'> <div id='content'> <div style='height: 50px'> </div> <div class='A'> <h1>A</h1> <p>My name is Boffer Bings. I was born of honest parents in one of the humbler walks of life, my father being a manufacturer of dog-oil and my mother having a small studio in the shadow of the village church, where she disposed of unwelcome babes. In my boyhood I was trained to habits of industry; I not only assisted my father in procuring dogs for his vats, but was frequently employed by my mother to carry away the debris of her work in the studio. In performance of this duty I sometimes had need of all my natural intelligence for all the law officers of the vicinity were opposed to my mother's business. They were not elected on an opposition ticket, and the matter had never been made a political issue; it just happened so. My father's business of making dog-oil was, naturally, less unpopular, though the owners of missing dogs sometimes regarded him with suspicion, which was reflected, to some extent, upon me. My father had, as silent partners, all the physicians of the town, who seldom wrote a prescription which did not contain what they were pleased to designate as _Ol. can._ It is really the most valuable medicine ever discovered. But most persons are unwilling to make personal sacrifices for the afflicted, and it was evident that many of the fattest dogs in town had been forbidden to play with me--a fact which pained my young sensibilities, and at one time came near driving me to become a pirate. </div> <div class='B'> <h1>B</h1> <p> Looking back upon those days, I cannot but regret, at times, that by indirectly bringing my beloved parents to their death I was the author of misfortunes profoundly affecting my future. <p> One evening while passing my father's oil factory with the body of a foundling from my mother's studio I saw a constable who seemed to be closely watching my movements. Young as I was, I had learned that a constable's acts, of whatever apparent character, are prompted by the most reprehensible motives, and I avoided him by dodging into the oilery by a side door which happened to stand ajar. I locked it at once and was alone with my dead. My father had retired for the night. The only light in the place came from the furnace, which glowed a deep, rich crimson under one of the vats, casting ruddy reflections on the walls. Within the cauldron the oil still rolled in indolent ebullition, occasionally pushing to the surface a piece of dog. Seating myself to wait for the constable to go away, I held the naked body of the foundling in my lap and tenderly stroked its short, silken hair. Ah, how beautiful it was! Even at that early age I was passionately fond of children, and as I looked upon this cherub I could almost find it in my heart to wish that the small, red wound upon its breast--the work of my dear mother--had not been mortal. </div> <div class='C'> <h1>C</h1> <p>It had been my custom to throw the babes into the river which nature had thoughtfully provided for the purpose, but that night I did not dare to leave the oilery for fear of the constable. "After all," I said to myself, "it cannot greatly matter if I put it into this cauldron. My father will never know the bones from those of a puppy, and the few deaths which may result from administering another kind of oil for the incomparable _ol. can._ are not important in a population which increases so rapidly." In short, I took the first step in crime and brought myself untold sorrow by casting the babe into the cauldron. </div> <div style='height: 75em;'> </div> </div> </div> 

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

This works for Chrome 7, IE6, IE7, IE8, IE9, FF 3.6 and Safari 5. 这适用于Chrome 7,IE6,IE7,IE8,IE9,FF 3.6和Safari 5。

2012 UPDATE 2012年更新
This is still good but I had to use it again. 这仍然很好,但我不得不再次使用它。 Sometimes position doesn't work so this is an alternative: 有时position不起作用所以这是一个替代方案:

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

The browser support status is this: 浏览器支持状态如下:

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

Chrome, Safari: $("body") Chrome,Safari: $("body")

So this works: 这样可行:

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

For the scroll : 'html' or 'body' for setter (depend on browser)... 'window' for getter ... 对于滚动: 'html'或'body'用于setter (取决于浏览器)... 'window'用于getter ...

A jsFiddle for testing is here : http://jsfiddle.net/molokoloco/uCrLa/ 一个jsFiddle测试在这里: 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');

There is a bug in Chrome (not in Safari at the time we checked) that gives unexpected results in Javascript's various width and height measurements when opening tabs in the background ( bug details here ) - we logged the bug in June and it's remained unresolved since. 在我们检查时,Chrome中存在一个错误(在我们检查时不在Safari中),在后台打开标签时会在Javascript的各种宽度和高度测量中产生意外结果( 此处有错误详细信息 ) - 我们在6月份记录了该错误并且自从此以后仍未解决。

It's possible you've encountered the bug in what you're attempting to do. 你有可能遇到了你想要做的事情的错误。

Works for Safari, Firefox, and IE7 (haven't tried IE8). 适用于Safari,Firefox和IE7(尚未尝试过IE8)。 Simple test: 简单测试:

<button onclick='$("body,html").scrollTop(0);'>  Top </button>

<button onclick='$("body,html").scrollTop(100);'> Middle </button>

<button onclick='$("body,html").scrollTop(250);'> Bottom </button>

Most examples use either one or both, but in reverse order (ie, "html,body"). 大多数示例使用其中一个或两个,但顺序相反(即“html,body”)。

Cheers. 干杯。

(And semantic purists out there, don't bust my chops -- I've been looking for this for weeks, this is a simple example, that validates XHTML strict. Feel free to create 27 layers of abstraction and event binding bloat for your OCD peace of mind. Just please give due credit, since the folks in the jQuery forums, SO, and the G couldn't cough up the goods. Peace out.) (还有语义纯粹主义者,不要破坏我的印章 - 我一直在寻找这个数周,这是一个简单的例子,它验证XHTML严格。随意为你创建27层抽象和事件绑定膨胀OCD安心。请你给予应有的信任,因为jQuery论坛中的人们,SO和G都无法咳出货物。和平了。)

setTimeout(function() { 
   $("body,html,document").scrollTop( $('body').height() ); 
}, 100);

This probably should work even if time is 10ms. 即使时间是10毫秒,这可能也应该有效。

怎么样

var top = $('html').scrollTop() || $('body').scrollTop();

It worked for me, just leave it to the jQuery. 它对我有用,只需将它留给jQuery。

$("html,body").animate({ scrollTop: 0 }, 1);

Basically you should know the browser and write the code considering browser differences. 基本上你应该知道浏览器并考虑浏览器差异来编写代码。 Since jQuery is cross-browser it should handle the first step. 由于jQuery是跨浏览器,因此它应该处理第一步。 And finally you fake the js-engine of the browser by animating the scrolling in 1 millisecond. 最后,你通过在1毫秒内动画滚动来伪造浏览器的js-engine。

Which element is the offsetParent of another is not well-specified and may vary across browsers. 哪个元素是另一个元素的offsetParent没有明确指定,并且可能因浏览器而异。 It is not guaranteed to the be the scrollable parent you are looking for. 不保证您正在寻找可滚动的父级。

The body itself also shouldn't be the page's main scrollable element. 正文本身也不应该是页面的主要可滚动元素。 It only is in Quirks Mode, which in general you would want to avoid. 它只是在Quirks模式下,一般你想要避免。

The offsetTop ​/​ offsetLeft ​/​ offsetParent measurements aren't terribly useful by themselves, they're only really reliable when you use them in a loop to get the total page-relative co-ordinates (as position() in jQuery does). offsetTop / offsetLeft / offsetParent测量本身并不是非常有用,当您使用它们在一个循环中得到总的相对页面坐标(因为他们是唯一真正可靠的position()在jQuery不会)。 You should know which is the element you want to scroll and find out the difference in page co-ordinates between that and the descendant target to find out how much to scroll it by. 您应该知道要滚动的元素是哪一个,并找出它与后代target之间的页面坐标的差异,以找出滚动它的数量。

Or if it's always the page itself you're talking about scrolling, just use a location.href= '#'+target.id navigation instead. 或者如果它总是页面本身你正在谈论滚动,只需使用location.href= '#'+target.id导航。

This appears to be working in FF and WebKit; 这似乎在FF和WebKit中有效; IE not tested so far. IE目前尚未测试过。

$(document).scrollTop();

There is not a big choice of elements that might get auto-assigned with a scrollTop value as we scroll a webpage. 在我们滚动网页时,可能会有一个很大的元素选择可能会自动分配一个scrollTop值。

So I wrote this little function to iterate through the probable elements and return the one we seek. 所以我写了这个小函数来遍历可能的元素并返回我们寻找的元素。

var grab=function (){
    var el=$();
        $('body#my_body, html, document').each(function(){
            if ($(this).scrollTop()>0) {
                el= ($(this));
                return false;
            }
        })
    return el;
}
//alert(grab().scrollTop());

In Google chrome it would get us the body, in IE - HTML. 在谷歌浏览器中,它将以IE - HTML格式获取身体。

(Note, we don't need to set overflow:auto explicitly on our html or body that way.) (注意,我们不需要在我们的html或body上设置overflow:auto 。)

I was facing this problem, I created this link at the bottom and implemented the jQuery scrollTop code and it worked perfectly in Firefox, IE, Opera but didn't work in Chrome and Safari. 我遇到了这个问题,我在底部创建了这个链接并实现了jQuery scrollTop代码,它在Firefox,IE,Opera中完美运行,但在Chrome和Safari中无效。 I'm learning jQuery so I don't know if this solution is technically perfect but this worked for me. 我正在学习jQuery,所以我不知道这个解决方案在技术上是否完美,但这对我有用。 I just implemented 2 ScrollTop codes the first one uses $('html') which works for Firefox, etc. The second one uses $('html body') this works for Chrome and Safari. 我刚刚实现了2个ScrollTop代码,第一个使用$('html'),适用于Firefox等。第二个使用$('html body'),这适用于Chrome和Safari。

$('a#top').click(function() {

    $('html').animate({scrollTop: 0}, 'slow');
    return false;

    $('html body').animate({scrollTop: 0}, 'slow');
    return false;
});

Indeed, seems like animation is required to make it work in Safari. 实际上,似乎需要动画才能使其在Safari中运行。 I ended up with: 我结束了:

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

bodyelem.animate({scrollTop:0},{queue:false, duration:100, easing:"linear", complete:callbackFunc});

I am not sure if this is the case: 我不确定是否是这种情况:

I was using Google's CDN for jQuery ie 我正在使用Google的CDN for jQuery ie

Putting "https:" before //ajax.google....... worked, it seems Safari recognized it as a local path (checked it by - Inspect Element) //ajax.google.......之前放置"https:" ,似乎Safari认为它是一个本地路径(通过 - Inspect Element检查)

Sorry, only tested in Safari 7.0.3 :( 对不起,仅在Safari 7.0.3中测试:(

I my case, the button was working for two of 8 links. 我的情况是,按钮正在为8个链接中的两个工作。 My solution was 我的解决方案是

$("body,html,document").animate({scrollTop:$("#myLocation").offset().top},2500);

This created a nice scroll effect as well 这也创造了一个很好的滚动效果

To summarise solutions from a couple of questions/answers: 总结几个问题/答案的解决方案:

If you want to get the current scroll offset use: 如果要获取当前滚动偏移量,请使用:

$(document).scrollTop()

To set the scroll offset use: 要设置滚动偏移量,请使用:

$('html,body').scrollTop(x)

To animate the scroll use use: 要为滚动设置动画,请使用:

$('html,body').animate({scrollTop: x});

It's not really a bug, just a difference in implantation by the browser vendors. 这不是一个真正的错误,只是浏览器供应商植入的差异。

As a rule avoid browser sniffing. 通常避免浏览器嗅探。 There is a nifty jQuery fix which is hinted at in the answers. 有一个漂亮的jQuery修复,在答案中暗示。

This is what works for me: $('html:not(:animated),body:not(:animated)').scrollTop() 这对我有用: $('html:not(:animated),body:not(:animated)').scrollTop()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM