12

Is there any way to set scrollLeft and scrollTop of a div simultaneously? In Chrome, Safari and Opera it works right away by setting them sequentially but in Firefox(older than 4) and IE(even in IE9!) setting one of them causes reflow resulting in ugly glitches because the page will first move left then down, like a stair-motion.

I see that window has a method called scrollTo(x,y), is there any equivalent for normal divs?

Or, is it possible to change the behavior of the browser so the reflow won't trigger on just changing the scroll. One source i found said this would only happen if i have onscroll-event registered on the div but i don't have any so that can't be the problem.

vaxthus
  • 121
  • 1
  • 1
  • 3
  • Instead of setting the scrollLeft and scrollTop you can set focus on some element in that position - such element can be created on the fly as well. – Shadow The GPT Wizard Nov 30 '10 at 09:38
  • @mercator, this is a completely different question. I am having this same problem with "left" and "width": my animation sometimes looks jumpy because I need both properties to be set simultaneously, or at least without a reflow in between. – harpo Jan 13 '11 at 05:31
  • It does seem to be the same as this question, asked only a week or two earlier: http://stackoverflow.com/questions/4207505/is-there-a-way-to-apply-multiple-css-styles-in-a-batch-to-avoid-multiple-reflows – harpo Jan 13 '11 at 05:59
  • @harpo, hmmm, you're right. I thought the answer to this question would be very similar, but I probably got thrown off by the `return false`. I thought the scroll event was cancelable. – mercator Jan 13 '11 at 10:06
  • What happens if you do something like: var left=20; var top=100; elem.scrollTop = (elem.scrollLeft = left) - left + top; – Gerben Jan 14 '11 at 11:58

5 Answers5

7

I was having this same issue just moments ago. I found that the animate suggestion was not good (jumpy, laggy, ultimately worse), but the supplied jQuery plugin that came with it was at least marginally better. For me, the overhead it required was not really worth the tiny gain.

In my situation, I have a scrollable div with one large image inside. The larger this image is, the worse the reflow. I was able to quite drastically improve the situation by hiding the div immediately before setting the scroll properties, then showing it again immediately afterward. This allows IE to ignore re-rendering the contents after the first property is set, and instead wait until the element is "visible" again (after they are both set).

There doesn't seem to be any flicker in any current version of any major browser (which was my first concern). Tested in Firefox 4, Opera 11, Chrome 10, IE 8, IE8 Compatibility, and Safari 5.

In jQuery:

var my_pane = $('#my_scroll_pane');
my_pane.css( 'visibility', 'hidden' );
my_pane.scrollTop( 100 ).scrollLeft( 100 );
my_pane.css( 'visibility', 'visible' );

Regular ole' JavaScript:

var scroll_pane = document.getElementById('my_scroll_pane');
scroll_pane.style.visibility = 'hidden';
scroll_pane.scrollTop = 100;
scroll_pane.scrollLeft = 100;
scroll_pane.style.visibility = 'visible';

UPDATE: This does flicker pretty roughly in FF3.6. If anybody has any ideas that don't involve browser sniffing, any input would be welcome.

Slobaum
  • 669
  • 7
  • 17
1

You should not be using scrollLeft and scrollTop, you should be setting the scrollLeft and scrollTop using .animate().

.animate({
    .scrollLeft: x,
    .scrollTop: y
})

There are also several plugins built from http://plugins.jquery.com/project/ScrollTo to simplify the process.

S16
  • 2,963
  • 9
  • 40
  • 64
0

I would imagine that an animation would be the best method for this (most JavaScript frameworks will do it), but you could also try this:

setTimeout("verticalScrollFunction", 1);
setTimeout("horizontalScrollfunction", 1);
Brad Wilkie
  • 331
  • 4
  • 12
0

You might be able to use Object.assign:

const {scrollLeft, scrollTop} = computeGoodScrollPosition(myDiv);
Object.assign(myDiv, {
  scrollLeft,
  scrollTop
});
Cris
  • 41
  • 1
  • 4
-1

Use absolute positioning or minus margin rather than scrolling.