JSFiddle - React, Tailwind, and code Playground
by neonDog
HTML
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.css">
<!--
Bootstrap docs: https://getbootstrap.com/docs
-->
<div class="container text-center">
<div class="row neon-resizer neon-resizable-item" data-position="bottom" data-type="padding">
<div class="neon-resizable-col col" data-col="6">
1 of
</div>
<div class="neon-resizable-col col" data-col="6">
2 of 2
</div>
</div>
<div class="row neon-resizable-item" data-position="bottom" data-type="padding">
<div class="neon-resizable-col col" data-col="4">
1 of 3
</div>
<div class="neon-resizable-col col" data-col="4">
2 of 3
</div>
<div class="neon-resizable-col col" data-col="4">
3 of 3
</div>
</div>
<br>
<br>
<img class="neon-resizable-item border rounded" data-type="padding" src="https://image.shutterstock.com/image-photo/beautiful-water-drop-on-dandelion-260nw-789676552.jpg">
</div>
SCSS
.drag-bar {
position: fixed;
background: rgba(100, 100, 150, 0.3);
}
.row {
background: #f8f9fa;
min-height: 100px;
}
.neon-resizable-col {
position: relative;
border: 1px solid #aaa;
&.active::after {
background-color: var(--primary)!important;
}
&[data-col]::after {
z-index:10;
content: " ";
background-color: #eee;
position: absolute;
right: -2px;
width: 4px;
height: 100%;
cursor: w-resize;
background-repeat: no-repeat;
background-position: 50%;
background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
}
&[data-position="bottom"]::before {
z-Index:10;
content: " ";
position: absolute;
bottom:-2px;
height: 2px;
width: 100%;
cursor: s-resize;
background-color: var(--primary);
}
}
JavaScript
const applyColClass = function(el, cols, classPrefix) {
const collClass = cols > 0 ? classPrefix + '-' + cols : classPrefix;
el.className = collClass + ' neon-resizable-col';
el.setAttribute('data-col', cols);
}
class NeonResizableColumn {
constructor(settings = {}) {
const defaults = {
container: document.body,
columns: 12,
classPrefix: 'col-sm',
mode: 'class', // 'class', 'percent', 'pixel'
};
this.options = Object.assign({}, defaults, settings);
this.resetUI();
this._animate = this._animate.bind(this);
this._mousedown = this._mousedown.bind(this);
this._mouseup = this._mouseup.bind(this);
this._mousemove = this._mousemove.bind(this);
this.moveListenersActive = false;
this.eventListenersActive = false;
this._eventListeners();
}
resetUI() {
this.ui = {mouse:[], dragBar:null, colSpans:[], panels:[], bounds:[], active:false, otherCols:0};
}
_mousedown(e) {
if (this.ui.active) return;
this.resetUI();
const col = e.target.closest('.neon-resizable-col');
if (!col) return;
const b = col.getBoundingClientRect();
const positions = ['top','right', 'bottom', 'left'];
const intersects = [];
for (let i=0; i < 3; i++) {
const pos = positions[i];
const axis = i & 1 ? 'clientX' : 'clientY';
if (b[pos] - 3 < e[axis] && b[pos] + 3 > e[axis]) {
intersects.push(pos);
}
}
if (intersects.length === 0) return;
e.preventDefault();
e.stopPropagation();
col.classList.add('active');
const ui = this.ui;
if (intersects.includes('right')) {
ui.dragBar = document.createElement('div');
ui.dragBar.className = 'drag-bar';
ui.dragBar.setAttribute('style', `width:${ 4 || b.width }px; height:${ b.height }px; top:${ b.top }px; left:${ b.right }px;`);
document.body.append(ui.dragBar);
}
ui.data = col.dataset;
...