How to Create Paralax Content with jQuery

The simple idea behind paralax scrolling is to move down content while scrolling down and to move up while scrolling up.

Sounds complicated but it's actually pretty simple.

You need 3 functions:

  1. A fuction that will check if element is visible part of the screen.
  2. A fuction that will move the background up or down.
    I use transform: translateY, beacause it costs less RAM and CPU. For older browsers I use a CSS 'top' property.
  3. A fuction that will detect browser prefixes (e.g. -moz-, -webkit-).

The HTML I've used is:


<div class="simple-paralax">
    <img src="image.png" class="simple-paralax-image">
    <div class="simple-paralax-content">Example Content</div>
</div>

And a several lines of CSS:

.simple-paralax{
  position: relative;
  overflow: hidden;
}

.simple-paralax-image{
  height: auto;
  position: absolute;
  top: 0;
  left: 0;
  width: auto;
  min-width: 100%;
}

The image is with position absolute and is behind the content.

As the image is manipulated with by its classname, you can put another element instead(e.g. video, iframe, div)


So lets start with defining the name of the Object and require jQuery. I call it SimpleParalax :)


  <script src="path/to/jquery.js"></script>
  <script>

  (function(){
    if(!!this.window && !this.SimpleParalax){
        SimpleParalax = {};
    }
  })();
  <script>

Second we have to detect which transform property does the browser supports.

Note: When detecting browser features, you have to do it only once per feature, and then store it in a global variable.


transform : function(){
    if(!!this._transform){
      return this._transform;
    }
    this._transform = '';
    var prefixes = ['transform', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform'],
      test = document.createElement('div'), i = 0, l = prefixes.length;
      for( ; i < l; i++) {
          if(test.style[prefixes[i]] !== undefined) {
              this._transform = prefixes[i];
              break;
          }
      }
      return this._transform;
}

Next lets detect if a specific element is visible on the screen. This function only detects if whole or part of the element is visible.


isInview : function(el){
    var $el = $(el);
    if($el.length === 0) { return false; }
    var dt = $(window).scrollTop(),
        db = dt + $(window).height(),
        et = $el.offset().top;
    return (et <= db) && !(dt > ($el.height() + et));
}

And the core of the functionality:


set:function(){
  $(".simple-paralax-image").each(function(){
        if(SimpleParalax.isInview(this)){
          var pos = ($(window).scrollTop() - $(this).parent().offset().top)/2;
          var transform = SimpleParalax.transform();
          if(transform != ''){
            /* Check if transform property is supported. */
            $(this).css(transform, 'translateY('+pos+'px)');
          }
          else{  /* Fallback for older browsers. */
            $(this).css('top', pos);
          }
        }
    });
}

And now lets combine everything and add and 'init' function.


  (function(){
    if(!!this.window && !this.SimpleParalax){
        SimpleParalax = {
          transform : function(){
            if(!!this._transform){
              return this._transform;
            }
            this._transform = '';
            var prefixes = ['transform', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform'],
              test = document.createElement('div'), i = 0, l = prefixes.length;
              for( ; i < l; i++) {
                  if(test.style[prefixes[i]] !== undefined) {
                      this._transform = prefixes[i];
                      break;
                  }
              }
              return this._transform;
          },
          isInview : function(el){
              var $el = $(el);
              if($el.length === 0) { return false; }
              var dt = $(window).scrollTop(),
                  db = dt + $(window).height(),
                  et = $el.offset().top;
              return (et <= db) && !(dt > ($el.height() + et));
          },
          set:function(){
            $(".simple-paralax-image").each(function(){
                  if(SimpleParalax.isInview(this)){
                    var pos = ($(window).scrollTop() - $(this).parent().offset().top)/2;
                    var transform = SimpleParalax.transform();
                    if(transform != ''){
                      $(this).css(transform, 'translateY('+pos+'px)');
                    }
                    else{
                      $(this).css('top', pos);
                    }
                  }
              });
          },
          init:function(){
            $(document).ready(function(){
               $(".simple-paralax").css('minHeight', $(window).height());
               SimpleParalax.set();
            });
            $(window).bind('load resize scroll', function(e){
                SimpleParalax.set();
                if(e.type=='load' || e.type=='resize'){
                  $(".simple-paralax").css('minHeight', $(window).height());
                }
                if(e.type=='load' || e.type=='resize'){
                    $(".simple-paralax-image").each(function(){
                        var el = $(this), h = el.parent().height(), h = h+(h/2);
                        el.height(h);
                    });
                }
            });
          }
        }
        SimpleParalax.init();
    }
  })();

In this example I have made every conatainer to have for a minimum height the height of the window.