Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Large background images causing lag while scrolling

The website I am building has 4 large background images that take up the entire height and width of the user's browser. They are implemented as CSS background divs. The problem is, when scrolling on larger screen sizes, it is very laggy and choppy. Scrolling between these images is done automatically via JavaScript when the user presses a button, so this is part of the core functionality of my website and I must find a way to prevent lag.

So far, I have tried preloading the images via JS and converting the images from PNG to JPEG (increase compression and decrease quality) server-side. Neither of these worked.

The minimum height of the image can be 630 pixels. How can I prevent lag while scrolling between sections?

Here's my code:

CSS:

 body { height: 100%; margin: 0px; font-family: HelveticaNeue, Helvetica, Arial, sans-serif; }

 .area { height: 630px; border: 0px solid red; background: repeat-x; margin-bottom: 0px; }

 a { text-decoration: none; }
 h1, h2, h3, h4, h5, h6 { font-family: Av, Helvetica, Arial, sans-serif; color: #292E37; font-weight: lighter; }

 #top { position: fixed; width: 100%; height: 10%; background: #292E37; box-shadow: inset 0px -1px 5px #000; z-index: 1000; }
 #navigation { float: right; height: 100%; }
 #bottom { width: 100%; position: fixed; bottom: 0px; padding: 10px; background: #292E37; box-shadow: inset 0px 1px 5px #000; text-shadow: 0px 1px 0px #000; color: #fff; }
 #sceneSelection { top: 20%; position: fixed; padding: 10px; }
 #info { margin-top: 50px; margin-bottom: 50px; }
 .box { margin-top: 50px; padding: 75px; background: #292E37; box-shadow: inset 0px 1px 5px #000; text-shadow: 0px 1px 0px #000; color: #fff; }

 .nav { position: relative; top: 38%; height: 100%; margin-right: 35px; display: inline-block;  color: #fff; text-shadow: 0px 1px #000; }
 .nav:hover { color: #EA5555; }

 .nimage { float: left; width: 16px; height: 16px; position: relative; top: 5%; left: -20%; }
 .home { background: url(site_images/icons/nav/home.png); }
 .pricing { background: url(site_images/icons/nav/pricing.png); }
 .features { background: url(site_images/icons/nav/features.png); }
 .blog { background: url(site_images/icons/nav/blog.png); }
 .contact { background: url(site_images/icons/nav/contact.png); }
 .about { background: url(site_images/icons/nav/us.png); }

 .logo { font-size: 2em; text-shadow: 0px 1px #000; padding-top: 10px;  padding-left: 15px; color: #EA5555; font-family: Av, Helvetica, Arial, sans-serif; }
 .red { color: #EA5555; }
 .white { color: #fff; text-shadow: 0px 1px 0px #000; font-weight: bold; }
 .dark { color: #202020; }

 .center { text-align: center; }
 .left { text-align: left; }
 .right { text-align: right; }

 .larger { font-size: 1.25em; }


 .buttoni { -webkit-border-radius: 2px; -moz-border-radius: 0px; border-radius: 4px; background: #ddd; display: block; color: #ccc; font-size: 14pt; height: 50px; text-align: right; margin: 10px; cursor: pointer; color: #505050; }
 .buttoni:hover { background: #EA5555; color: #fff; }

 .btext { padding: 15px; position: relative; top: 25%; }

 .groundi { background: url(ground_button.png); }
 .skyi { background: url(sky_button.png); }
 .stratospherei { background: url(stratosphere_button.png); }
 .spacei { background: url(space_button.png); }

 .image { height: 50px; width: 50px; float: left; border-top-left-radius: 5px; border-bottom-left-radius: 5px; }

 li { color: #EA5555; }
 li span { color: #505050; }

HTML:

  <div class="space area" id="a4">

  </div>
  <div class="stratosphere area" id="a3">

  </div>
  <div class="sky area" id="a2">

  </div>
  <div class="ground area" id="a1">

  </div>

JavaScript:

function scroll_to(id, speed, margin) {
         $('html, body').animate({
           scrollTop: $('#' + id).offset().top - margin
         }, speed);
       }

function match_height() {
         var heights = [11, 630, 693, 756, 819, 882, 945, 1008, 1071, 1134, 1197, 1260, 1323, 1386, 1449, 1512, 1575, 1638, 1701, 1764, 1827, 1890, 1953, 2016, 2079, 2142, 2205, 2268, 2331, 2394, 2457, 2520];

           var browsery = $(window).height();


           var i = 0;

           while(browsery > heights[i]) {
             i++;
           }

           var h = heights[i];

           $(".area").css("height", h + "px");
           $(".area").css("width", "100%");

           $(".ground").css("background", "url(scenes/ground/" + h + ".png)");

           $(".sky").css("background", "url(scenes/sky/" + h + ".png)");
           $(".stratosphere").css("background", "url(scenes/stratosphere/" + h + ".png)");

           $(".space").css("background", "url(scenes/space/" + h + ".png)");


       }

       match_height();

       var pos = 0;

       $(".buttoni").click(function() {
         var id = $(this).attr("id");

         if(pos != id) {
           scroll_to("a" + id, 2000, 0);
         }

         pos = id;
       });
like image 307
flowers Avatar asked Sep 16 '12 02:09

flowers


People also ask

How can I fix my background image while scrolling?

To keep your background fixed, scroll, or local in CSS, we have to use the background-attachment property. Background-attachment: This property is used in CSS to set a background image as fixed or scroll. The default value of this property is scroll.

What is the use of infinite scrolling background image?

The idea here is to create the appearance of a slideshow without the carousel. In other words, we're making a series of images the slide from left to right and repeat once the end of the images has been reached.


3 Answers

OP,

For browsers that support 3d transforms, e.g.: -webkit-transform, you could try the following:

your.div { -webkit-transform: translate3d(0,0,1px); }

Might not look like much, but doing the above causes the div in question to be hardware-accelerated.

Should you run into any flickering issues—they've been known to turn up in some cases—the following should sort you out:

your.div { 
    -webkit-transform: translate3d(0,0,1px); 
    -webkit-backface-visibility: hidden;
}

Via David Walsh - http://davidwalsh.name/translate3d

The use of translate3d pushes CSS animations into hardware acceleration. Even if you're looking to do a basic 2d translation, use translate3d for more power! If your animation is still flickering after switching to the transform above, you can use a few little-known CSS properties to try to fix the problem

Hope that helps.

like image 178
couzzi Avatar answered Nov 09 '22 05:11

couzzi


As per my understanding, the issue and the solution drafted in the OP is two-fold:

  • initially, within the match_height() function, the OP author retrieves the images that best fits the screen height, so that upon completed animation the user sees one full background image.
  • after initial load, the user can navigate up and down the sections (with their respective background images) with the help of some buttons that trigger the scroll_to() function and its contained animation. Here is where the actual problem resides.

My efforts and the resulting fiddle focus on the scroll_to() function and the associated animation. I applied the following measures that, in conjunction, result in a (as per my subjective observation) 'smoother' scolling experience:

  • the original animation happened against 'html' and 'body', I'm reducing the jQuery selector to one selector only. In order to be able to use jQuery 1.9 (where jQuery.browser is deprecated) I'm using feature detection to get the 'right' selector:

    function getScrollerSelector() {
        var $body = $("<body/>");
        $body.scrollTop(1);
        return $body.scrollTop() == 1 ? "body" : "html";
    }
    
  • In order to reduce the browser's processing load, I'm applying a logic that, per CSS, sets the background image of invisible sections to none during scrolling:

    .scrolldown.scrollto-a2 #a1,
    .scrolldown.scrollto-a3 #a1, .scrolldown.scrollto-a3 #a2,
    .scrolldown.scrollfrom-a3 #a4,
    .scrolldown.scrollfrom-a2 #a4, .scrolldown.scrollfrom-a2 #a3,
    .scrollup.scrollto-a3 #a4,
    .scrollup.scrollto-a2 #a4, .scrollup.scrollto-a2 #a3,
    .scrollup.scrollfrom-a2 #a1,
    .scrollup.scrollfrom-a3 #a1, .scrollup.scrollfrom-a3 #a2
        { background: none; }
    
  • I played around with linear easing, but that did not necessarily improve anything

All in all, scrolling doesn't seem choppy to me any more, but please take into account that this is also dependent on the client computers processing power.

Here's the scroll_to() function:

function scroll_to(id, speed, margin) {
    var currentScrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
    var scrollTop = $('#' + id).offset().top - margin;
    var direction = scrollTop > currentScrollTop ? "down" : "up";
    $("body").addClass("scroll"+direction + " scrollto-"+id + " scrollfrom-"+getScrollFrom(direction));
    $( scrollerSelector ).animate({
             scrollTop: scrollTop
        }, {
             //easing: 'linear',
             duration: speed,
             complete: function() {
                 $("body").removeClass("scrollup scrolldown scrollto-a1 scrollto-a2 scrollto-a3 scrollto-a4 scrollfrom-a1 scrollfrom-a2 scrollfrom-a3 scrollfrom-a4");                     
             }
         }
     );
}

This is the link to jsfiddle

like image 31
marty Avatar answered Nov 09 '22 06:11

marty


Since you are Scaling up the image, you can tell the Browser how to handle the rendering of image. During the animation / scrolling, you can tell browser to Optimize on Speed and on completion of Animation / scrolling, Optimize on Quality.

Here is the CSS Property you can use on img: 'image-rendering' with values as optimizeSpeed / optimizeQuality.

https://developer.mozilla.org/en-US/docs/CSS/image-rendering

like image 45
Neeraj Avatar answered Nov 09 '22 06:11

Neeraj