45

On my I have a fixed DIV at the top, 3 fixed tabs and a fixed div at the bottom (this will only be shown when logged in - in the future).

I am getting poor scrolling performance on Chrome only - FF & IE are fine.

I have ready some problem reports about Chrome, Fixed Positioning and Scrolling and wanted to see if anyone had any suggestions? I really would like to fix these elements in their locations but I would also like good scrolling performance in Chrome.

Any Ideas on a fix?

Note: its much more noticeable when zoomed on chrome...

Update: I have read other people have a similar issues and updated this Chrome issue, which was later merged into 136555, allegedly fixed since Chrome 26.

Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
Adam
  • 19,932
  • 36
  • 124
  • 207
  • 1
    Any news on this issue? I was about to make a similar question. – DBUK Feb 06 '13 at 10:42
  • as far i can see, firefox and chrome have the same performance on Linux(ubuntu) – osdamv Feb 28 '13 at 23:17
  • @Adam Mind selecting best answer? I know this is super old now (and was answered super late since I was researching the problem at a different time and just sharing the answer), but I just updated it since it still seems to get attention. – corylulu Sep 07 '16 at 19:18

5 Answers5

86

Problem and How to Monitor It

The reason for this is because Chrome for some reasons decides it needs to redecode and resize any images when a fixed panel goes over it. You can see this particularly well with

Right-Click Inspect Timeline Hit ⏺ Record

► Go back to the page and drag scrollbar up and down (Mouse-wheel scrolling not as effective)

Edit (9/1/2016): Since posting this, Chrome added new features to help monitor this:

Right-Click Inspect Rendering (Bottom tabs)

     ☑ Scrolling Performance Issues
     ☑ Paint Flashing
     ☑ FPS Meter (less important, but can be useful)

This will help you identify exactly what elements require repaints on scrolls and highlight them clearly on screen.

This seems to just be a problem with the method Chrome is using to determine if a lower element needs to be repainted.

To make matters worse, you can't even get around the issue by creating a div above a scrollable div to avoid using the position:fixed attribute. This will actually cause the same effect. Pretty much Chrome says if anything on the page has to be drawn over an image (even in an iframe, div or whatever it might be), repaint that image. So despite what div/frame you are scrolling it, the problem persists.

.

The Easy Hack Solution

But I did find one hack to get around this issue that seems to have few downside.

By adding the following to the fixed elements

/* Edit (9/1/2016): Seems translate3d works better than translatez(0) on some devices */
-webkit-transform: translate3d(0, 0, 0);

Some browsers might require this to prevent flickering

-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;

This puts the fixed element in its own compositing layer and forces the browser to utilize GPU acceleration.

EDIT: One potential issue was pointed out to me by albb; when using transform, all descendant position:fixed elements will be fixed to that composition layer rather than the entire page.

.

Alternative Solution

Alternatively, you could simply hide the top navigation while scrolling and bring it back in afterwards. Here is an example that could work on the stackoverflow.com's header or a site like theverge.com if pasted in DevTools > Console (or manually type "javascript:" into this pages URL bar and paste in the code below after it and hit enter):

/* Inject some CSS to fix the header to the top and hide it
 * when adding a 'header.hidden' class name. */
var css= document.createElement("style");
css.type = 'text/css'; 
css.innerHTML = 'header { transition: top .20s !important; }';
css.innerHTML += 'header.hideOnScroll { top: -55px !important; }';
css.innerHTML += 'header { top: 0 !important; position: fixed !important; }';
document.head.appendChild(css);

var header = document.querySelector("header");
var reinsertId = null; /* will be null if header is not hidden */

window.onscroll = function() {
    if(!reinsertId) { 
      /* Hides header on scroll */
      header.classList.add("hideOnScroll");
      setTimeout(function() { header.style.visibility = "hidden"; }, 250);
    } else {
      /* Resets the re-insert timeout function */
      clearTimeout(reinsertId);
    }
    /* Re-insert timeout function */
    reinsertId = setTimeout(function(){
      header.classList.remove("hideOnScroll");
      header.style.visibility = "visible";
      reinsertId = null;
    }, 1500);
};
corylulu
  • 3,449
  • 1
  • 19
  • 35
  • 2
    One downside for "-webkit-transform" is, "position: fixed;" descendants will use it as container, rather than the screen. https://bugs.webkit.org/show_bug.cgi?id=110478 Moving those elements out and everything works fine. – albb Dec 12 '13 at 07:43
  • @albb That's interesting to know. However, it seems kinda odd that you would need a child element that is position fixed. However, I can understand when it can come up when using more dynamic layouts or customizable user-styles or themeing. I haven't done tests recently though regarding this issue. I'm not even sure if the scroll performance is still greatly hindered like it used to be in ~Chrome 22. – corylulu Dec 12 '13 at 20:31
  • @albb I edited the post to mention this bug though, thanks for the heads up. – corylulu Dec 12 '13 at 21:03
  • Thank you for this! – Manos Serifios Mar 27 '18 at 08:39
16

The first solution of @Corylulu works, but not completely (still a little stutter, but much less). I also had to add -webkit-backface-visibility: hidden; to the fixed element to be stutter free.

So for me the following worked like a charm to prevent scroll down stutter in chrome when using fixed elements on the page:

-webkit-transform: translateZ(0);
-webkit-backface-visibility: hidden;

Edit: Webkit-transform and webkit-backface-visibility both cause blurry fonts and images. So make sure you only apply both on the hover state.

  • 1
    your fix fixed my problem. Slow scrolling Chrome now it's back to good scrolling. I thought it's a problem of so much styling on my elements displayed in my scrolling DIV. Anyway, now works. Thumbs up for the solution. – Adrian Tanase Oct 30 '15 at 18:01
  • This fix helped me too! Thank you :) – DiChrist Aug 21 '17 at 19:09
  • do i keep my div fixed? do these styles belong on the scrollable div on its fixed parent? – Omar Aug 28 '22 at 12:30
5

Add this rule to your fixed element,

will-change: transform;

Read about solution from Here,
and read about will-change property from Here.

Az.Youness
  • 2,167
  • 1
  • 24
  • 33
2

There's a recent bug report on this particularly annoying issue: http://code.google.com/p/chromium/issues/detail?id=155313

It has to do with the combination of floating elements and large images. Still a problem on Chrome Canary 24.0.1310.0.

surj
  • 4,706
  • 2
  • 25
  • 34
1

There are a number of ways you could speed up this front end, try out the PageSpeed Insights Chrome plugin for some ideas. Personally I'd recommend rebuilding this front end with the same design on top of a framework like Twitter's Bootstrap, but if you'd like some specifics on this front end:

  • As you say, the positioning of your header bar is causing the most time in terms of CSS rendering (CSS stress test results). Get rid of that big image that's in there and replace it with a 1px wide background image. You're also resizing images like your logo (and every other image in this header) unnecessarily, replace with actual-size versions
  • You could save a lot of bytes transferred by optimizing all your content images
Alec Rust
  • 10,532
  • 12
  • 48
  • 63