JSFiddle - React, Tailwind, and code Playground

by Dogbert

HTML

<p>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit perspiciatis ullam sequi? Cumque reprehenderit blanditiis odio deleniti non ipsa minima dolorum sit autem laborum excepturi, illo. Obcaecati tempora asperiores nulla.
</p>
<p>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit perspiciatis ullam sequi? Cumque reprehenderit blanditiis odio deleniti non ipsa minima dolorum sit autem laborum excepturi, illo. Obcaecati tempora asperiores nulla.
</p>
<p>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit perspiciatis ullam sequi? Cumque reprehenderit blanditiis odio deleniti non ipsa minima dolorum sit autem laborum excepturi, illo. Obcaecati tempora asperiores nulla.
</p>
<p>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit perspiciatis ullam sequi? Cumque reprehenderit blanditiis odio deleniti non ipsa minima dolorum sit autem laborum excepturi, illo. Obcaecati tempora asperiores nulla.
</p>
<p>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit perspiciatis ullam sequi? Cumque reprehenderit blanditiis odio deleniti non ipsa minima dolorum sit autem laborum excepturi, illo. Obcaecati tempora asperiores nulla.
</p>
<p>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit perspiciatis ullam sequi? Cumque reprehenderit blanditiis odio deleniti non ipsa minima dolorum sit autem laborum excepturi, illo. Obcaecati tempora asperiores nulla.
</p>
<p>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit perspiciatis ullam sequi? Cumque reprehenderit blanditiis odio deleniti non ipsa minima dolorum sit autem laborum excepturi, illo. Obcaecati tempora asperiores nulla.
</p>
<p>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit perspiciatis ullam sequi? Cumque reprehenderit blanditiis odio deleniti non ipsa minima dolorum sit autem laborum excepturi, illo. Obcaecati tempora asperiores nulla.
</p>
<p>
  Lorem ipsum dolor sit amet,...

CSS

* {
  box-sizing: border-box;
}

body {
  background: url(http://subtlepatterns2015.subtlepatterns.netdna-cdn.com/patterns/restaurant_icons.png);
  font-size: 14px;
  margin: 60px 10px;
}

p {
  margin: 20px 3% 70px 3%;
  padding: 20px;
  background: steelblue;
  color: white;
  font-family: Open Sans;
  width: 44%;
  float: left;
}

JavaScript

(function($) {
  var $elements = [];
  var isRunning = false;

  $.fn.parallaxScrolling = function() {
    var ret = this.each(function() {
      $elements.push($(this));
    });
    recalculate();
    return ret;
  }

  var $window = $(window);
  $window.on("resize orientationchange", recalculate);
  $window.on("scroll", resume);

  function recalculate() {
    var windowHeight = $(window).height();
    for (var i = 0; i < $elements.length; i++) {
      var $element = $elements[i];
      var transform = $element.css("transform");
      $element.css("transform", "");
      var offsetTop = $element.offset().top;
      var outerHeight = $element.outerHeight();
      $element.attr("data-top", offsetTop);
      $element.attr("data-bottom", offsetTop + outerHeight);
      $element.attr("data-start", offsetTop - windowHeight);
      $element.attr("data-stop", offsetTop + outerHeight);
      $element.css("transform", transform);
    };
    resume();
  }

  function resume() {
    if (!isRunning) {
      isRunning = true;
      requestAnimationFrame(tick);
    }
  }

  function tick() {
    // console.log("tick");
    var anyChanged = false;
    var windowHeight = $(window).height();
    var windowScrollTop = $(window).scrollTop();
    for (var i = 0; i < $elements.length; i++) {
      var $element = $elements[i];
      var offsetTop = $element.attr('data-top');
      var offsetBottom = $element.attr('data-bottom');
      var movement = -windowHeight / 5;
      var translateY;
      if (offsetTop > (windowScrollTop + windowHeight)) {
        translateY = -movement * 0.5;
      } else if (offsetBottom < windowScrollTop) {
        translateY = movement * 0.5;
      } else {
        var start = $element.attr('data-start');
        var stop = $element.attr('data-stop');
        var percent = (windowScrollTop - start) / (stop - start) - 0.5;
        var destY = movement * percent;
        var currentY = 0;
        var transform = $element.css('transform');
        if...