JSFiddle - React, Tailwind, and code Playground

by gunderson

HTML

<p>Brunch tofu disrupt, American Apparel chambray swag narwhal sartorial lomo. Ugh roof party +1, wolf slow-carb swag hashtag post-ironic leggings banh mi Wes Anderson bicycle rights Shoreditch. Neutra Pinterest gastropub heirloom food truck YOLO. Authentic Schlitz Brooklyn keffiyeh. Thundercats flexitarian chia put a bird on it, before they sold out keffiyeh pug single-origin coffee authentic small batch yr 90's street art. Pug vinyl banh mi, Helvetica Wes Anderson hella pickled squid iPhone mlkshk Blue Bottle. Letterpress cred locavore squid, PBR&amp;B Thundercats polaroid meggings vegan mlkshk iPhone mustache.</p>
<p>Flannel cornhole roof party keytar fingerstache. Ethical actually yr, Tumblr VHS freegan Neutra cred kogi plaid irony twee hashtag YOLO readymade. Slow-carb salvia Odd Future umami, leggings wolf cardigan High Life Tumblr pug four loko drinking vinegar jean shorts forage. Church-key twee irony gastropub banjo, drinking vinegar butcher. Skateboard ethical chia deep v, vegan keytar synth pickled asymmetrical Shoreditch PBR&amp;B banh mi McSweeney's Kickstarter Blue Bottle. Hella umami lomo, master cleanse Helvetica literally banh mi. Street art McSweeney's beard quinoa readymade.</p>
<p>Pickled Cosby sweater cray fashion axe, Neutra mustache umami blog narwhal tousled vegan Bushwick disrupt. Hoodie photo booth gentrify crucifix, Helvetica ethical slow-carb viral normcore banjo keffiyeh. Letterpress VHS Intelligentsia, ennui fanny pack photo booth art party flannel messenger bag gastropub skateboard +1 normcore Brooklyn. Next level seitan meh, raw denim food truck wolf ugh. Photo booth retro pug 90's. Selvage Wes Anderson mustache fashion axe keffiyeh. Pitchfork Marfa vegan dreamcatcher, pop-up hashtag Odd Future swag scenester fashion axe Bushwick keffiyeh selvage slow-carb pork belly.</p>
<p>Craft beer pickled meggings mlkshk. Fashion axe craft beer mumblecore hella disrupt wolf, YOLO Kickstarter Thundercats typewriter farm-to-table. Ennui kale...

CSS

body{
    background: #f00;
    color: #fff;
    cursor: default;
}



.line{
    transform: translate3d(0,0,0);
}

.word{
    padding-right: 5px;
}

JavaScript

$(document).ready(onReady);

function onReady(){
    $("p").each(makeSpans);
    $(window)
        .on("scroll", onScroll)
        .on("resize", onResize);
    onScroll();
}

function onResize(){
    $("p").each(makeSpans);
    onScroll();
}

function makeSpans(){
    var $p = $(this);
    $p.find("span").contents().unwrap();
    var text = $p.text();
    var words = text.split(" ");
    var html = "<span class='word'>" + words.join("</span> <span class='word'>") + "</span>";
    $p.html(html);
    var _$lines = [];
    var lines = [];
    var lineNo = -1;
    $p.find("span").each(function(i, o){
        var $word = $(this);
        if (i > 0 && _$lines[lineNo] && $word.position().top === _$lines[lineNo][0].position().top){
            // it's the same line
            _$lines[lineNo].push($word);
            lines[lineNo].push(this);
        } else {
            _$lines[++lineNo] = [];
            lines[lineNo] = [];
            _$lines[lineNo].push($word);
            lines[lineNo].push(this);
        }
    });
    lines.forEach(function(line){
        $(line).wrapAll("<span class='line'>"); 
    });
    $p.find(".word").contents().after(" ").unwrap();
    $p.find(".word").remove();
}

function onScroll(){
    console.log("scroll");
    var pageTop = $(window).scrollTop();
    $("p").each(function(){
        var $p = $(this);
        var offset = $p.offset();
        var height = $p.height();
        var bottomOffset = offset.top + height;
        if (offset.top < pageTop + window.innerHeight && bottomOffset > pageTop){
            evaluateLines($p);   
        }
    });
}

function evaluateLines($p){
    var pageTop = $(window).scrollTop();
    var halfHeight = window.innerHeight >> 1;
    $p.find(".line").each(function(){
        var $line = $(this);
        var offset = $line.offset();
        var percentFromCenter = Math.abs(((offset.top - pageTop) - halfHeight) / halfHeight);
        percentFromCenter *= percentFromCenter * percentFromCenter;
       ...