├── README ├── scripts.js ├── reset.css ├── styles.css ├── jquery.scrollParallax.min.js ├── index.html ├── index-horizontal.html └── jquery.scrollParallax.js /README: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scripts.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | /* main background image. moves against the direction of scroll*/ 3 | $('.item').scrollParallax({ 4 | 'speed': -0.2 5 | }); 6 | 7 | /* inner items, moves slightly faster than the background */ 8 | $('.item .inner').scrollParallax({ 9 | 'speed': -0.5 10 | }); 11 | 12 | /* two additional samples inside item2, both moving with direction of scroll*/ 13 | $('.item .inner-lev1').scrollParallax({ 14 | 'speed': 0.2 15 | }); 16 | $('.item .inner-lev2').scrollParallax({ 17 | 'speed': 0.5 18 | }); 19 | }); -------------------------------------------------------------------------------- /reset.css: -------------------------------------------------------------------------------- 1 | /** 2 | * html5doctor.com Reset Stylesheet (Eric Meyer's Reset Reloaded + HTML5 baseline) 3 | * v1.6.1 2010-09-17 | Authors: Eric Meyer & Richard Clark 4 | * html5doctor.com/html-5-reset-stylesheet/ 5 | */ 6 | 7 | html, body, body div, span, object, iframe, 8 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 9 | abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, 10 | small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, 11 | fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, 12 | article, aside, canvas, details, figcaption, figure, 13 | footer, header, hgroup, menu, nav, section, summary, 14 | time, mark, audio, video { 15 | margin: 0; 16 | padding: 0; 17 | border: 0; 18 | font-size: 100%; 19 | vertical-align: baseline; 20 | } 21 | 22 | article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { 23 | display: block; 24 | } 25 | 26 | blockquote, q { quotes: none; } 27 | 28 | blockquote:before, blockquote:after, 29 | q:before, q:after { content: ""; content: none; } 30 | 31 | ins { background-color: #ff9; color: #000; text-decoration: none; } 32 | 33 | mark { background-color: #ff9; color: #000; font-style: italic; font-weight: bold; } 34 | 35 | del { text-decoration: line-through; } 36 | 37 | abbr[title], dfn[title] { border-bottom: 1px dotted; cursor: help; } 38 | 39 | table { border-collapse: collapse; border-spacing: 0; } 40 | 41 | hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; } 42 | 43 | 44 | /** 45 | * Font normalization inspired by YUI Library's fonts.css: developer.yahoo.com/yui/ 46 | */ 47 | 48 | body { font:13px/1.231 sans-serif; *font-size:small; } /* Hack retained to preserve specificity */ 49 | 50 | /* Normalize monospace sizing: 51 | en.wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome */ 52 | pre, code, kbd, samp { font-family: monospace, sans-serif; } -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | /* vertical version */ 2 | .items{ 3 | overflow:hidden; 4 | } 5 | .item{ 6 | width:100%; 7 | overflow:hidden; 8 | position:relative; 9 | height:768px; 10 | } 11 | .inner,.inner-lev1,.inner-lev2{ 12 | width:100%; 13 | height:100%; 14 | position:absolute; 15 | z-index:1; 16 | } 17 | .content{ 18 | background:rgba(255,255,255,0.9); 19 | background:white; 20 | padding:20px; 21 | width:300px; 22 | margin:30px; 23 | position:relative; 24 | z-index:2; 25 | } 26 | 27 | /* alterations for horizontal version */ 28 | .items-horizontal{ 29 | width:5120px; 30 | } 31 | .items-horizontal .item{ 32 | width:1024px; 33 | float:left; 34 | } 35 | 36 | /* parallax images */ 37 | .item1{ 38 | background: white url(http://lorempixum.com/1024/768/city/1) 0px 0px fixed no-repeat; 39 | } 40 | .inner1{ 41 | background: url(http://lorempixum.com/200/200/people/1) 400px 200px fixed no-repeat; 42 | } 43 | .item2{ 44 | background: white url(http://lorempixum.com/1024/768/city/2) 0px 0px fixed no-repeat; 45 | } 46 | .inner2{ 47 | background: url(http://lorempixum.com/200/200/people/2) 400px 200px fixed no-repeat; 48 | } 49 | .inner2a{ 50 | background: url(http://lorempixum.com/200/200/sports/1) 500px 250px fixed no-repeat; 51 | } 52 | .inner2b{ 53 | background: url(http://lorempixum.com/200/200/sports/2) 600px 300px fixed no-repeat; 54 | } 55 | .item3{ 56 | background: white url(http://lorempixum.com/1024/768/city/3) 0px 0px fixed no-repeat; 57 | } 58 | .inner3{ 59 | background: url(http://lorempixum.com/200/200/people/3) 400px 200px fixed no-repeat; 60 | } 61 | .item4{ 62 | background: white url(http://lorempixum.com/1024/768/city/4) 0px 0px fixed no-repeat; 63 | } 64 | .inner4{ 65 | background: url(http://lorempixum.com/200/200/people/4) 400px 200px fixed no-repeat; 66 | } 67 | .item5{ 68 | background: white url(http://lorempixum.com/1024/768/city/5) 0px 0px fixed no-repeat; 69 | } 70 | .inner5{ 71 | background: url(http://lorempixum.com/200/200/people/5) 400px 200px fixed no-repeat; 72 | } -------------------------------------------------------------------------------- /jquery.scrollParallax.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net) 3 | * backgroundPosition cssHook for jquery. Necessary to combat different css property names between browsers 4 | * https://github.com/brandonaaron/jquery-cssHooks 5 | * Licensed under the MIT License (LICENSE.txt). 6 | */ 7 | (function(c){var a=c('
');c.support.backgroundPosition=a.css("backgroundPosition")==="3px 5px"?true:false;c.support.backgroundPositionXY=a.css("backgroundPositionX")==="3px"?true:false;a=null;var d=["X","Y"];function b(g){var f=g.split(/\s/),e={X:f[0],Y:f[1]};return e}if(!c.support.backgroundPosition&&c.support.backgroundPositionXY){c.cssHooks.backgroundPosition={get:function(g,f,e){return c.map(d,function(h,j){return c.css(g,"backgroundPosition"+h)}).join(" ")},set:function(e,f){c.each(d,function(j,g){var h=b(f);e.style["backgroundPosition"+g]=h[g]})}}}if(c.support.backgroundPosition&&!c.support.backgroundPositionXY){c.each(d,function(f,e){c.cssHooks["backgroundPosition"+e]={get:function(j,i,g){var h=b(c.css(j,"backgroundPosition"));return h[e]},set:function(h,j){var g=b(c.css(h,"backgroundPosition")),i=e==="X";h.style.backgroundPosition=(i?j:g.X)+" "+(i?g.Y:j)}};c.fx.step["backgroundPosition"+e]=function(g){c.cssHooks["backgroundPosition"+e].set(g.elem,g.now+g.unit)}})}})(jQuery); 8 | /*! 9 | * Scroll-based parallax plugin for jQuery 10 | * Copyright (c) 2011 Dave Cranwell (http://davecranwell.com) 11 | * Licensed under the MIT License. 12 | * 2011-05-18 13 | * version 1.0 14 | */ 15 | (function(a){a.fn.scrollParallax=function(c){var d={speed:0.2,axis:"x,y",debug:false};function b(e){if(d.debug&&"console" in window&&"log" in window.console){console.log(e)}}return this.each(function(){var h=a(this);if(c){a.extend(d,c)}h.bind("inview",function(i,j){if(j==true){h.addClass("inview");b("in view")}else{h.removeClass("inview");b("out of view")}});var f=h.css("backgroundPosition").split(" ");var g=parseInt(f[0].replace(/[^0-9\-]/g,""));var e=parseInt(f[1].replace(/[^0-9\-]/g,""));a(window).bind("scroll",function(){if(h.hasClass("inview")){var l=h.offset();if(d.axis.match(/x/)){var m=l.left-a(window).scrollLeft();var k=(-(m)*d.speed)+g}else{var k=g}if(d.axis.match(/y/)){var j=l.top-a(window).scrollTop();var i=(-(j)*d.speed)+e}else{var i=e}b("new X position: "+k);b("new Y position: "+i);h.css({backgroundPosition:parseInt(k)+"px "+parseInt(i)+"px"})}})})}})(jQuery); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /index-horizontal.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /jquery.scrollParallax.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net) 3 | * backgroundPosition cssHook for jquery. Necessary to combat different css property names between browsers 4 | * https://github.com/brandonaaron/jquery-cssHooks 5 | * Licensed under the MIT License (LICENSE.txt). 6 | */ 7 | (function($) { 8 | // backgroundPosition[X,Y] get hooks 9 | var $div = $('
'); 10 | $.support.backgroundPosition = $div.css('backgroundPosition') === "3px 5px" ? true : false; 11 | $.support.backgroundPositionXY = $div.css('backgroundPositionX') === "3px" ? true : false; 12 | $div = null; 13 | 14 | var xy = ["X","Y"]; 15 | 16 | // helper function to parse out the X and Y values from backgroundPosition 17 | function parseBgPos(bgPos) { 18 | var parts = bgPos.split(/\s/), 19 | values = { 20 | "X": parts[0], 21 | "Y": parts[1] 22 | }; 23 | return values; 24 | } 25 | 26 | if (!$.support.backgroundPosition && $.support.backgroundPositionXY) { 27 | $.cssHooks.backgroundPosition = { 28 | get: function( elem, computed, extra ) { 29 | return $.map(xy, function( l, i ) { 30 | return $.css(elem, "backgroundPosition" + l); 31 | }).join(" "); 32 | }, 33 | set: function( elem, value ) { 34 | $.each(xy, function( i, l ) { 35 | var values = parseBgPos(value); 36 | elem.style[ "backgroundPosition" + l ] = values[ l ]; 37 | }); 38 | } 39 | }; 40 | } 41 | 42 | if ($.support.backgroundPosition && !$.support.backgroundPositionXY) { 43 | $.each(xy, function( i, l ) { 44 | $.cssHooks[ "backgroundPosition" + l ] = { 45 | get: function( elem, computed, extra ) { 46 | var values = parseBgPos( $.css(elem, "backgroundPosition") ); 47 | return values[ l ]; 48 | }, 49 | set: function( elem, value ) { 50 | var values = parseBgPos( $.css(elem, "backgroundPosition") ), 51 | isX = l === "X"; 52 | elem.style.backgroundPosition = (isX ? value : values[ "X" ]) + " " + 53 | (isX ? values[ "Y" ] : value); 54 | } 55 | }; 56 | $.fx.step[ "backgroundPosition" + l ] = function( fx ) { 57 | $.cssHooks[ "backgroundPosition" + l ].set( fx.elem, fx.now + fx.unit ); 58 | }; 59 | }); 60 | } 61 | })(jQuery); 62 | 63 | /*! 64 | * Scroll-based parallax plugin for jQuery 65 | * Copyright (c) 2011 Dave Cranwell (http://davecranwell.com) 66 | * Licensed under the MIT License. 67 | * 2011-05-18 68 | * version 1.0 69 | */ 70 | (function($){ 71 | $.fn.scrollParallax = function(options) { 72 | var settings = { 73 | 'speed': 0.2, 74 | 'axis': 'x,y', 75 | 'debug': false 76 | } 77 | 78 | function debug(msg){ 79 | if(settings.debug && 'console' in window && 'log' in window.console){ 80 | console.log(msg); 81 | } 82 | } 83 | 84 | return this.each(function() { 85 | //defined accessible $this var in standard way for use within functions 86 | var $this = $(this), 87 | //timestamp,last position for the interval & FPS ~= 30 88 | ts,FPS = 34,lastPos = {x:0,y:0},intervalActive, 89 | //find current position so parallax can be relative to it 90 | currentPosArray=$this.css("backgroundPosition").split(" "), 91 | currentXPos=parseInt(currentPosArray[0].replace(/[^0-9\-]/g, "")), 92 | currentYPos=parseInt(currentPosArray[1].replace(/[^0-9\-]/g, "")); 93 | 94 | //extend options in standard way 95 | if (options) { 96 | $.extend(settings, options); 97 | } 98 | 99 | $this.bind('inview', function (event, visible) { 100 | if (visible == true) { 101 | $this.addClass("inview"); 102 | debug("in view"); 103 | }else{ 104 | $this.removeClass("inview"); 105 | debug("out of view"); 106 | } 107 | }); 108 | 109 | function updateElemPos(){ 110 | var newXPos,newYPos, 111 | offset = $this.offset(); 112 | 113 | //calculate new position 114 | newXPos = (settings.axis.match(/x/))? 115 | parseInt((-(offset.left - $(window).scrollLeft()) * settings.speed) + currentXPos) + "px": 116 | currentPosArray[0]; 117 | 118 | newYPos = (settings.axis.match(/y/))? 119 | parseInt((-(offset.top - $(window).scrollTop()) * settings.speed) + currentYPos) + "px": 120 | currentPosArray[1]; 121 | 122 | if(typeof intervalActive == 'undefined'){ 123 | lastPos.x = newXPos; 124 | lastPos.y = newYPos; 125 | } 126 | 127 | intervalActive = true; 128 | 129 | debug("new X position: "+ newXPos); 130 | debug("new Y position: "+ newYPos); 131 | 132 | if((newXPos !== lastPos.x) || (newYPos !== lastPos.y)){ 133 | $this.css({'backgroundPosition': newXPos + " " + newYPos}); 134 | lastPos.x = newXPos; 135 | lastPos.y = newYPos; 136 | }else{ 137 | clearInterval(ts); 138 | intervalActive = false; 139 | $(window).bind('scroll.parallax',onScroll); 140 | } 141 | } 142 | 143 | function onScroll(){ 144 | if($this.hasClass("inview")){ 145 | if(!intervalActive){ 146 | ts = setInterval(updateElemPos,FPS); 147 | $(window).unbind('scroll.parallax'); 148 | } 149 | } 150 | } 151 | 152 | //recalculate position on scroll 153 | $(window).bind('scroll.parallax',onScroll); 154 | }); 155 | }; 156 | 157 | })(jQuery); --------------------------------------------------------------------------------