├── LICENSE ├── README.md ├── demo1 ├── bg@2x.jpg ├── demo-bgpos.css ├── demo-bgpos.html └── demo-bgpos.js ├── demo2 ├── bg@2x.jpg ├── demo-translate.css ├── demo-translate.html └── demo-translate.js └── demo3 ├── asparagus.css ├── asparagus.html ├── asparagus.js └── bg@2x.jpg /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Form5 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Perfecting Parallax Scrolling 2 | 3 | This is part of a talk I gave at a Icelandic javascript user group meetup. 4 | 5 | Slides from the presentation: 6 | http://dev.form5.is/parallax/slides.pdf 7 | 8 | The demo code can be found in this repository and following is an article I wrote on the subject which has links to the demos from the talk. 9 | 10 | *** 11 | 12 | **Parallax scrolling** has become quite popular in contemporary web design. This is understandable as it helps add a sense of depth and fluidity but most solutions are far from being perfect and are far too heavy on the cpu and noticeably choppy while scrolling. 13 | 14 | 15 | ### TL;DR version 16 | 17 | This is the search for better parallax scrolling. The best approach uses translate3d and a single ticking requestAnimationFrame method that will make your parallax scroll much lighter and smoother. 18 | 19 | 20 | ### How do we measure performance? 21 | 22 | To measure the performance of our methods we'll be using the [performance profiling capabilities](https://developers.google.com/chrome-developer-tools/docs/timeline) of the timeline tab in Google Chrome's developer inspector: 23 | 24 | ![Timeline tab](http://dev.form5.is/parallax/images/timeline.png) 25 | 26 | Doing framerate optimizations is pretty much a limbo dance competition, touch the bars at your own risk! The green bars signal that rendering is being done by the CPU. Bars rising above 60fps are a clear indication of choppiness and those that touch 30fps or an even lower number are arrows aimed directly at a baby seal's heart. You don't want that on you conscience, do you? 27 | 28 | 29 | ### The demonstration 30 | 31 | Following are three examples of different parallax techniques, the first two being common solutions and then we present the third method — Asparagus. 32 | 33 | The (perhaps much too familiar) hero image is a very common design pattern these days, being a default with popular front-end frameworks like Twitter Bootstrap and Zurb's Foundation. Love it or hate it, it serves as a great example for showing the difference in performance between the most common parallax techniques and Asparagus. 34 | 35 | ![Our demonstration design](http://dev.form5.is/parallax/images/design.png) 36 | 37 | 38 | ### Technique 1: The Background Position Method 39 | 40 | The first method is the background-position method where the background image placed on the `#hero` element. This is probably the most straightforward way of implementing parallax scrolling and it has been [demonstrated](http://coding.smashingmagazine.com/2011/07/12/behind-the-scenes-of-nike-better-world/) in [various tutorials](http://net.tutsplus.com/tutorials/html-css-techniques/simple-parallax-scrolling-technique/) around the web. 41 | 42 | **The Markup** 43 | ```html 44 |
45 |
46 |

background-position

47 |

This parallax method updates background-position and is the slowest of all. Rendering takes place on the CPU.

48 |
49 |
50 | ``` 51 | 52 | ```css 53 | #hero { 54 | height: 750px; 55 | background: url('bg.jpg') 50% 0 no-repeat; 56 | background-size: cover; 57 | } 58 | ``` 59 | 60 | This markup is nothing out of the ordinary and the actual parallax functionality takes place in the JavaScript where `updatePosition()` is fired on every scroll event which changes the hero area's `background-position` attribute. This creates the parallax effect while the user is scrolling. 61 | 62 | ```javascript 63 | var updatePosition = function() { 64 | var hero = document.getElementById('hero'); 65 | var scrollPos = window.pageYOffset / 2; 66 | hero.style['background-position'] = '50% ' + scrollPos + 'px'; 67 | }; 68 | 69 | window.addEventListener('scroll', updatePosition, false); 70 | ``` 71 | 72 | #### Results: Very, Very Bad 73 | 74 | [View the demo](http://dev.form5.is/parallax/demo-bgpos.html) 75 | 76 | The use of the background-position method, where rendering is handled by the CPU, results in terrible performance as can be clearly observed in the timeline measure we mentioned above. 77 | 78 | ![background-position performance](http://dev.form5.is/parallax/images/bgpos.png) 79 | 80 | ### Technique 2: The Relative Top Positioning and translateY Methods 81 | 82 | Here we'll actually be showing two different methods (but both share the same markup) where the background is moved to a separate element and the position of the whole element is changed when scrolling (rather than updating the background position). 83 | 84 | 85 | ```html 86 |
87 |
88 | 89 |
90 |

translateY

91 |

This parallax method is probably the most common one. It has the background image on a seperate element and 2d translates that element onscroll. We can do better than this.

92 |
93 |
94 | ``` 95 | 96 | On the CSS side, we're absolute positioning the background element. 97 | 98 | ``` css 99 | #hero { 100 | position: relative; 101 | height: 750px; 102 | overflow: hidden; 103 | } 104 | 105 | #hero-bg { 106 | position: absolute; 107 | width: 100%; 108 | height: 750px; 109 | top: 0; 110 | bottom: 0; 111 | background: url('bg.jpg') 50% 0 no-repeat; 112 | background-size: cover; 113 | } 114 | ``` 115 | 116 | In the JavaScript we have a function that updates our translate settings on every scroll event. 117 | 118 | On one hand, we can move the new background element with [relative positioning using the `top` attribute](http://www.webdesignerdepot.com/2013/07/how-to-create-a-simple-parallax-effect/). 119 | 120 | On the other hand, we can make use of the `translateY` attribute. The latter delivers [better performance](http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/) as `translateY` takes rendering to the GPU level. Both methods can be observed below but we'll be using the latter for this demonstration. 121 | 122 | ```javascript 123 | updatePosition = function() { 124 | var heroBg = document.getElementById('hero-bg'); 125 | var newPos = window.pageYOffset / 2; 126 | 127 | translateY(heroBg, newPos); 128 | // We could use relative top positioning here instead 129 | // but that will always be slower 130 | // heroBg.style.top = newPos + 'px'; 131 | }; 132 | 133 | function translateY(elm, value) { 134 | var translate = 'translateY(' + value + 'px)'; 135 | elm.style['-webkit-transform'] = translate; 136 | elm.style['-moz-transform'] = translate; 137 | elm.style['-ms-transform'] = translate; 138 | elm.style['-o-transform'] = translate; 139 | elm.style.transform = translate; 140 | } 141 | 142 | window.addEventListener('scroll', updatePosition, false); 143 | ``` 144 | 145 | #### Results: It's Alright - But We Can Do Better 146 | 147 | [View the demo](http://dev.form5.is/parallax/demo-translate.html) 148 | 149 | ![translateY performance](http://dev.form5.is/parallax/images/translate.png) 150 | 151 | The `translateY` performance for this technique is much better than the one we saw for technique 1 (`background-position`) but we're still seeing spikes of slow rendering. We need to take this to the next level. 152 | 153 | ### Technique 3: Asparagus 154 | 155 | We could settle for the other techniques but Asparagus is where we [Bump the Lamp](http://www.helloerik.com/bump-the-lamp-the-reason-for-caring)". 156 | 157 | 'But why?' you may ask, feeling that the other techniques are good enough. We've discussed the individual performance issues above but lets focus on the two general problems. First, as the performance profiling indicated (the green bars, remember), the GPU isn't being utilized nearly as much as it could with the most common methods. Secondly, calculations are being done at a **much higher** rate than is actually needed, causing constant reflow and repaint in the browser. 158 | 159 | This is where requestAnimationFrame and translate3d come to the rescue. 160 | 161 | To limit the rate at which calculation is being done we'll be using the awesome requestAnimationFrame (rAF) API. Without going into too much detail, rAF collects your constant rendering updates into a single reflow and repaint cycle, and this ensures that your animation calculation is being done in a balanced 'sweetspot' of constant calculation and smooth rendering. To learn more about rAF I recommend reading [this article](http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/) by Paul Irish and [that article](http://www.html5rocks.com/en/tutorials/speed/animations/) by Paul Lewis. 162 | 163 | The markup is the same as we used above in technique 2 but we'll be using `translate3d(x,y,z)` instead of `translateY(y)` for the actual translation of the background element. This will do wonders for our rendering even though we're only going to be using the y paramter of `translate3d` with 0px given for the x and z axis. 164 | 165 | So lets take a look at what's happening under the hood. 166 | 167 | We start off by attaching a simple function to the window's scroll event: 168 | ``` javascript 169 | var lastScrollY = 0, 170 | ticking = false, 171 | bgElm = document.getElementById('hero-bg'), 172 | speedDivider = 2; 173 | 174 | // Update scroll value and request tick 175 | var doScroll = function() { 176 | lastScrollY = window.pageYOffset; 177 | requestTick(); 178 | }; 179 | 180 | window.addEventListener('scroll', doScroll, false); 181 | ``` 182 | 183 | As you can see, the `lastScrollY` variable is being updated for each scroll event and `requestTick()` is being called. This will pass our `updatePosition` function to the the rAF API. What it also does is ensure that the background position isn't being updated multiple times concurrently: 184 | 185 | ```javascript 186 | var requestTick = function() { 187 | if (!ticking) { 188 | window.requestAnimationFrame(updatePosition); 189 | ticking = true; 190 | } 191 | }; 192 | ``` 193 | 194 | `translate3d` is used in the function rather than `translateY` which allow the true power of the GPU to be unleashed. 195 | 196 | ```javascript 197 | var updatePosition = function() { 198 | var translateValue = lastScrollY / speedDivider; 199 | 200 | // We don't want parallax to happen if scrollpos is below 0 201 | if (translateValue < 0) 202 | translateValue = 0; 203 | 204 | translateY3d(bgElm, translateValue); 205 | 206 | // Stop ticking 207 | ticking = false; 208 | }; 209 | 210 | // Translates an element on the Y axis using translate3d 211 | // to ensure that the rendering is done by the GPU 212 | var translateY3d = function(elm, value) { 213 | var translate = 'translate3d(0px,' + value + 'px, 0px)'; 214 | elm.style['-webkit-transform'] = translate; 215 | elm.style['-moz-transform'] = translate; 216 | elm.style['-ms-transform'] = translate; 217 | elm.style['-o-transform'] = translate; 218 | elm.style.transform = translate; 219 | }; 220 | ``` 221 | 222 | #### The Results: We Have a Winner! 223 | 224 | The performance optimization can be seen very clearly by [looking at the demo](http://dev.form5.is/parallax/asparagus.html) but we'll also need objective measures to see whether `requestAnimationFrame` combined with `translate3d` is the silver bullet for doing parallax animation as we hope. 225 | 226 | The timeline now shows a different picture. The green bars have almost vanished and are now being replaced with unfilled bars. This means that rendering is no longer being done by the CPU and has moved to the much faster GPU. 227 | 228 | ![Asparagus performance](http://dev.form5.is/parallax/images/asparagus.png) 229 | 230 | 231 | #### About The Author 232 | 233 | Olafur Nielsen is a web developer with a huge passion for good user experience. He is a Co-Founder of [Form5](http://form5.is), an interactive studio based in Reykjavík, Iceland. Check us out at [twitter](http://twitter.com/Form5) or even [GitHub](https://github.com/Form5). 234 | -------------------------------------------------------------------------------- /demo1/bg@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KolibriDev/Form5-parallax/c1dadbd3aedda2ed12b568c211df982b02f97c0d/demo1/bg@2x.jpg -------------------------------------------------------------------------------- /demo1/demo-bgpos.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: Helvetica, Arial, sans-serif; 5 | } 6 | 7 | #hero { 8 | position: relative; 9 | height: 750px; 10 | overflow: hidden; 11 | 12 | background-image: url('bg@2x.jpg'); 13 | background-position: 50% 0; 14 | background-repeat: no-repeat; 15 | background-size: cover; 16 | } 17 | 18 | .hero-content { 19 | position: absolute; 20 | right: 0; 21 | left: 0; 22 | top: 15em; 23 | padding: 1em; 24 | margin: auto; 25 | width: 300px; 26 | text-align: center; 27 | background: rgba(0,0,0,0.25); 28 | color: white; 29 | } -------------------------------------------------------------------------------- /demo1/demo-bgpos.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Demo #1 6 | 7 | 8 | 9 |
10 |
11 |

Method #1

12 |

This parallax method updates background-position and is the slowest of all. Rendering takes place on the CPU.

13 |
14 |
15 | 16 |

Demo lorem

17 | 18 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sagittis accumsan nunc, non interdum est pellentesque ut. Duis semper arcu vel eros congue lacinia non vitae sapien. Morbi porttitor est et est facilisis hendrerit. Phasellus accumsan nibh sit amet aliquam tincidunt. Vivamus dapibus neque eget orci sagittis fringilla. Phasellus dignissim elementum urna id porttitor. Nullam ultricies euismod turpis eget semper. Curabitur tincidunt porta urna a ultrices. Donec eu bibendum nisl. Vivamus sapien tellus, accumsan vitae enim eget, condimentum commodo nisl. Curabitur feugiat tristique lectus, sed sagittis enim scelerisque sit amet. Quisque luctus tellus arcu, eget venenatis mauris fermentum non. Duis eget magna at dolor laoreet vehicula nec a erat. Nullam pellentesque viverra elementum. Cras ac dictum arcu. Fusce ac aliquet tortor.

19 | 20 |

Integer vehicula quam non egestas pulvinar. Curabitur euismod est vitae tincidunt adipiscing. Curabitur molestie tincidunt mauris, et bibendum urna ultricies non. Aliquam ultrices, purus vitae pellentesque tincidunt, nisi orci dapibus dolor, vitae laoreet massa lectus bibendum nibh. Sed placerat ac nisl sed viverra. Etiam congue purus in aliquet varius. In hac habitasse platea dictumst. Donec eget enim mollis, porttitor nisi suscipit, condimentum nisi. Pellentesque eget tellus ut felis convallis fermentum. Donec et leo sed quam dignissim semper. Phasellus et tellus et massa mattis tempus et vitae est. Nulla quis sollicitudin orci, ac vestibulum lectus. Aliquam dignissim eu ipsum nec fringilla. Cras eget sapien nec nisi sollicitudin aliquam.

21 | 22 |

Ipsum awesome

23 | 24 |

Maecenas auctor urna ut ante pulvinar lacinia ac sed leo. Aenean vehicula quis odio sit amet hendrerit. Curabitur fringilla augue eu tincidunt pellentesque. Integer eget nibh sit amet metus ullamcorper consequat. Quisque in pretium elit, vel ornare urna. Cras eu velit tortor. Suspendisse ut sollicitudin lectus. Morbi laoreet metus ut mauris placerat laoreet. Morbi nec eleifend dui.

25 | 26 |

Aenean nec eros velit. Praesent hendrerit ligula eu purus rhoncus, vitae molestie elit porta. Aliquam nibh turpis, faucibus vitae mollis sit amet, auctor ut augue. Sed eu ultrices velit, a convallis dui. Ut fringilla nibh tortor. Aliquam erat volutpat. Etiam dignissim ullamcorper mollis. Etiam ultrices nunc eget risus tempus elementum. Praesent quis enim vestibulum, fringilla arcu eu, ornare massa. In luctus, dui non interdum semper, eros est hendrerit diam, sed fringilla massa arcu eget quam. Nunc pretium eros in malesuada pretium. Duis id interdum mi. Cras imperdiet, lectus ut ultrices imperdiet, nisl tellus lacinia sapien, ac hendrerit erat lorem a nisl. Donec faucibus orci a neque suscipit fermentum.

27 | 28 |

Nunc ornare feugiat nisl, eu lacinia nulla malesuada et. Maecenas porta orci nec ipsum faucibus aliquam. Suspendisse potenti. In iaculis eu magna a commodo. Curabitur leo nisl, viverra a justo sed, tincidunt facilisis mi. Aenean neque mi, condimentum vel nisl eu, faucibus dapibus dui. Nulla quis dictum metus, quis ultricies neque. Suspendisse egestas tristique libero, at dapibus ante. Sed eu justo a felis rutrum sollicitudin. Maecenas non quam eget odio iaculis sodales rutrum ut justo. Nulla mi dui, lacinia nec felis nec, convallis gravida erat. Etiam hendrerit viverra quam eget feugiat. In a iaculis lacus. Pellentesque gravida lorem eu congue porttitor. Donec ornare fermentum pulvinar.

29 | 30 |

Dolor cool

31 | 32 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sagittis accumsan nunc, non interdum est pellentesque ut. Duis semper arcu vel eros congue lacinia non vitae sapien. Morbi porttitor est et est facilisis hendrerit. Phasellus accumsan nibh sit amet aliquam tincidunt. Vivamus dapibus neque eget orci sagittis fringilla. Phasellus dignissim elementum urna id porttitor. Nullam ultricies euismod turpis eget semper. Curabitur tincidunt porta urna a ultrices. Donec eu bibendum nisl. Vivamus sapien tellus, accumsan vitae enim eget, condimentum commodo nisl. Curabitur feugiat tristique lectus, sed sagittis enim scelerisque sit amet. Quisque luctus tellus arcu, eget venenatis mauris fermentum non. Duis eget magna at dolor laoreet vehicula nec a erat. Nullam pellentesque viverra elementum. Cras ac dictum arcu. Fusce ac aliquet tortor.

33 | 34 |

Aenean nec eros velit. Praesent hendrerit ligula eu purus rhoncus, vitae molestie elit porta. Aliquam nibh turpis, faucibus vitae mollis sit amet, auctor ut augue. Sed eu ultrices velit, a convallis dui. Ut fringilla nibh tortor. Aliquam erat volutpat. Etiam dignissim ullamcorper mollis. Etiam ultrices nunc eget risus tempus elementum. Praesent quis enim vestibulum, fringilla arcu eu, ornare massa. In luctus, dui non interdum semper, eros est hendrerit diam, sed fringilla massa arcu eget quam. Nunc pretium eros in malesuada pretium. Duis id interdum mi. Cras imperdiet, lectus ut ultrices imperdiet, nisl tellus lacinia sapien, ac hendrerit erat lorem a nisl. Donec faucibus orci a neque suscipit fermentum.

35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /demo1/demo-bgpos.js: -------------------------------------------------------------------------------- 1 | updatePosition = function() { 2 | var hero = document.getElementById('hero'); 3 | var scrollPos = window.pageYOffset / 2; 4 | hero.style['background-position'] = '50% ' + scrollPos + 'px'; 5 | }; 6 | 7 | $(document).ready(function() { 8 | $(window).on('scroll', updatePosition); 9 | }); -------------------------------------------------------------------------------- /demo2/bg@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KolibriDev/Form5-parallax/c1dadbd3aedda2ed12b568c211df982b02f97c0d/demo2/bg@2x.jpg -------------------------------------------------------------------------------- /demo2/demo-translate.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: Helvetica, Arial, sans-serif; 5 | } 6 | 7 | #hero { 8 | position: relative; 9 | height: 750px; 10 | overflow: hidden; 11 | } 12 | 13 | #hero-bg { 14 | position: absolute; 15 | width: 100%; 16 | height: 750px; 17 | top: 0; 18 | bottom: 0; 19 | 20 | background-image: url('bg@2x.jpg'); 21 | background-position: 50% 0; 22 | background-repeat: no-repeat; 23 | background-size: cover; 24 | } 25 | 26 | .hero-content { 27 | position: absolute; 28 | right: 0; 29 | left: 0; 30 | top: 15em; 31 | padding: 1em; 32 | margin: auto; 33 | width: 300px; 34 | text-align: center; 35 | background: rgba(0,0,0,0.25); 36 | color: white; 37 | } -------------------------------------------------------------------------------- /demo2/demo-translate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Parallax using translateY 6 | 7 | 8 | 9 |
10 |
11 | 12 |
13 |

Method #2

14 |

This parallax method is probably the most common one. It has the background image on a seperate element and 2d translates that element onscroll. We can do better than this.

15 |
16 |
17 | 18 |

Demo lorem

19 | 20 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sagittis accumsan nunc, non interdum est pellentesque ut. Duis semper arcu vel eros congue lacinia non vitae sapien. Morbi porttitor est et est facilisis hendrerit. Phasellus accumsan nibh sit amet aliquam tincidunt. Vivamus dapibus neque eget orci sagittis fringilla. Phasellus dignissim elementum urna id porttitor. Nullam ultricies euismod turpis eget semper. Curabitur tincidunt porta urna a ultrices. Donec eu bibendum nisl. Vivamus sapien tellus, accumsan vitae enim eget, condimentum commodo nisl. Curabitur feugiat tristique lectus, sed sagittis enim scelerisque sit amet. Quisque luctus tellus arcu, eget venenatis mauris fermentum non. Duis eget magna at dolor laoreet vehicula nec a erat. Nullam pellentesque viverra elementum. Cras ac dictum arcu. Fusce ac aliquet tortor.

21 | 22 |

Integer vehicula quam non egestas pulvinar. Curabitur euismod est vitae tincidunt adipiscing. Curabitur molestie tincidunt mauris, et bibendum urna ultricies non. Aliquam ultrices, purus vitae pellentesque tincidunt, nisi orci dapibus dolor, vitae laoreet massa lectus bibendum nibh. Sed placerat ac nisl sed viverra. Etiam congue purus in aliquet varius. In hac habitasse platea dictumst. Donec eget enim mollis, porttitor nisi suscipit, condimentum nisi. Pellentesque eget tellus ut felis convallis fermentum. Donec et leo sed quam dignissim semper. Phasellus et tellus et massa mattis tempus et vitae est. Nulla quis sollicitudin orci, ac vestibulum lectus. Aliquam dignissim eu ipsum nec fringilla. Cras eget sapien nec nisi sollicitudin aliquam.

23 | 24 |

Ipsum awesome

25 | 26 |

Maecenas auctor urna ut ante pulvinar lacinia ac sed leo. Aenean vehicula quis odio sit amet hendrerit. Curabitur fringilla augue eu tincidunt pellentesque. Integer eget nibh sit amet metus ullamcorper consequat. Quisque in pretium elit, vel ornare urna. Cras eu velit tortor. Suspendisse ut sollicitudin lectus. Morbi laoreet metus ut mauris placerat laoreet. Morbi nec eleifend dui.

27 | 28 |

Aenean nec eros velit. Praesent hendrerit ligula eu purus rhoncus, vitae molestie elit porta. Aliquam nibh turpis, faucibus vitae mollis sit amet, auctor ut augue. Sed eu ultrices velit, a convallis dui. Ut fringilla nibh tortor. Aliquam erat volutpat. Etiam dignissim ullamcorper mollis. Etiam ultrices nunc eget risus tempus elementum. Praesent quis enim vestibulum, fringilla arcu eu, ornare massa. In luctus, dui non interdum semper, eros est hendrerit diam, sed fringilla massa arcu eget quam. Nunc pretium eros in malesuada pretium. Duis id interdum mi. Cras imperdiet, lectus ut ultrices imperdiet, nisl tellus lacinia sapien, ac hendrerit erat lorem a nisl. Donec faucibus orci a neque suscipit fermentum.

29 | 30 |

Nunc ornare feugiat nisl, eu lacinia nulla malesuada et. Maecenas porta orci nec ipsum faucibus aliquam. Suspendisse potenti. In iaculis eu magna a commodo. Curabitur leo nisl, viverra a justo sed, tincidunt facilisis mi. Aenean neque mi, condimentum vel nisl eu, faucibus dapibus dui. Nulla quis dictum metus, quis ultricies neque. Suspendisse egestas tristique libero, at dapibus ante. Sed eu justo a felis rutrum sollicitudin. Maecenas non quam eget odio iaculis sodales rutrum ut justo. Nulla mi dui, lacinia nec felis nec, convallis gravida erat. Etiam hendrerit viverra quam eget feugiat. In a iaculis lacus. Pellentesque gravida lorem eu congue porttitor. Donec ornare fermentum pulvinar.

31 | 32 |

Dolor cool

33 | 34 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sagittis accumsan nunc, non interdum est pellentesque ut. Duis semper arcu vel eros congue lacinia non vitae sapien. Morbi porttitor est et est facilisis hendrerit. Phasellus accumsan nibh sit amet aliquam tincidunt. Vivamus dapibus neque eget orci sagittis fringilla. Phasellus dignissim elementum urna id porttitor. Nullam ultricies euismod turpis eget semper. Curabitur tincidunt porta urna a ultrices. Donec eu bibendum nisl. Vivamus sapien tellus, accumsan vitae enim eget, condimentum commodo nisl. Curabitur feugiat tristique lectus, sed sagittis enim scelerisque sit amet. Quisque luctus tellus arcu, eget venenatis mauris fermentum non. Duis eget magna at dolor laoreet vehicula nec a erat. Nullam pellentesque viverra elementum. Cras ac dictum arcu. Fusce ac aliquet tortor.

35 | 36 |

Aenean nec eros velit. Praesent hendrerit ligula eu purus rhoncus, vitae molestie elit porta. Aliquam nibh turpis, faucibus vitae mollis sit amet, auctor ut augue. Sed eu ultrices velit, a convallis dui. Ut fringilla nibh tortor. Aliquam erat volutpat. Etiam dignissim ullamcorper mollis. Etiam ultrices nunc eget risus tempus elementum. Praesent quis enim vestibulum, fringilla arcu eu, ornare massa. In luctus, dui non interdum semper, eros est hendrerit diam, sed fringilla massa arcu eget quam. Nunc pretium eros in malesuada pretium. Duis id interdum mi. Cras imperdiet, lectus ut ultrices imperdiet, nisl tellus lacinia sapien, ac hendrerit erat lorem a nisl. Donec faucibus orci a neque suscipit fermentum.

37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /demo2/demo-translate.js: -------------------------------------------------------------------------------- 1 | updatePosition = function() { 2 | var heroBg = document.getElementById('hero-bg'); 3 | var newPos = window.pageYOffset / 2; 4 | translateY(heroBg, newPos); 5 | }; 6 | 7 | function translateY(elm, value) { 8 | var translate = 'translateY(' + value + 'px'; 9 | elm.style['-webkit-transform'] = translate; 10 | elm.style['-moz-transform'] = translate; 11 | elm.style['-ms-transform'] = translate; 12 | elm.style['-o-transform'] = translate; 13 | elm.style.transform = translate; 14 | } 15 | 16 | $(document).ready(function() { 17 | $(window).on('scroll', updatePosition); 18 | }); -------------------------------------------------------------------------------- /demo3/asparagus.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: Helvetica, Arial, sans-serif; 5 | } 6 | 7 | #hero { 8 | position: relative; 9 | height: 750px; 10 | overflow: hidden; 11 | } 12 | 13 | #hero-bg { 14 | position: absolute; 15 | width: 100%; 16 | height: 750px; 17 | top: 0; 18 | bottom: 0; 19 | 20 | background-image: url('bg@2x.jpg'); 21 | background-position: 50% 0; 22 | background-repeat: no-repeat; 23 | background-size: cover; 24 | } 25 | 26 | .hero-content { 27 | position: absolute; 28 | right: 0; 29 | left: 0; 30 | top: 15em; 31 | padding: 1em; 32 | margin: auto; 33 | width: 300px; 34 | text-align: center; 35 | background: rgba(0,0,0,0.25); 36 | color: white; 37 | } -------------------------------------------------------------------------------- /demo3/asparagus.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Asparagus demo 6 | 7 | 8 | 9 |
10 |
11 | 12 |
13 |

rAF + translate3d

14 |

Written in native Javascript using a single ticking requestAnimationFrame() method and translate3d to ensure GPU acceleration.

15 |
16 | 17 |
18 | 19 |

Demo lorem

20 | 21 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sagittis accumsan nunc, non interdum est pellentesque ut. Duis semper arcu vel eros congue lacinia non vitae sapien. Morbi porttitor est et est facilisis hendrerit. Phasellus accumsan nibh sit amet aliquam tincidunt. Vivamus dapibus neque eget orci sagittis fringilla. Phasellus dignissim elementum urna id porttitor. Nullam ultricies euismod turpis eget semper. Curabitur tincidunt porta urna a ultrices. Donec eu bibendum nisl. Vivamus sapien tellus, accumsan vitae enim eget, condimentum commodo nisl. Curabitur feugiat tristique lectus, sed sagittis enim scelerisque sit amet. Quisque luctus tellus arcu, eget venenatis mauris fermentum non. Duis eget magna at dolor laoreet vehicula nec a erat. Nullam pellentesque viverra elementum. Cras ac dictum arcu. Fusce ac aliquet tortor.

22 | 23 |

Integer vehicula quam non egestas pulvinar. Curabitur euismod est vitae tincidunt adipiscing. Curabitur molestie tincidunt mauris, et bibendum urna ultricies non. Aliquam ultrices, purus vitae pellentesque tincidunt, nisi orci dapibus dolor, vitae laoreet massa lectus bibendum nibh. Sed placerat ac nisl sed viverra. Etiam congue purus in aliquet varius. In hac habitasse platea dictumst. Donec eget enim mollis, porttitor nisi suscipit, condimentum nisi. Pellentesque eget tellus ut felis convallis fermentum. Donec et leo sed quam dignissim semper. Phasellus et tellus et massa mattis tempus et vitae est. Nulla quis sollicitudin orci, ac vestibulum lectus. Aliquam dignissim eu ipsum nec fringilla. Cras eget sapien nec nisi sollicitudin aliquam.

24 | 25 |

Ipsum awesome

26 | 27 |

Maecenas auctor urna ut ante pulvinar lacinia ac sed leo. Aenean vehicula quis odio sit amet hendrerit. Curabitur fringilla augue eu tincidunt pellentesque. Integer eget nibh sit amet metus ullamcorper consequat. Quisque in pretium elit, vel ornare urna. Cras eu velit tortor. Suspendisse ut sollicitudin lectus. Morbi laoreet metus ut mauris placerat laoreet. Morbi nec eleifend dui.

28 | 29 |

Aenean nec eros velit. Praesent hendrerit ligula eu purus rhoncus, vitae molestie elit porta. Aliquam nibh turpis, faucibus vitae mollis sit amet, auctor ut augue. Sed eu ultrices velit, a convallis dui. Ut fringilla nibh tortor. Aliquam erat volutpat. Etiam dignissim ullamcorper mollis. Etiam ultrices nunc eget risus tempus elementum. Praesent quis enim vestibulum, fringilla arcu eu, ornare massa. In luctus, dui non interdum semper, eros est hendrerit diam, sed fringilla massa arcu eget quam. Nunc pretium eros in malesuada pretium. Duis id interdum mi. Cras imperdiet, lectus ut ultrices imperdiet, nisl tellus lacinia sapien, ac hendrerit erat lorem a nisl. Donec faucibus orci a neque suscipit fermentum.

30 | 31 |

Nunc ornare feugiat nisl, eu lacinia nulla malesuada et. Maecenas porta orci nec ipsum faucibus aliquam. Suspendisse potenti. In iaculis eu magna a commodo. Curabitur leo nisl, viverra a justo sed, tincidunt facilisis mi. Aenean neque mi, condimentum vel nisl eu, faucibus dapibus dui. Nulla quis dictum metus, quis ultricies neque. Suspendisse egestas tristique libero, at dapibus ante. Sed eu justo a felis rutrum sollicitudin. Maecenas non quam eget odio iaculis sodales rutrum ut justo. Nulla mi dui, lacinia nec felis nec, convallis gravida erat. Etiam hendrerit viverra quam eget feugiat. In a iaculis lacus. Pellentesque gravida lorem eu congue porttitor. Donec ornare fermentum pulvinar.

32 | 33 |

Dolor cool

34 | 35 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sagittis accumsan nunc, non interdum est pellentesque ut. Duis semper arcu vel eros congue lacinia non vitae sapien. Morbi porttitor est et est facilisis hendrerit. Phasellus accumsan nibh sit amet aliquam tincidunt. Vivamus dapibus neque eget orci sagittis fringilla. Phasellus dignissim elementum urna id porttitor. Nullam ultricies euismod turpis eget semper. Curabitur tincidunt porta urna a ultrices. Donec eu bibendum nisl. Vivamus sapien tellus, accumsan vitae enim eget, condimentum commodo nisl. Curabitur feugiat tristique lectus, sed sagittis enim scelerisque sit amet. Quisque luctus tellus arcu, eget venenatis mauris fermentum non. Duis eget magna at dolor laoreet vehicula nec a erat. Nullam pellentesque viverra elementum. Cras ac dictum arcu. Fusce ac aliquet tortor.

36 | 37 |

Aenean nec eros velit. Praesent hendrerit ligula eu purus rhoncus, vitae molestie elit porta. Aliquam nibh turpis, faucibus vitae mollis sit amet, auctor ut augue. Sed eu ultrices velit, a convallis dui. Ut fringilla nibh tortor. Aliquam erat volutpat. Etiam dignissim ullamcorper mollis. Etiam ultrices nunc eget risus tempus elementum. Praesent quis enim vestibulum, fringilla arcu eu, ornare massa. In luctus, dui non interdum semper, eros est hendrerit diam, sed fringilla massa arcu eget quam. Nunc pretium eros in malesuada pretium. Duis id interdum mi. Cras imperdiet, lectus ut ultrices imperdiet, nisl tellus lacinia sapien, ac hendrerit erat lorem a nisl. Donec faucibus orci a neque suscipit fermentum.

38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /demo3/asparagus.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license Asparagus v1.0 3 | * (c) 2013 Form5 http://form5.is 4 | * License: MIT 5 | */ 6 | (function() { 7 | var lastScrollY = 0, 8 | ticking = false, 9 | bgElm = document.getElementById('hero-bg'), 10 | speedDivider = 2; 11 | 12 | // Update background position 13 | var updatePosition = function() { 14 | var translateValue = lastScrollY / speedDivider; 15 | 16 | // We don't want parallax to happen if scrollpos is below 0 17 | if (translateValue < 0) 18 | translateValue = 0; 19 | 20 | translateY(bgElm, translateValue); 21 | 22 | // Stop ticking 23 | ticking = false; 24 | }; 25 | 26 | // Translates an element on the Y axis using translate3d to ensure 27 | // that the rendering is done by the GPU 28 | var translateY = function(elm, value) { 29 | var translate = 'translate3d(0px,' + value + 'px, 0px)'; 30 | elm.style['-webkit-transform'] = translate; 31 | elm.style['-moz-transform'] = translate; 32 | elm.style['-ms-transform'] = translate; 33 | elm.style['-o-transform'] = translate; 34 | elm.style.transform = translate; 35 | }; 36 | 37 | // This will limit the calculation of the background position to 38 | // 60fps as well as blocking it from running multiple times at once 39 | var requestTick = function() { 40 | if (!ticking) { 41 | window.requestAnimationFrame(updatePosition); 42 | ticking = true; 43 | } 44 | }; 45 | 46 | // Update scroll value and request tick 47 | var doScroll = function() { 48 | lastScrollY = window.pageYOffset; 49 | requestTick(); 50 | }; 51 | 52 | // Initialize on domready 53 | (function() { 54 | var loaded = 0; 55 | var bootstrap = function() { 56 | if (loaded) return; 57 | loaded = 1; 58 | 59 | rafPolyfill(); 60 | window.onscroll = doScroll; 61 | }; 62 | 63 | if ( document.readyState === 'complete' ) { 64 | setTimeout( bootstrap ); 65 | } else { 66 | document.addEventListener( 'DOMContentLoaded', bootstrap, false ); 67 | window.addEventListener( 'load', bootstrap, false ); 68 | } 69 | })(); 70 | 71 | // RequestAnimationFrame polyfill for older browsers 72 | var rafPolyfill = function() { 73 | var lastTime, vendors, x; 74 | lastTime = 0; 75 | vendors = ["webkit", "moz"]; 76 | x = 0; 77 | while (x < vendors.length && !window.requestAnimationFrame) { 78 | window.requestAnimationFrame = window[vendors[x] + "RequestAnimationFrame"]; 79 | window.cancelAnimationFrame = window[vendors[x] + "CancelAnimationFrame"] || window[vendors[x] + "CancelRequestAnimationFrame"]; 80 | ++x; 81 | } 82 | if (!window.requestAnimationFrame) { 83 | window.requestAnimationFrame = function(callback, element) { 84 | var currTime, id, timeToCall; 85 | currTime = new Date().getTime(); 86 | timeToCall = Math.max(0, 16 - (currTime - lastTime)); 87 | id = window.setTimeout(function() { 88 | callback(currTime + timeToCall); 89 | }, timeToCall); 90 | lastTime = currTime + timeToCall; 91 | return id; 92 | }; 93 | } 94 | if (!window.cancelAnimationFrame) { 95 | window.cancelAnimationFrame = function(id) { 96 | clearTimeout(id); 97 | }; 98 | } 99 | }; 100 | 101 | }).call(this); -------------------------------------------------------------------------------- /demo3/bg@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KolibriDev/Form5-parallax/c1dadbd3aedda2ed12b568c211df982b02f97c0d/demo3/bg@2x.jpg --------------------------------------------------------------------------------