I'm designing a layout similar to the sidebar of the CodePen. While I've managed to replicate most of its behavior, I'm facing an issue when sliding windows upwards—everything works smoothly. However, when sliding downwards, the containers at the bottom fail to expand fully, unlike the demonstration in the provided code. Could someone point out where I might be making an error and help me rectify it?
function handleEditorWindowResize () {
const parent = document.querySelector("aside")
const editorWindows = document.querySelectorAll("aside > div")
const labelHeight = document.querySelector(".lang-label")
.getBoundingClientRect().height-4
const handleResize = (ele)=> {
let startY =0, height = 0;
const disableInteraction = (ele, state)=> {
if(state) {
ele.style.userSelect = 'none';
ele.style.pointerEvents = 'none';
} else {
ele.style.removeProperty('user-select');
ele.style.removeProperty('pointer-events');
}
}
const handleMouseDown = (e)=> {
startY = e.clientY - 2; // 2 coming from cuz we have 2px border of hr in css
height = ele.previousElementSibling.getBoundingClientRect().height;
editorWindows.forEach((ele) => {
disableInteraction(ele, true)
});
window.addEventListener("mousemove", handleMouseMove);
window.addEventListener("mouseup", handleMouseUp);
ele.style.borderWidth = `5px`;
}
const handleMouseMove = (e)=> {
const dy = e.clientY - startY;
const h = ((height + dy) * 100) / parent.getBoundingClientRect().height;
ele.previousElementSibling.style.height = `calc(max(${h}%, ${labelHeight}px)`;
editorWindows.forEach(win=> {
if(
win === ele.nextElementSibling
) {
win.style.flex = '1';
win.style.height = `${win.clientHeight}px`;
} else {
win.style.removeProperty("flex")
win.style.height = `${win.clientHeight}px`
}
})
}
const handleMouseUp = (e)=> {
editorWindows.forEach(ele => disableInteraction(ele, false));
window.removeEventListener("mousemove", handleMouseMove);
window.removeEventListener("mouseup", handleMouseUp);
ele.style.borderWidth = `2px`;
}
ele.addEventListener("mousedown",handleMouseDown);
}
document.querySelectorAll("aside > .h-divider")
.forEach(ele => handleResize(ele));
}
handleEditorWindowResize()
:root {
--black: #111;
--maroon: rgb(117, 14, 33);
--orange: rgb(227, 101, 29);
--green: rgb(190, 215, 84);
--text-color: rgba(255,255,255,1);
--light-text-color: rgba(255,255,255,0.8);
--overlay-color: rgba(255,255,255,0.1);
--gray-100: #111;
--gray-400: #444;
}
body, html {
width: 100%;
height: 100%;
overflow-x: hidden;
}
main {
display: flex;
width: 100%;
height: 100%;
}
.divider {
background-color: var(--gray-400);
cursor: ew-resize;
height: 100%;
width: 8px;
}
aside {
width: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
}
aside > div {
width: 100%;
display: flex;
flex-direction: column;
height: calc(100% / 3);
position: relative;
}
aside > div:last-child {
/* flex: 1; */
/* height: auto; */
}
aside > .h-divider {
border: 2px solid var(--gray-400);
position: sticky;
cursor: row-resize;
}
aside textarea {
overflow-y: auto;
min-width: 100%;
max-width: 100%;
flex:1;
padding: 0.5rem;
font-size: 0.8em;
background: var(--black);
border: none;
font-weight: 300;
border-bottom: 1px solid var(--gray-400);
background: var(--gray-100);
color: var(--light-text-color);
}
aside textarea:focus { outline: none; }
.lang-label {
padding: 0.3rem;
background-color: var(--maroon);
font-weight: 700;
display: flex;
align-items: center;
gap: 0.3rem;
position: relative;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<!-- main layout -->
<main>
<!-- code -->
<aside>
<div>
<div class="lang-label">
HTML
</div>
<textarea data-lang="html"></textarea>
</div>
<span class="h-divider"></span>
<div>
<div class="lang-label">
CSS
</div>
<textarea data-lang="css"></textarea>
</div>
<span class="h-divider"></span>
<div>
<div class="lang-label">
JS
</div>
<textarea data-lang="js"></textarea>
</div>
</aside>
</main>
</body>
</html>
Consider applying a small min-height
to the aside > div
elements. They implicitly have min-height: min-content
due to the vertical flex layout, so applying some other a small min-height
should enable the elements to shrink.
For example, here it is with min-height: 0
:
function handleEditorWindowResize () {
const parent = document.querySelector("aside")
const editorWindows = document.querySelectorAll("aside > div")
const labelHeight = document.querySelector(".lang-label")
.getBoundingClientRect().height-4
const handleResize = (ele)=> {
let startY =0, height = 0;
const disableInteraction = (ele, state)=> {
if(state) {
ele.style.userSelect = 'none';
ele.style.pointerEvents = 'none';
} else {
ele.style.removeProperty('user-select');
ele.style.removeProperty('pointer-events');
}
}
const handleMouseDown = (e)=> {
startY = e.clientY - 2; // 2 coming from cuz we have 2px border of hr in css
height = ele.previousElementSibling.getBoundingClientRect().height;
editorWindows.forEach((ele) => {
disableInteraction(ele, true)
});
window.addEventListener("mousemove", handleMouseMove);
window.addEventListener("mouseup", handleMouseUp);
ele.style.borderWidth = `5px`;
}
const handleMouseMove = (e)=> {
const dy = e.clientY - startY;
const h = ((height + dy) * 100) / parent.getBoundingClientRect().height;
ele.previousElementSibling.style.height = `calc(max(${h}%, ${labelHeight}px)`;
editorWindows.forEach(win=> {
if(
win === ele.nextElementSibling
) {
win.style.flex = '1';
win.style.height = `${win.clientHeight}px`;
} else {
win.style.removeProperty("flex")
win.style.height = `${win.clientHeight}px`
}
})
}
const handleMouseUp = (e)=> {
editorWindows.forEach(ele => disableInteraction(ele, false));
window.removeEventListener("mousemove", handleMouseMove);
window.removeEventListener("mouseup", handleMouseUp);
ele.style.borderWidth = `2px`;
}
ele.addEventListener("mousedown",handleMouseDown);
}
document.querySelectorAll("aside > .h-divider")
.forEach(ele => handleResize(ele));
}
handleEditorWindowResize()
:root {
--black: #111;
--maroon: rgb(117, 14, 33);
--orange: rgb(227, 101, 29);
--green: rgb(190, 215, 84);
--text-color: rgba(255,255,255,1);
--light-text-color: rgba(255,255,255,0.8);
--overlay-color: rgba(255,255,255,0.1);
--gray-100: #111;
--gray-400: #444;
}
body, html {
width: 100%;
height: 100%;
overflow-x: hidden;
}
main {
display: flex;
width: 100%;
height: 100%;
}
.divider {
background-color: var(--gray-400);
cursor: ew-resize;
height: 100%;
width: 8px;
}
aside {
width: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
}
aside > div {
width: 100%;
display: flex;
flex-direction: column;
height: calc(100% / 3);
position: relative;
min-height: 0;
}
aside > div:last-child {
/* flex: 1; */
/* height: auto; */
}
aside > .h-divider {
border: 2px solid var(--gray-400);
position: sticky;
cursor: row-resize;
}
aside textarea {
overflow-y: auto;
min-width: 100%;
max-width: 100%;
flex:1;
padding: 0.5rem;
font-size: 0.8em;
background: var(--black);
border: none;
font-weight: 300;
border-bottom: 1px solid var(--gray-400);
background: var(--gray-100);
color: var(--light-text-color);
}
aside textarea:focus { outline: none; }
.lang-label {
padding: 0.3rem;
background-color: var(--maroon);
font-weight: 700;
display: flex;
align-items: center;
gap: 0.3rem;
position: relative;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<!-- main layout -->
<main>
<!-- code -->
<aside>
<div>
<div class="lang-label">
HTML
</div>
<textarea data-lang="html"></textarea>
</div>
<span class="h-divider"></span>
<div>
<div class="lang-label">
CSS
</div>
<textarea data-lang="css"></textarea>
</div>
<span class="h-divider"></span>
<div>
<div class="lang-label">
JS
</div>
<textarea data-lang="js"></textarea>
</div>
</aside>
</main>
</body>
</html>
The lang-label
gets hidden though, so perhaps have the min-height
be set to the height of the lang-label
.