Skip to content

Instantly share code, notes, and snippets.

@Warry
Created December 11, 2012 00:11
Show Gist options
  • Select an option

  • Save Warry/4254579 to your computer and use it in GitHub Desktop.

Select an option

Save Warry/4254579 to your computer and use it in GitHub Desktop.

Revisions

  1. Warry revised this gist Dec 11, 2012. 1 changed file with 9 additions and 0 deletions.
    9 changes: 9 additions & 0 deletions zzzbad.html
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,12 @@
    <!--
    BAD EXEMPLE WITH window.onscroll
    BAD EXEMPLE WITH window.onscroll
    BAD EXEMPLE WITH window.onscroll
    -->
    <!doctype html>
    <html>
    <head>
  2. Warry revised this gist Dec 11, 2012. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions Article.md
    Original file line number Diff line number Diff line change
    @@ -83,3 +83,6 @@ I suggest you to have a look at the whole attached piece of code, that is struct
    * Try to skip calculations
    * Find elements that will change
    * Modify the DOM


    The last HTML file is a bad exemple, showing the difference with `window.onscroll` and without CSS 3D.
  3. Warry renamed this gist Dec 11, 2012. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  4. Warry revised this gist Dec 11, 2012. 1 changed file with 181 additions and 0 deletions.
    181 changes: 181 additions & 0 deletions bad.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,181 @@
    <!doctype html>
    <html>
    <head>
    <meta charset='utf-8'>
    <title>Slow scroll effect</title>
    <link rel="stylesheet" href="fse.css">
    </head>
    <body>
    <div id="wrapper">
    <section>
    <article>
    <h1>SCROLL DOWN</h1>
    </article>
    </section>
    <section class="stick">
    <article>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

    </article>
    </section>
    <section class="stick">
    <article>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </article>
    </section>
    <section>
    <article>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </article>
    </section>
    </div>
    <script>



    // BAD CODE !
    // This is the counter example





    var lastPosition = -1
    , wHeight = window.innerHeight
    , wrapper = document.getElementById("wrapper")
    , elements = document.getElementsByTagName("section")
    , size = elements.length
    , matrix = []

    // Pre calculate sizes to get better perfs
    function sizes(){
    wHeight = window.innerHeight
    var i = 0
    for (i =0; i<size; i++){
    matrix[i] = matrix[i] || { el: elements[i] }

    // Reinit
    matrix[i].el.style.display = "block"
    lastPosition = -1

    matrix[i].height = matrix[i].el.offsetHeight
    matrix[i].start = matrix[i-1] ? matrix[i-1].stop : 0
    matrix[i].stop = matrix[i-1] ? matrix[i-1].stop + matrix[i].height : matrix[i].height
    matrix[i].isScroll = matrix[i].el.className.indexOf("stick") < 0

    // If it's sticked but higher than the screen...
    if (matrix[i].height - wHeight > 0) matrix[i].gap = matrix[i].height - wHeight

    // Let's find a index
    matrix[i].el.style.zIndex = !matrix[i].isScroll ? 10 - i : 100 - i
    }
    wrapper.style.height = matrix[i-1].stop + "px"
    }
    window.onresize = sizes

    function setTop(m, t){
    console.log(t)
    m.el.style.top = t + "px"
    }

    function loop(){
    lastPosition = window.pageYOffset
    var i = 0
    for (i =0; i<size; i++){
    // Is it visible right now?
    if (lastPosition >= matrix[i].start - wHeight && lastPosition <= matrix[i].stop){
    matrix[i].el.style.display = "block"
    if (
    // Is it scrolling?
    (matrix[i].isScroll) ||
    // Or is it stick, but higher than window?
    (!matrix[i].isScroll && matrix[i].gap && lastPosition >= matrix[i].start)
    )
    setTop(matrix[i], matrix[i].start - lastPosition)
    } else {
    matrix[i].el.style.display = "none"
    }
    }
    }

    // Let's go
    sizes()
    window.onscroll = loop

    </script>
    <style type="text/css">
    section {
    transform: none;
    -moz-transform: none;
    -webkit-transform: none;
    }
    </style>
    </body>
    </html>
  5. Warry revised this gist Dec 11, 2012. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion fse.js
    Original file line number Diff line number Diff line change
    @@ -22,6 +22,7 @@ var cssTransform = (function(){

    // Detect request animation frame
    var scroll = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame || function(callback){ window.setTimeout(callback, 1000/60) }
    // Vars
    , has3d = document.body.style.transform
    , lastPosition = -1
    , wHeight = window.innerHeight
    @@ -32,14 +33,14 @@ var scroll = window.requestAnimationFrame || window.webkitRequestAnimationFrame

    // Pre calculate sizes to get better perfs
    function sizes(){
    lastPosition = -1 // Force a recalculation
    wHeight = window.innerHeight
    var i = 0
    for (i =0; i<size; i++){
    matrix[i] = matrix[i] || { el: elements[i] }

    // Reinit
    matrix[i].el.style.display = "block"
    lastPosition = -1

    matrix[i].height = matrix[i].el.offsetHeight
    matrix[i].start = matrix[i-1] ? matrix[i-1].stop : 0
  6. Warry revised this gist Dec 11, 2012. 2 changed files with 16 additions and 14 deletions.
    10 changes: 1 addition & 9 deletions exemple.html
    Original file line number Diff line number Diff line change
    @@ -75,15 +75,7 @@ <h1>SCROLL DOWN</h1>
    <article>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    quis nostrud exercitation cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </article>
    </section>
    20 changes: 15 additions & 5 deletions fse.css
    Original file line number Diff line number Diff line change
    @@ -23,33 +23,43 @@ section.stick {
    }

    /* Decoration */
    section:nth-child(1){
    background: url(http://i.images.cdn.fotopedia.com/alibradshaw-bs7HFo22Ff4-hd/New_York_City/New_York_City.jpg);
    /* Ali Bradshaw - http://www.fotopedia.com/wiki/New_York_City#!/items/alibradshaw-bs7HFo22Ff4 */
    background-size: cover;
    }
    section:nth-child(2){
    background: #f5f5f5;
    }
    section:nth-child(4){
    background: #fff;
    }
    section:nth-child(3){
    background: #333;
    background: url(http://i.images.cdn.fotopedia.com/fransimo-onrEHtg2404-hd/New_York_City/Rector_Street.jpg);
    /* Fran Simó - http://www.fotopedia.com/wiki/New_York_City#!/items/fransimo-onrEHtg2404 */
    background-size: cover;
    color: #fff;
    text-shadow: 0 0 3px #000;
    text-align: right;
    }
    article {
    width: 600px;
    margin: 60px auto;
    }
    section:nth-child(3) article {
    float: right;
    margin: 60px;
    }
    h1, h2, h3 {
    font-family: "HelveticaNeue-CondensedBold", "Helvetica Neue", "Helvetica", sans-serif;
    font-weight: bold;
    font-stretch: condensed;
    }

    h1 {
    position: absolute;
    bottom: 50px;
    left 0;
    width: 600px;
    text-align: center;
    font-size: 60px;
    color: #fff;
    }
    h1:before {
    content: "⬇"; /* ↓ ⇓ */
  7. Warry revised this gist Dec 11, 2012. 2 changed files with 36 additions and 6 deletions.
    1 change: 1 addition & 0 deletions exemple.html
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,7 @@
    <!doctype html>
    <html>
    <head>
    <meta charset='utf-8'>
    <title>Faster scroll effect</title>
    <link rel="stylesheet" href="fse.css">
    </head>
    41 changes: 35 additions & 6 deletions fse.css
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,7 @@
    html, body {
    height: 100%;
    font: 19px "Helvetica Neue", "Helvetica", sans-serif;
    color: #333;
    }

    section {
    @@ -16,12 +18,39 @@ section {
    -moz-transform: translate3d(0,0,0);
    -webkit-transform: translate3d(0,0,0);
    }
    section.stick {
    z-index: 10;
    }

    /* FOR DEMO */
    section:nth-child(even){
    background: #eee;
    /* Decoration */
    section:nth-child(2){
    background: #f5f5f5;
    }
    section:nth-child(4){
    background: #fff;
    }
    section:nth-child(3){
    background: #333;
    color: #fff;
    }
    article {
    width: 600px;
    margin: 60px auto;
    }
    h1, h2, h3 {
    font-family: "HelveticaNeue-CondensedBold", "Helvetica Neue", "Helvetica", sans-serif;
    font-weight: bold;
    font-stretch: condensed;
    }

    section.stick {
    z-index: 10;
    }
    h1 {
    position: absolute;
    bottom: 50px;
    left 0;
    width: 600px;
    text-align: center;
    font-size: 60px;
    }
    h1:before {
    content: "⬇"; /* ↓ ⇓ */
    }
  8. Warry revised this gist Dec 11, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Article.md
    Original file line number Diff line number Diff line change
    @@ -11,7 +11,7 @@ The reflow appens as many times as there are frames per seconds. It recalculate
    * use window.pageYOffset to get the scroll position
    * prefer requestAnimationFrame than onScroll event.

    Why is requestAnimationFrame (really) faster than the scroll event? Actually the scroll event popups whenever it wants, even if you haven't finished calculating the previous position, or between two reflows then creating a new one (if you modify DOM on this event)... While the requestAnimationFrame can only popup if the previous frame was calculated. So you save reflows out of your loop function, and you manage to never overlap two calculations.
    Why is requestAnimationFrame (really) faster than the scroll event? Actually the scroll event popups whenever it wants, even if you haven't finished calculating the previous position, or between two reflows... While the requestAnimationFrame can only popup if the previous frame was calculated. So you save reflows out of your loop function, and you manage to never overlap two calculations.

    ```js
    // Detect request animation frame
  9. Warry revised this gist Dec 11, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Article.md
    Original file line number Diff line number Diff line change
    @@ -52,7 +52,7 @@ transform: translate3d(0,0,0);

    Be carefull with `position:fixed` inside a 3D element, they will appear like they were absolute.

    ## Precalculate sizes and positions
    ## Save calculations

    Like I said before, the browser is calculating a lot of things when you modify the DOM. A smooth animation should have between 30 and 60 frames (and reflows) per second. If you ask too much calculation at each frame then your animation will be slower. jQuery doesn't help much for that (big objects, no cache).

  10. Warry revised this gist Dec 11, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Article.md
    Original file line number Diff line number Diff line change
    @@ -42,7 +42,7 @@ This does half of the work.

    ## Graphic rendering

    On modern webkit, if you use 3D css then your elements are both cached as bitmap (one object to render for the element and children). This works for scroll effects, but actually also for every kind of animations and transitions. It works really (really) well on the mobile too.
    On modern webkit, if you use 3D css then your elements are both cached as bitmap (one object to render for the element and children) and rendered by the GPU. This works for scroll effects, but actually also for every kind of animations and transitions. It works really (really) well on the mobile too.

    ```css
    transform: translate3d(0,0,0);
  11. Warry revised this gist Dec 11, 2012. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions Article.md
    Original file line number Diff line number Diff line change
    @@ -80,6 +80,6 @@ I suggest you to have a look at the whole attached piece of code, that is struct
    * Define all variables
    * Precalculation function (called on load and resize)
    * Loop function (called up to 60 times per second)
    * * Try to skip calculations
    * * Find elements that will change
    * * Modify the DOM
    * Try to skip calculations
    * Find elements that will change
    * Modify the DOM
  12. Warry revised this gist Dec 11, 2012. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions Article.md
    Original file line number Diff line number Diff line change
    @@ -80,6 +80,6 @@ I suggest you to have a look at the whole attached piece of code, that is struct
    * Define all variables
    * Precalculation function (called on load and resize)
    * Loop function (called up to 60 times per second)
    ** Try to skip calculations
    ** Find elements that will change
    ** Modify the DOM
    * * Try to skip calculations
    * * Find elements that will change
    * * Modify the DOM
  13. Warry revised this gist Dec 11, 2012. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions Article.md
    Original file line number Diff line number Diff line change
    @@ -54,7 +54,7 @@ Be carefull with `position:fixed` inside a 3D element, they will appear like the

    ## Precalculate sizes and positions

    Like I said before, the browser is calculating a lot of things when you modify the DOM. A smooth animation should have between 30 and 60 franes (and reflows) per second. If you ask too much calculation at each frame then your animation will be slower. jQuery doesn't help much for that (big objects, no cache).
    Like I said before, the browser is calculating a lot of things when you modify the DOM. A smooth animation should have between 30 and 60 frames (and reflows) per second. If you ask too much calculation at each frame then your animation will be slower. jQuery doesn't help much for that (big objects, no cache).

    Since the requestAnimationFrame works all the time and not only when you scroll, you better tells your browser that it has nothing to calculate if you haven't scrolled:

    @@ -80,6 +80,6 @@ I suggest you to have a look at the whole attached piece of code, that is struct
    * Define all variables
    * Precalculation function (called on load and resize)
    * Loop function (called up to 60 times per second)
    * Try to skip calculations
    * Find elements that will change
    * Modify the DOM
    ** Try to skip calculations
    ** Find elements that will change
    ** Modify the DOM
  14. Warry revised this gist Dec 11, 2012. 2 changed files with 7 additions and 4 deletions.
    5 changes: 5 additions & 0 deletions fse.css
    Original file line number Diff line number Diff line change
    @@ -17,6 +17,11 @@ section {
    -webkit-transform: translate3d(0,0,0);
    }

    /* FOR DEMO */
    section:nth-child(even){
    background: #eee;
    }

    section.stick {
    z-index: 10;
    }
    6 changes: 2 additions & 4 deletions fse.js
    Original file line number Diff line number Diff line change
    @@ -90,9 +90,7 @@ function loop(){
    }

    // Let's go
    function init(){
    sizes()
    loop()
    }
    sizes()
    loop()

    })();
  15. Warry revised this gist Dec 11, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion exemple.html
    Original file line number Diff line number Diff line change
    @@ -103,6 +103,6 @@ <h1>SCROLL DOWN</h1>
    </article>
    </section>
    </div>
    <script src="../fse.js"></script>
    <script src="fse.js"></script>
    </body>
    </html>
  16. Warry revised this gist Dec 11, 2012. 1 changed file with 39 additions and 38 deletions.
    77 changes: 39 additions & 38 deletions Article.md
    Original file line number Diff line number Diff line change
    @@ -13,42 +13,42 @@ The reflow appens as many times as there are frames per seconds. It recalculate

    Why is requestAnimationFrame (really) faster than the scroll event? Actually the scroll event popups whenever it wants, even if you haven't finished calculating the previous position, or between two reflows then creating a new one (if you modify DOM on this event)... While the requestAnimationFrame can only popup if the previous frame was calculated. So you save reflows out of your loop function, and you manage to never overlap two calculations.

    ```js
    // Detect request animation frame
    var scroll = window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    // IE Fallback, you can even fallback to onscroll
    function(callback){ window.setTimeout(callback, 1000/60) };
    ```js
    // Detect request animation frame
    var scroll = window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    // IE Fallback, you can even fallback to onscroll
    function(callback){ window.setTimeout(callback, 1000/60) };

    function loop(){
    function loop(){

    var top = window.pageYOffset;
    var top = window.pageYOffset;

    // Where the magic goes
    // ...
    // Where the magic goes
    // ...

    // Recall the loop
    scroll( loop )
    }
    // Recall the loop
    scroll( loop )
    }

    // Call the loop for the first time
    loop();
    ```
    // Call the loop for the first time
    loop();
    ```

    This does half of the work.

    ## Graphic rendering

    On modern webkit, if you use 3D css then your elements are both cached as bitmap (one object to render for the element and children). This works for scroll effects, but actually also for every kind of animations and transitions. It works really (really) well on the mobile too.

    ```css
    transform: translate3d(0,0,0);
    -moz-transform: translate3d(0,0,0);
    -webkit-transform: translate3d(0,0,0);
    ```
    ```css
    transform: translate3d(0,0,0);
    -moz-transform: translate3d(0,0,0);
    -webkit-transform: translate3d(0,0,0);
    ```

    Be carefull with `position:fixed` inside a 3D element, they will appear like they were absolute.

    @@ -58,27 +58,28 @@ Like I said before, the browser is calculating a lot of things when you modify t

    Since the requestAnimationFrame works all the time and not only when you scroll, you better tells your browser that it has nothing to calculate if you haven't scrolled:

    ```js
    var lastPosition = -1;
    ```js
    var lastPosition = -1;

    function loop(){
    // Avoid calculations if not needed
    if (lastPosition == window.pageYOffset) {
    scroll(loop);
    return false;
    } else lastPosition = window.pageYOffset;
    function loop(){
    // Avoid calculations if not needed
    if (lastPosition == window.pageYOffset) {
    scroll(loop);
    return false;
    } else lastPosition = window.pageYOffset;

    //... calculations
    //... calculations

    scroll( loop );
    ```
    scroll( loop );
    }
    ```

    I suggest you to have a look at the whole attached piece of code, that is structured like that:

    * Detect advanced features
    * Define all variables
    * Precalculation function (called on load and resize)
    * Loop function (called up to 60 times per second)
    * Try to skip calculations
    * Find elements that will change
    * Modify the DOM
    * Try to skip calculations
    * Find elements that will change
    * Modify the DOM
  17. Warry revised this gist Dec 11, 2012. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions Article.md
    Original file line number Diff line number Diff line change
    @@ -13,7 +13,7 @@ The reflow appens as many times as there are frames per seconds. It recalculate

    Why is requestAnimationFrame (really) faster than the scroll event? Actually the scroll event popups whenever it wants, even if you haven't finished calculating the previous position, or between two reflows then creating a new one (if you modify DOM on this event)... While the requestAnimationFrame can only popup if the previous frame was calculated. So you save reflows out of your loop function, and you manage to never overlap two calculations.

    '''js
    ```js
    // Detect request animation frame
    var scroll = window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    @@ -36,7 +36,7 @@ Why is requestAnimationFrame (really) faster than the scroll event? Actually the

    // Call the loop for the first time
    loop();
    '''
    ```

    This does half of the work.

  18. Warry revised this gist Dec 11, 2012. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions Article.md
    Original file line number Diff line number Diff line change
    @@ -13,7 +13,7 @@ The reflow appens as many times as there are frames per seconds. It recalculate

    Why is requestAnimationFrame (really) faster than the scroll event? Actually the scroll event popups whenever it wants, even if you haven't finished calculating the previous position, or between two reflows then creating a new one (if you modify DOM on this event)... While the requestAnimationFrame can only popup if the previous frame was calculated. So you save reflows out of your loop function, and you manage to never overlap two calculations.

    ''' js
    '''js
    // Detect request animation frame
    var scroll = window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    @@ -44,7 +44,7 @@ This does half of the work.

    On modern webkit, if you use 3D css then your elements are both cached as bitmap (one object to render for the element and children). This works for scroll effects, but actually also for every kind of animations and transitions. It works really (really) well on the mobile too.

    ``` css
    ```css
    transform: translate3d(0,0,0);
    -moz-transform: translate3d(0,0,0);
    -webkit-transform: translate3d(0,0,0);
    @@ -58,7 +58,7 @@ Like I said before, the browser is calculating a lot of things when you modify t

    Since the requestAnimationFrame works all the time and not only when you scroll, you better tells your browser that it has nothing to calculate if you haven't scrolled:

    ``` js
    ```js
    var lastPosition = -1;

    function loop(){
  19. Warry created this gist Dec 11, 2012.
    84 changes: 84 additions & 0 deletions Article.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,84 @@
    # How to make faster scroll effects?

    * Avoid too many reflows (the browser to recalculate everything)
    * Use advanced CSS3 for graphic card rendering
    * Precalculate sizes and positions

    ## Beware of reflows

    The reflow appens as many times as there are frames per seconds. It recalculate all positions that change in order to diplay them. Basically, when you scroll you execute a function where you move things between two reflows. But there are functions that triggers reflows such as jQuery offset, scroll... So there are two things to take care about when you dynamically change objects in javascript to avoid too many reflows:

    * use window.pageYOffset to get the scroll position
    * prefer requestAnimationFrame than onScroll event.

    Why is requestAnimationFrame (really) faster than the scroll event? Actually the scroll event popups whenever it wants, even if you haven't finished calculating the previous position, or between two reflows then creating a new one (if you modify DOM on this event)... While the requestAnimationFrame can only popup if the previous frame was calculated. So you save reflows out of your loop function, and you manage to never overlap two calculations.

    ''' js
    // Detect request animation frame
    var scroll = window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    // IE Fallback, you can even fallback to onscroll
    function(callback){ window.setTimeout(callback, 1000/60) };

    function loop(){

    var top = window.pageYOffset;

    // Where the magic goes
    // ...

    // Recall the loop
    scroll( loop )
    }

    // Call the loop for the first time
    loop();
    '''

    This does half of the work.

    ## Graphic rendering

    On modern webkit, if you use 3D css then your elements are both cached as bitmap (one object to render for the element and children). This works for scroll effects, but actually also for every kind of animations and transitions. It works really (really) well on the mobile too.

    ``` css
    transform: translate3d(0,0,0);
    -moz-transform: translate3d(0,0,0);
    -webkit-transform: translate3d(0,0,0);
    ```

    Be carefull with `position:fixed` inside a 3D element, they will appear like they were absolute.

    ## Precalculate sizes and positions

    Like I said before, the browser is calculating a lot of things when you modify the DOM. A smooth animation should have between 30 and 60 franes (and reflows) per second. If you ask too much calculation at each frame then your animation will be slower. jQuery doesn't help much for that (big objects, no cache).

    Since the requestAnimationFrame works all the time and not only when you scroll, you better tells your browser that it has nothing to calculate if you haven't scrolled:

    ``` js
    var lastPosition = -1;

    function loop(){
    // Avoid calculations if not needed
    if (lastPosition == window.pageYOffset) {
    scroll(loop);
    return false;
    } else lastPosition = window.pageYOffset;

    //... calculations

    scroll( loop );
    ```

    I suggest you to have a look at the whole attached piece of code, that is structured like that:

    * Detect advanced features
    * Define all variables
    * Precalculation function (called on load and resize)
    * Loop function (called up to 60 times per second)
    * Try to skip calculations
    * Find elements that will change
    * Modify the DOM
    108 changes: 108 additions & 0 deletions exemple.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,108 @@
    <!doctype html>
    <html>
    <head>
    <title>Faster scroll effect</title>
    <link rel="stylesheet" href="fse.css">
    </head>
    <body>
    <div id="wrapper">
    <section>
    <article>
    <h1>SCROLL DOWN</h1>
    </article>
    </section>
    <section class="stick">
    <article>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

    </article>
    </section>
    <section class="stick">
    <article>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </article>
    </section>
    <section>
    <article>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </article>
    </section>
    </div>
    <script src="../fse.js"></script>
    </body>
    </html>
    22 changes: 22 additions & 0 deletions fse.css
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,22 @@
    html, body {
    height: 100%;
    }

    section {
    background: white;
    position: fixed;
    display:block;
    top: 0;
    left: 0;
    width: 100%;
    min-height: 100%;
    overflow: hidden;
    z-index: 100;
    transform: translate3d(0,0,0);
    -moz-transform: translate3d(0,0,0);
    -webkit-transform: translate3d(0,0,0);
    }

    section.stick {
    z-index: 10;
    }
    98 changes: 98 additions & 0 deletions fse.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,98 @@
    /*
    * Faster Scroll Effect
    * Version: 0.1
    * Copyright 2012
    * MIT Licence
    */

    (function(){

    // Detect css transform
    var cssTransform = (function(){
    var prefixes = 'transform webkitTransform mozTransform oTransform msTransform'.split(' ')
    , el = document.createElement('div')
    , cssTransform
    , i = 0
    while( cssTransform === undefined ){
    cssTransform = document.createElement('div').style[prefixes[i]] != undefined ? prefixes[i] : undefined
    i++
    }
    return cssTransform
    })()

    // Detect request animation frame
    var scroll = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame || function(callback){ window.setTimeout(callback, 1000/60) }
    , has3d = document.body.style.transform
    , lastPosition = -1
    , wHeight = window.innerHeight
    , wrapper = document.getElementById("wrapper")
    , elements = document.getElementsByTagName("section")
    , size = elements.length
    , matrix = []

    // Pre calculate sizes to get better perfs
    function sizes(){
    wHeight = window.innerHeight
    var i = 0
    for (i =0; i<size; i++){
    matrix[i] = matrix[i] || { el: elements[i] }

    // Reinit
    matrix[i].el.style.display = "block"
    lastPosition = -1

    matrix[i].height = matrix[i].el.offsetHeight
    matrix[i].start = matrix[i-1] ? matrix[i-1].stop : 0
    matrix[i].stop = matrix[i-1] ? matrix[i-1].stop + matrix[i].height : matrix[i].height
    matrix[i].isScroll = matrix[i].el.className.indexOf("stick") < 0

    // If it's sticked but higher than the screen...
    if (matrix[i].height - wHeight > 0) matrix[i].gap = matrix[i].height - wHeight

    // Let's find a index
    matrix[i].el.style.zIndex = !matrix[i].isScroll ? 10 - i : 100 - i
    }
    wrapper.style.height = matrix[i-1].stop + "px"
    }
    window.onresize = sizes

    function setTop(m, t){
    if (cssTransform)
    m.el.style[cssTransform] = "translate3d(0, "+ t +"px,0)"
    else
    m.el.style["top"] = t
    }

    function loop(){
    // Avoid calculations if not needed
    if (lastPosition == window.pageYOffset) {
    scroll(loop)
    return false
    } else lastPosition = window.pageYOffset

    var i = 0
    for (i =0; i<size; i++){
    // Is it visible right now?
    if (lastPosition >= matrix[i].start - wHeight && lastPosition <= matrix[i].stop){
    matrix[i].el.style.display = "block"
    if (
    // Is it scrolling?
    (matrix[i].isScroll) ||
    // Or is it stick, but higher than window?
    (!matrix[i].isScroll && matrix[i].gap && lastPosition >= matrix[i].start)
    )
    setTop(matrix[i], matrix[i].start - lastPosition)
    } else {
    matrix[i].el.style.display = "none"
    }
    }
    scroll(loop)
    }

    // Let's go
    function init(){
    sizes()
    loop()
    }

    })();