JSFiddle - React, Tailwind, and code Playground

by khamer

HTML

<h1>
            Consectetur fuga dolor similique aperiam!
        </h1>


        <h2>
            Amet architecto dignissimos pariatur.
        </h2>
        <p>Adipisicing eveniet id corporis fugiat quidem laborum vitae. Ratione
            aliquid dolorum harum ipsa ipsum soluta voluptates? Illum quisquam
            deleniti ducimus dolorum magni, laborum voluptas provident earum
            iure possimus. Adipisci dolorem quas a animi quisquam deserunt
            provident repellendus repudiandae. Explicabo sint.</p>
        <p>Dolor dignissimos commodi iusto voluptatibus quae. Recusandae animi
            placeat modi vel accusamus commodi! Sapiente aspernatur provident
            dolorum vitae veniam quo expedita rem tenetur. Libero eveniet ipsa
            quidem repellat animi maxime doloremque esse repudiandae quam
            aspernatur doloribus ipsam dolores? A culpa.</p>
        <p>Adipisicing optio deserunt quis voluptate veniam. Explicabo natus est
            necessitatibus dolores placeat consequatur autem laborum rerum sint
            vero. Adipisci perspiciatis voluptatibus perferendis dolorum
            maiores. Autem perferendis at placeat tempora architecto vero odit
            doloribus nisi. Consequatur officia repellat assumenda soluta
            molestias.</p>
        <h3>
            Lorem at dolorem repudiandae laboriosam molestiae.
        </h3>
        <ul>
            <li>Adipisicing nihil modi libero odit voluptas laudantium in
                blanditiis. Optio nisi tempore cum fugiat neque.</li>
            <li>Lorem inventore molestiae maiores sunt voluptas. Provident eius
                officia ea facere voluptates. Voluptates praesentium nihil.</li>
            <li>Ipsum fugit consequatur quisquam eius placeat consectetur
                maxime, dolor corporis! Animi deserunt culpa nobis
                necessitatibus.</li>
            <li>Sit cum corporis laudantium sed ratione? Itaque unde at aut eius
               ...

CSS

html, body {
    margin: 0;
    padding: 0;
    font: 18px/2 arial;
}

body {
    padding: 1em;
}

.box {
    width: 100px;
    height: 100px;
    background: red;
}

JavaScript

;(function($, window) {

    /**
     * options
     *
     *     start
     *         How far from the top edge of the screen to start sticking.
     *     until
     *         A selector or element to release when comes on screen.
     *     duration
     *         How many pixels of scroll to stay on screen.
     */
    var FixedElement = function(elem, options) {
        var defaults = {
            startOffset: 0,
            stopEarly: 0
        };
        options = $.extend(defaults, options);

        var that = this,
            state = 'init',
            elem = $(elem),
            dupe = elem
            .clone()
            .addClass('fixed-element-duplicate')
            .css({
                visibility: 'hidden'
            })
            .insertAfter(elem);

        if ('until' in options) {
            options.until = $(options.until);
        }

        elem.css({
            position: 'absolute'
        });

        that.startAt = function() {
            return dupe.offset().top - options.startOffset;
        };

        that.endAt = function() {
            var offset = that.startAt();
            if ('duration' in options) {
                offset += options.duration;
            } else if ('until' in options) {
                offset = options.until.offset().top;
            }

            if ('endOffset' in options) {
                offset -= options.endOffset;
            } else {
                offset -= options.startOffset;
            }

            return offset - options.stopEarly;
        };

        that.release = function(top) {
            console.log('release', top);
            state = 'released';
            elem.css({
                position: 'absolute',
                top: '',
                transform: 'translate(0, ' + top + 'px)'
            });
        };

        that.fix = function(percentage) {
            var offset = options.startOffset;

            if (percentage !== undefined) {
                offset +=...