我正在设计一个类似于 CodePen 的侧边栏的布局。虽然我已经成功地复制了它的大部分行为,但向上滑动窗口时我遇到了一个问题 - 一切都很顺利。然而,当向下滑动时,底部的容器无法完全展开,这与提供的代码中的演示不同。有人可以指出我可能犯错误的地方并帮助我纠正吗?
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>
考虑对
min-height
元素应用一个小的 aside > div
。由于垂直弹性布局,它们隐式具有 min-height: min-content
,因此应用其他一些小的 min-height
应该可以使元素收缩。
例如,这里是
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>
但是
lang-label
被隐藏了,所以也许可以将 min-height
设置为 lang-label
的高度。