JSFiddle - React, Tailwind, and code Playground

by BurpmanJunior

HTML

<section class="wrap">
  <div id="mover"></div>

  <p>Nulla porta dolor. Vestibulum suscipit nulla quis orci. Etiam imperdiet imperdiet orci. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Sed a libero.</p>
  <p>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Vivamus consectetuer hendrerit lacus. Donec orci lectus, aliquam ut, faucibus non, euismod id, nulla. Sed fringilla mauris sit amet nibh.</p>
  <p>Maecenas vestibulum mollis diam. Vivamus in erat ut urna cursus vestibulum. Cras varius. Phasellus blandit leo ut odio. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis.</p>
  <p>Praesent blandit laoreet nibh. Phasellus accumsan cursus velit. Donec sodales sagittis magna. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Cras risus ipsum, faucibus ut, ullamcorper id, varius ac, leo.</p>
  <p>Curabitur blandit mollis lacus. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, lacus. Nunc sed turpis. Maecenas ullamcorper, dui et placerat feugiat, eros pede varius nisi, condimentum viverra felis nunc et lorem. Aenean ut eros et nisl sagittis vestibulum.</p>
</section>

CSS

*,
*:before,
*:after{
  box-sizing: border-box;
}

.wrap{
  max-width: 640px;
  padding: 20px;
  margin: 0 auto;
  position: relative;
}

#mover{
  width: 100px;
  height: 100px;
  background-color: #353535;
  cursor: move;
}

#mover:active{
  background-color: #555;
}

JavaScript

/**
 * Drag
 */
function _drag(el, dragFn, downFn, upFn, rel){
	el.addEventListener('mousedown', function(downEvt){
  	var OFFSET_X = 0,
        OFFSET_Y = 0,
        REL_X = 0,
        REL_Y = 0,
        elRect,
        dragFnInner,
        upFnInner;
        
    // Set relative offset
    if(rel){
    	var relRect = rel.getBoundingClientRect();
      REL_X = relRect.left - window.scrollX;
      REL_Y = relRect.top - window.scrollY;
    }
    
    // Set offsets
    elRect = el.getBoundingClientRect();
    OFFSET_X = (downEvt.clientX - (elRect.left - window.scrollX)) + REL_X;
    OFFSET_Y = (downEvt.clientY - (elRect.top - window.scrollY)) + REL_Y;
    el.OFFSET_X = OFFSET_X;
    el.OFFSET_Y = OFFSET_Y;
    
    // Prevent drag slip selections
    document.body.style.userSelect = document.body.style.webkitUserSelect = document.body.style.MozUserSelect = 'none';
       
    // Apply mousedown callback
  	if(downFn){
    	downFn.apply(el, [downEvt]);
    }
    
    var dragFnInner = function(moveEvt){
    	// Core drag event
    	dragFn.apply(el, [moveEvt]);
    }
    
    var upFnInner = function(upEvt){
    	// Remove slip select protection
      document.body.style.userSelect = document.body.style.webkitUserSelect = document.body.style.MozUserSelect = '';
    
    	// Apply mouseup callback
    	if(upFn){
      	upFn.apply(el, [upEvt]);
      }
      
      // Remove 2nd level listeners
      window.removeEventListener('mousemove', dragFnInner);
      window.removeEventListener('mouseup', upFnInner);
    }
    
    // Apply 2nd level listeners
    window.addEventListener('mousemove', dragFnInner);
    window.addEventListener('mouseup', upFnInner);
  }, false);
}


/**
 * DEMO
 */
var mover = document.getElementById('mover');
_drag(mover, function(e){
	// Drag
	this.style.left = (e.x - this.OFFSET_X) + 'px';
	this.style.top = (e.y - this.OFFSET_Y) + 'px';
}, function(e){
	// Down
	console.log('Grabbed');
  this.style.position = 'absolute';
}, function(e){
	//...