Resizeable Demo
by Nicholas Berlette
HTML
<div id="resizeable">
<div id="handle"></div>
</div>
CSS
.resizeable {
--resizeable-width: 300px;
--resizable-height: 100vh;
width: var(--resizeable-width);
min-width: var(--min-width, 1vw);
max-width: var(--max-width, 100vw);
height: var(--resizable-height);
min-height: var(--min-height, 1vh);
max-height: var(--max-height, 100vh);
background-color: grey;
}
.x-handle {
float: right;
height: 100vh;
width: 1px;
background-color: #0006;
border-left: 1px solid #fff6;
border-right: 1px solid #fff6;
z-index: 1;
}
.x-handle::after {
content: "";
width: 9px;
position: absolute;
top: 0;
bottom: 0;
margin-left: -4px;
background-color: transparent;
cursor: ew-resize;
z-index: 2;
}
.y-handle {
width: 100vw;
height: 1px;
background-color: #0006;
border-top: 1px solid #fff6;
border-bottom: 1px solid #fff6;
z-index: 1;
}
.y-handle::after {
content: "";
height: 9px;
position: absolute;
top: 0;
bottom: 0;
margin-top: -4px;
background-color: transparent;
cursor: ns-resize;
z-index: 2;
}
body {
margin: 0px;
}
* {
box-sizing: border-box;
}
JavaScript
const getResizeableElement = () => $(".resizeable");
const getHandleElement = (dir = "x") => $(`.${dir}-handle`);
const minPaneWidth = 150;
const maxPaneWidth = document.body.clientWidth * 0.75;
const minPaneHeight = 150;
const maxPaneHeight = document.body.clientHeight * 0.75;
getResizeableElement().style.setProperty('--max-width', `${maxPaneWidth}px`);
getResizeableElement().style.setProperty('--min-width', `${minPaneWidth}px`);
getResizeableElement().style.setProperty('--max-height', `${maxPaneHeight}px`);
getResizeableElement().style.setProperty('--min-height', `${minPaneHeight}px`);
const setPaneWidth = (width) => {
getResizeableElement().style
.setProperty('--resizeable-width', `${width}px`);
};
const getPaneWidth = () => {
const computed = getComputedStyle(getResizeableElement());
return parseInt(computed.getPropertyValue('--resizeable-width'), 10);
};
const setPaneHeight = (width) => {
getResizeableElement().style.setProperty('--resizeable-width', `${width}px`);
};
const getPaneWidth = () => {
const computed = getComputedStyle(getResizeableElement());
return parseInt(computed.getPropertyValue('--resizeable-width'), 10);
};
const startDragging = (event) => {
event.preventDefault();
const host = getResizeableElement();
const startingPaneWidth = getPaneWidth();
const xOffset = event.pageX;
const mouseDragHandler = (moveEvent) => {
moveEvent.preventDefault();
const primaryButtonPressed = moveEvent.buttons === 1;
if (!primaryButtonPressed) {
setPaneWidth(Math.min(Math.max(getPaneWidth(), minPaneSize), maxPaneSize));
document.body.removeEventListener('pointermove', mouseDragHandler);
return;
}
const paneOriginAdjustment = 'left' === 'right' ? 1 : -1;
setPaneWidth((xOffset - moveEvent.pageX ) * paneOriginAdjustment + startingPaneWidth);
};
const remove = document.body.addEventListener('pointermove', mouseDragHandler);
};
getHandleElement().addEventListener('mousedown', startDragging);