Chrome slow scrolling with fixed position elements - html

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.

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

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.

Add this rule to your fixed element,
will-change: transform;
Read about solution from Here,
and read about will-change property from Here.

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.

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

Related

Form shifts to the left after making selections

On mobile (or desktop with small window size to replicate mobile, as per the screenshots) the form on my page loads fine with default dates, but when a new date range is selected the form shifts to the left after making the selection (or rather, a gap is inserted to the right) but I can't find anything using F12 developer tools that is causing it. It is not possible to scroll to the left.
On page load:
After selecting dates:
The form itself is displayed by embedding a third party JavaScript link on the page - is there anything I can do to prevent this from happening? I can't figure it out!
Note: The page uses a YouTube video background which is blocked by the firewall where I am working from at the moment (hence the grey background), but is not causing any JavaScript errors. The problem is the same on all mobiles and on networks where the background is able to load.
Live example at #########.com (address will be removed when resolved)
Thanks
UPDATE: As per the answer from Wouter, removing the overflow: hidden from <section class="gg-section hero video-home" id="dots-section1"> fixes the issue, but unfortunately that causes other layout problems so cannot be applied.
The problem is likely to be caused by the video being 300% width. Try to set a overflow: hidden; to the following element:
<div class="video-background">
May not help but..
I had a similar issue with page jumping and forms before.
It was caused by an <input class="hiddencheckbox" type="checkbox" />.
Every time I used js select/deselect the checkbox, the browser would try and jump to the checkbox position, which I had hidden by moving its position outside the viewport.
.hiddencheckbox {
position:fixed;
right: -1000px;
// BAD WITH JS
}
I removed the positioning and changed it to:
.hiddencheckbox {
display:none;
}

how to disable scrolling on background divs in mobile web application

in mobile web application I'd often use modals.
Some modals can expand sizes and thus were made scrollable.
How can I enable higher z-indexed modal to be scrollable and set background div not to scroll?
b/c whenever I scroll with two fingers on the current modal, sometimes background scroll, sometimes foreground scrolls.
I think you can't fix background with background-attachment: fixed;
you have to apply position: fixed on it
and then
You should try iScroll 4
"iScroll finally received a complete rewrite. Now it’s smoother than ever and adds some new important features: pinch/zoom, pull down to refresh, snap to elements and more custom events for a higher level of hackability."
or
skrollr 0.6.25
Stand-alone parallax scrolling JavaScript library for mobile (Android, iOS, etc.) and desktop in about 12k minified.
Other Helpful link
http://webdesigner-webdeveloper.com/weblog/fullscreen-images-for-the-ipad-ios-and-mobile-safari/
https://github.com/louisremi/background-size-polyfill/issues/27
http://bradfrostweb.com/blog/mobile/fixed-position/
Hope this answer little bit helpful for you. :)
There are a couple "hacky" ways to get this working. Here are a couple off the top of my head (that I've experimented with in the past) - if you're targeting iOS devices, just skip to #3...
1) Use JS and prevent scrolling. You would want to check if the element within the modal is scrollable or not. If it's not, you disable touch events, preventing the user from scrolling. Be mindful of direction. Also, devices that would typically "rubberband" the scroll will stop.
Sorry, no fiddle to demonstrate.
2) Apply absolute positioning to the body element with overflow hidden. As weird as it sounds, if you apply absolute position to the body, you can prevent the page from scrolling. However, layout issues might prevent you from using this. In addition, when you apply the position to the body, any scroll offset will be removed, and the page will scroll to 0,0. Also, the page will still rubberband (if the device supports rubberbanding) resulting in a weird interaction.
JS fiddle: http://fiddle.jshell.net/L7FJF/show/
3) If you're targeting iOS devices (or newer Chrome browsers on Android), there's a fun workaround when using -webkit-overflow-scrolling: touch and rubberbanding. Using JS, you can always offset the scrollable div +/-1px to prevent background scrolling. (To be honest, this is my favorite work around since it works great. However, it's limited to just iOS w/ overflow-scrolling support.)
JS fiddle: http://fiddle.jshell.net/jDqSP/show/
Hope this helps!
assume the only div you want to allow to scroll is
<div class="scroll">...</div>
here is the code. works on ios and android, also handled the problem that when son has scrolled to end, parent's scroll will automatically be triggered.
$(document).on('touchmove', function(e) {
e.preventDefault();
}).ready(function() {
$('.scroll').on('touchstart', function(e) {
this.allowUp = (this.scrollTop > 0);
this.allowDown = (this.scrollTop < this.scrollHeight - this.clientHeight);
this.prevTop = null;
this.prevBot = null;
this.lastY = e.originalEvent.touches[0].clientY;
}).on('touchmove', function(e) {
var event = e.originalEvent;
var up = (event.touches[0].clientY > this.lastY), down = !up;
this.lastY = event.touches[0].clientY;
if ((up && this.allowUp) || (down && this.allowDown))
event.stopPropagation();
else
event.preventDefault();
});
});
when you don't need to ban scroll, you just remove the listener like this:
document.addEventListener('touchmove', handleTouchMove, false);
document.removeEventListener('touchmove', handleTouchMove);
from
https://stackoverflow.com/a/13278230/1982712 & prevent full page scrolling iOS
(which is the questioner's own answer).
(my main account has been banned :( )
I was facing same problem and CSS property touch-action: none; solved my problem on iPhone with Safari browser. More infrmation here https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action

How can I prevent the scrollbar overlaying content in IE10?

In IE10, the scrollbar is not always there... and when it appears it comes on as an overlay... It's a cool feature but I would like to turn it off for my specific website as it is a full screen application and my logos and menus are lost behind it.
IE10:
CHROME:
Anyone know a way of always having the scrollbar fixed in position on IE10?
overflow-y:scroll doesn't seem to work! it just puts it permanently over my website.
It may be bootstrap causing the issue but which part I have no idea! see example here: http://twitter.github.io/bootstrap/
As xec mentioned in his answer, this behavior is caused by the #-ms-viewport setting.
The good news is that you do not have to remove this setting to get the scrollbars back (in our case we rely on the #-ms-viewport setting for responsive web design).
You can use the -ms-overflow-style to define the overflow behavoir, as mentioned in this article:
http://msdn.microsoft.com/en-us/library/ie/hh771902(v=vs.85).aspx
Set the style to scrollbar to get the scrollbars back:
body {
-ms-overflow-style: scrollbar;
}
scrollbar
Indicates the element displays a classic scrollbar-type
control when its content overflows. Unlike -ms-autohiding-scrollbar,
scrollbars on elements with the -ms-overflow-style property set to
scrollbar always appear on the screen and do not fade out when the
element is inactive. Scrollbars do not overlay content, and therefore
take up extra layout space along the edges of the element where they
appear.
After googling a bit I stumbled across a discussion where a comment left by "Blue Ink" states:
Inspecting the pages, I managed to reproduce it by using:
#-ms-viewport { width: device-width; }
which causes the scrollbars to become transparent. Makes sense, since
the content now takes up the whole screen.
In this scenario, adding:
overflow-y: auto;
makes the scrollbars auto-hide
And in bootstraps responsive-utilities.less file, line 21 you can find the following CSS code
// IE10 in Windows (Phone) 8
//
// Support for responsive views via media queries is kind of borked in IE10, for
// Surface/desktop in split view and for Windows Phone 8. This particular fix
// must be accompanied by a snippet of JavaScript to sniff the user agent and
// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at
// our Getting Started page for more information on this bug.
//
// For more information, see the following:
//
// Issue: https://github.com/twbs/bootstrap/issues/10497
// Docs: http://getbootstrap.com/getting-started/#support-ie10-width
// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/
// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/
#-ms-viewport {
width: device-width;
}
This snippet is what's causing the behavior. I recommend reading the links listed in the commented code above. (They were added after I initially posted this answer.)
SOLUTION: Two steps - detect if IE10, then use CSS:
do this on init:
if (/msie\s10\.0/gi.test(navigator.appVersion)) {
$('body').addClass('IE10');
} else if (/rv:11.0/gi.test(navigator.appVersion)) {
$('body').addClass('IE11');
}
// --OR--
$('body').addClass(
/msie\s10\.0/gi.test(navigator.appVersion) ? 'IE10' :
/rv:11.0/gi.test(navigator.appVersion) ? 'IE11' :
'' // Neither
);
// --OR (vanilla JS [best])--
document.body.className +=
/msie\s10\.0/gi.test(navigator.appVersion) ? ' IE10' :
/rv:11.0/gi.test(navigator.appVersion) ? ' IE11' :
''; // Neither
Add this CSS:
body.IE10, body.IE11 {
overflow-y: scroll;
-ms-overflow-style: scrollbar;
}
Why it works:
The overflow-y:scroll permanently turns on the <body> tag vertical scrollbar.
The -ms-overflow-style:scrollbar turns off the auto-hiding behavior, thus pushing the content over and giving us the scrollbar layout behavior we're all used to.
Updated for users asking about IE11.
- Reference https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/ms537503(v=vs.85)
Try this
body{-ms-overflow-style: scrollbar !important;}
This issue is also happening with Datatables on Bootstrap 4. Mi solution was:
Checked if the ie browser is opening.
Replaced table-responsive class for table-responsive-ie class.
CSS:
.table-responsive-ie {
display: block;
width: 100%;
overflow-x: auto;}
JS:
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) //If IE
{
$('#tableResponsibleID').removeClass('table-responsive');
$('#tableResponsibleID').addClass('table-responsive-ie');
}
Tried the #-ms-viewport and other suggestions but none worked in my case with IE11 on Windows 7. I had no scroll bars and the other posts here would at most give me a scroll bar that didn't scroll anywhere even though there was plenty of content. Found this article http://www.rlmseo.com/blog/overflow-auto-problem-bug-in-ie/ which reduced to . . .
body {
overflow-x: visible;
}
. . . and did the trick for me.

Chrome redraw issue

I'm getting an odd redraw issue in chrome:
See the broken right side? This is a div with a single background img.
HTML
<div id="resultsSortFilter>
<!-- ... -->
</div>
CSS
#resultsSortFilter {
float: left;
width: 712px;
height: 109px;
margin: 7px 0 0 8px;
background: url('../images/search_sortfilter_bg.png') no-repeat;
}
No issues in any other browser
Happens on newer versions only, we blocked the update to prevent this causing issues internally.
Seems to be triggered by scrolling up and down before rendering is finished.
Same issues on multiple sites
Has anyone else seen this? Anybody knows what's causing it or what Chrome intends to do about it?
Chrome version 26.0.1410.64 m
Update
The issue is on Windows and Mac OS. In fact seems worse on Mac.
I might have pinned it down further. We get the error on a page that contains lots of large images. I'm wondering if it has to do with the size of the data Chrome has to download?
This appears to make the issue go away (not going to call it a fix):
"It might be that the newer version of Chrome simply does not like
your GPU. I have had issues similar to yours and have solved them by
turning off the compositing and 3D acceleration features.
Type
chrome://flags into the address bar and set the following items:
GPU compositing on all pages: Disabled (Three options in a drop-down.)
Disable accelerated 2D canvas: Enable (Click the link that says
'Enable', the box will turn white.)
Disable accelerated CSS
animations: Enable (Like above, the item will turn white.)
Then click
the button that shows up at the bottom of the page Relaunch now to
restart chrome and test if this worked."
From https://askubuntu.com/questions/167140/google-chrome-with-strange-behavior
Update
The issue seems to be gone in later versions of Chrome.
Chrome is getting buggier. Something worth trying is forcing gpu hardware acceleration on the element.
Add this to the CSS to force hardware acceleration:
-webkit-transform: translate3d(0, 0, 0);
I have had problems with this in webkit browsers, not only Chrome.
I solved it by placing the following rule on my CSS:
html *:not(svg) {
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0); /*only in IE10*/
}
This applies hardware acceleration on all elements except for svgs on FF/IE/Safari/Chrome if supported.
I do not apply the transformation on SVG tags since for some reason this was causing my svgs to not render properly, oddly applying this to the elements like rect inside the tag itself causes no problems.
So try to add this rule to your css and see if it solves your problem.
I have had this kind of issue when toggling display:none; display:block;
For example with jQuery.toggle()
The element in question was just a wrapper for the content I wanted to show and hide. So this is its parent which would expand or shrink vertically. It would look like this:
<div class="parent">
<div class="child-to-toggle">
</div>
</div>
child-to-toggle had no styling rules and, when hidden, a part of the parent wasn't redrawn correctly. (the bottom part)
Then, I added a css rule to child-to-toggle and the problem was solved. It looks like adding a css rule will force some redrawing in that case.
Despite the accepted answer, I am adding this one because enabling hardware acceleration on my computer, Macbook pro, OSX Maverick, Chrome 36, would completely mess up the UI with artefacts so I had to find another way.
Adding a css rule might help. In my case I added a border-top to child-to-toggle.

IE9 renders a white line in the bottom of the page

I recently noticed in several webpages, and some of my own, that when they are displayed in Internet Explorer 9, when its not on Quirks Mode, it renders a white line, about 1px, in the bottom of the page. It's like the html tag was with padding-bottom:1px and wrapped in another element with white background (but it's not, and it has no padding). It looks like the differences between IE9 standards and quirks mode shows when determining a wrapping element's width, but vertically. It also feels like the content of an element gets pushed 1px by a previous element, like their content, but, not margins or borders, were overlapping the next element dimensions.
I can't determine exactly what causes it. Sometimes, a page contains 2 tables and everything is fine. Then you need to add a third one, and the line shows up. Doesn't even need to be tables btw.
Sometimes, reseting css solves it. Setting the same line-height we have on body to links:
body {
line-height: 1
}
a, links, visited {
line-height: 1
}
fixes it, but not always. Only thing i can do, is check element by element, disabling/enabling their css rules till it's gone.
I noticed that when there are elements like tables, inputs, textareas, this issue is more likely to happen. 'resetting' their attributes, sometimes, solves it too.
I know it would be easier to provide a code as an example, but like i said, i coudn't determine a pattern for it. I can give you some examples of sites/urls i notice that error (you gotta look at the very bottom of the page and see the difference between IE and another browser, like Firefox):
casinosdelmundo.info, gatosabido.com.br, espanol.yahoo.com, en.wikipedia.org/wiki/Bruce_Beutler, ea.com/command-and-conquer-4, facebook.com (the ones with white, or almost white bg, change body background with f12, developer's tool, and you'll see). I found an example even here at stackoverflow (as today, the main page stackoverflow.com is showing that line too, but that can change since, sometimes the issue appears or disappears when new elements show up or are removed):
this question has the white-line:
Make link in table cell fill the entire row height
this one has not:
FireFox 3 line-height
Check this screenshot, if you still didn't see what im talking about:
the presence of this issue on very established (or not) sites makes me feel it's a IE9 bug and the only definitive fix for it is always use white background, so nobody will notice the white line (the line will still be there though). but thats obviously not the best option. I never found this white line in Chrome or Safari.
So, has anyone faced the same problem and got a better solution?
I'm not sure, cause there is no HTML here, but it is very resemble to standard browser behavior, when it displays inline content. It is due to the fact, that when text is displayed browser needs to leave some space at the bottom for letters and symbols such as: "," , "y" , "p" and so on, cause in that letters there is a part which protrudes to the bottom. You can better understand what I'm talking about when you look at this picture:
example of how inline content is displayed
so if you have some markup like
<body>
<div></div>
<textarea></textarea>
</body>
you'll get that extra space at the bottom. To get rid off it you have to use there either block element, or set to your inline-element a css style 'display: block'
I found a solution to the problem, if an idiotic one: set the toggle of your browser window's Maximize/Restore down to Maximize (= tooltip text; this indicates that the window is in a nonmaximal state). Make the browser window actually smaller than screen fit. Press F11 in this state and there is no white line at the bottom of your screen (Win7 x32 & x64). (BTW, FF dose not have this problem and is the best alternative.)
It happens when you use fractional font-sizes.
For example, stackoverflow uses h2 {font-size: 140%;} body { font-size:80%;}, which results in an total font-size of 112% for h2. Apply that to 16px default size, and you get 17.93px (including rounding errors, hooray!)
Try it yourself: getComputedStyle(document.querySelector('h2')).fontSize
Browsers have a hard time rendering fractional pixels, and thus may get confused and add a pixel at the bottom.
By the way, Firefox has some trouble too. The spacing between the footer lines is off by a pixel.
The fix is obvious: Use integer pixels to declare font-sizes.
Another way would be to apply a :after content to your body only for IE and Edge.
This way you will get rid of the extra white line.
We may require some jQuery too so that the content applies only when you are at the bottom of the page.
body{
position:relative;
width:100%;
}
body:after{
content: "";
display:block;
background-color: #000;
height: 1px;
bottom: 0px;
position: fixed;
width: 100%;
}
jQuery
//add a border to internet explorer
if (bowser.name == "Microsoft Edge" || bowser.name == "Internet Explorer") {
//console.log(" iam inside");
$(window).scroll(function () {
if ($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
$("body").addClass("end-border");
}
else {
$("body").removeClass("end-border");
}
});
}