在 HTML 中进行拆分窗格的最佳方法 [关闭]
Posted
技术标签:
【中文标题】在 HTML 中进行拆分窗格的最佳方法 [关闭]【英文标题】:Best way to do a split pane in HTML [closed] 【发布时间】:2012-08-25 00:56:40 【问题描述】:有没有一种很好的技术可以在 html 中制作可调整大小的拆分窗格?
是否可以使用 CSS / jQuery / javascript 完成,或者有没有使用过的好的 JavaScript 库?
(拆分窗格的一个示例是Internet Explorer 中的收藏夹栏,您可能已停靠在主浏览器窗口的左侧。)
【问题讨论】:
没有非框架。好的方法显示在alistapart.com/articles/holygrail 【参考方案1】:我想要一个普通的轻量级(jQuery UI 布局大小为 185 KB),没有依赖选项(所有现有库都需要 jQuery),所以我写了Split.js。
它的重量小于 2 KB,不需要任何特殊标记。它支持旧版浏览器回到 Internet Explorer 9(或 Internet Explorer 8 与 polyfills)。对于现代浏览器,您可以将其与 Flexbox 和 grid 布局一起使用。
【讨论】:
PS:重量不仅仅是文件大小的问题,而是性能的问题。 JQuery 和 JQuery-UI 在这方面非常重要。所以非常感谢你:) @Sir.Walek 您可以在存储库上打开一个问题。 我现在在玩 split.js,当你创建一个 Split 实例时,你可以提供一个可选参数 sizes。如果您有两个窗格,并且您提供 [70,30],则窗格 1 为 70%,窗格 2 为 30%。我正在查看窗格以进行我正在做的垂直拆分,我真的很想能够使底部窗格具有固定大小(例如 25 像素),而顶部窗格占据剩余空间。这可能吗? 感谢您的出色工作,但它是否支持单击排水沟折叠? @personal_cloud 有一个demo of it here。当我尝试使用 Chrome 时,我可以看到并拖动拆分器,不是吗?【参考方案2】:改进Reza's answer:
防止浏览器干扰拖动 防止将元素设置为负尺寸 防止由于元素宽度饱和的增量增量交互而导致拖动与鼠标不同步<html><head><style>
.splitter
width: 100%;
height: 100px;
display: flex;
#separator
cursor: col-resize;
background-color: #aaa;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='30'><path d='M2 0 v30 M5 0 v30 M8 0 v30' fill='none' stroke='black'/></svg>");
background-repeat: no-repeat;
background-position: center;
width: 10px;
height: 100%;
/* Prevent the browser's built-in drag from interfering */
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
#first
background-color: #dde;
width: 20%;
height: 100%;
min-width: 10px;
#second
background-color: #eee;
width: 80%;
height: 100%;
min-width: 10px;
</style></head><body>
<div class="splitter">
<div id="first"></div>
<div id="separator" ></div>
<div id="second" ></div>
</div>
<script>
// A function is used for dragging and moving
function dragElement(element, direction)
var md; // remember mouse down info
const first = document.getElementById("first");
const second = document.getElementById("second");
element.onmousedown = onMouseDown;
function onMouseDown(e)
//console.log("mouse down: " + e.clientX);
md = e,
offsetLeft: element.offsetLeft,
offsetTop: element.offsetTop,
firstWidth: first.offsetWidth,
secondWidth: second.offsetWidth
;
document.onmousemove = onMouseMove;
document.onmouseup = () =>
//console.log("mouse up");
document.onmousemove = document.onmouseup = null;
function onMouseMove(e)
//console.log("mouse move: " + e.clientX);
var delta = x: e.clientX - md.e.clientX,
y: e.clientY - md.e.clientY;
if (direction === "H" ) // Horizontal
// Prevent negative-sized elements
delta.x = Math.min(Math.max(delta.x, -md.firstWidth),
md.secondWidth);
element.style.left = md.offsetLeft + delta.x + "px";
first.style.width = (md.firstWidth + delta.x) + "px";
second.style.width = (md.secondWidth - delta.x) + "px";
dragElement( document.getElementById("separator"), "H" );
</script></body></html>
【讨论】:
由于某种原因,我的鼠标按下事件没有 e.x 只有 e.screenX ? @Didier A. 好收获。虽然 x/y 是 documented,但有一条注意不要在生产代码中使用它。我想你已经找到了真正的原因(出于好奇,哪个浏览器缺少 x/y?)所以我更新了我的答案以使用 clientX/clientY。不同事件类型之间似乎也更加一致。 Reza 的原始代码对所有事件都使用了 clientX/clientY。 这对我来说真的很好用竖起大拇指。 我认为,使用 flexbox 不需要 "element.style.left = [...]" 这一行,分隔符会自动移动;此外,“防止负尺寸元素”的行对于拆分工作也不是必需的。 对我来说真正有用的是background-image
内联 SVG 拖动句柄,我可以将其粘贴到 split-grid(特别是 vue-split-grid 包装器)装订线 CSS 中而无需修改。如果您选择使用罐装分离器,这很有用。【参考方案3】:
最简单的 HTML + CSS 手风琴,只需 CSS resize。
div
resize: vertical;
overflow: auto;
border: 1px solid
.menu
display: grid
/* Try height: 100% or height: 100vh */
<div class="menu">
<div>
Hello, World!
</div>
<div>
Hello, World!
</div>
<div>
Hello, World!
</div>
</div>
最简单的 HTML + CSS 垂直可调整大小的窗格:
div
resize: horizontal;
overflow: auto;
border: 1px solid;
display: inline-flex;
height: 90vh
<div>
Hello, World!
</div>
<div>
Hello, World!
</div>
纯 HTML,details element!。
<details>
<summary>Morning</summary>
<p>Hello, World!</p>
</details>
<details>
<summary>Evening</summary>
<p>How sweat?</p>
</details>
最简单的 HTML + CSS 顶栏折叠菜单
div
display: flex
summary,p
margin: 0px 0 -1px 0px;
padding: 0 0 0 0.5rem;
border: 1px black solid
summary
padding: 0 1rem 0 0.5rem
<div>
<details>
<summary>FILE</summary>
<p>Save</p>
<p>Save as</p>
</details>
<details>
<summary>EDIT</summary>
<p>Pump</p>
<p>Transfer</p>
<p>Review</p>
<p>Compile</p>
</details>
<details>
<summary>PREFERENCES</summary>
<p>How sweat?</p>
<p>Powered by HTML</p>
</details>
</div>
固定底部菜单栏,向上展开。
div
display: flex;
position: fixed;
bottom: 0;
transform: rotate(180deg)
summary,p
margin: 0px 0 -1px 0px;
padding: 0 0 0 0.5rem;
border: 1px black solid;
transform: rotate(180deg)
summary
padding: 0 1rem 0 0.5rem;
<div>
<details>
<summary>FILE</summary>
<p>Save</p>
<p>Save as</p>
</details>
<details>
<summary>EDIT</summary>
<p>Pump</p>
<p>Transfer</p>
<p>Review</p>
<p>Compile</p>
</details>
<details>
<summary>PREF</summary>
<p>How?</p>
<p>Power</p>
</details>
</div>
最简单的可调整大小的窗格,使用 JavaScript。
let ismdwn = 0
rpanrResize.addEventListener('mousedown', mD)
function mD(event)
ismdwn = 1
document.body.addEventListener('mousemove', mV)
document.body.addEventListener('mouseup', end)
function mV(event)
if (ismdwn === 1)
pan1.style.flexBasis = event.clientX + "px"
else
end()
const end = (e) =>
ismdwn = 0
document.body.removeEventListener('mouseup', end)
rpanrResize.removeEventListener('mousemove', mV)
div
display: flex;
border: 1px black solid;
width: 100%;
height: 200px;
#pan1
flex-grow: 1;
flex-shrink: 0;
flex-basis: 50%; // initial status
#pan2
flex-grow: 0;
flex-shrink: 1;
overflow-x: auto;
#rpanrResize
flex-grow: 0;
flex-shrink: 0;
background: #1b1b51;
width: 0.2rem;
cursor: col-resize;
margin: 0 0 0 auto;
<div>
<div id="pan1">MENU</div>
<div id="rpanrResize"> </div>
<div id="pan2">BODY</div>
</div>
【讨论】:
我喜欢这个答案。一个建议是在 JavaScript 版本中使用panel.style.flexBasis = event.clientX + "px";
和 flex-grow
和 flex-shrink
。
这个 javascript 答案正是我所需要的!好吧,我认为 end()
函数中的最后一条语句可能是 document.body.removeEventListener('mousemove', mV)
。此外,如果 #pan1
不是页面的最左侧,我还使用 getBoundingClientRect()
获取元素的左侧并计算 flex-basis
的值。好吧,实际上我正在开发垂直版本,所以我使用 height
和 min-height
而不是 flex-basis
。【参考方案4】:
我为它编写了简单的代码,没有任何第三方库。此代码仅适用于水平分割器(垂直相同)。
function onload()
dragElement( document.getElementById("separator"), "H" );
// This function is used for dragging and moving
function dragElement( element, direction, handler )
// Two variables for tracking positions of the cursor
const drag = x : 0, y : 0 ;
const delta = x : 0, y : 0 ;
/* If present, the handler is where you move the DIV from
otherwise, move the DIV from anywhere inside the DIV */
handler ? ( handler.onmousedown = dragMouseDown ): ( element.onmousedown = dragMouseDown );
// A function that will be called whenever the down event of the mouse is raised
function dragMouseDown( e )
drag.x = e.clientX;
drag.y = e.clientY;
document.onmousemove = onMouseMove;
document.onmouseup = () => document.onmousemove = document.onmouseup = null;
// A function that will be called whenever the up event of the mouse is raised
function onMouseMove( e )
const currentX = e.clientX;
const currentY = e.clientY;
delta.x = currentX - drag.x;
delta.y = currentY - drag.y;
const offsetLeft = element.offsetLeft;
const offsetTop = element.offsetTop;
const first = document.getElementById("first");
const second = document.getElementById("second");
let firstWidth = first.offsetWidth;
let secondWidth = second.offsetWidth;
if (direction === "H" ) // Horizontal
element.style.left = offsetLeft + delta.x + "px";
firstWidth += delta.x;
secondWidth -= delta.x;
drag.x = currentX;
drag.y = currentY;
first.style.width = firstWidth + "px";
second.style.width = secondWidth + "px";
.splitter
width: 500px;
height: 100px;
display: flex;
#separator
cursor: col-resize;
background: url(https://raw.githubusercontent.com/RickStrahl/jquery-resizable/master/assets/vsizegrip.png) center center no-repeat #535353;
width: 10px;
height: 100px;
min-width: 10px;
#first
background-color: green;
width: 100px;
height: 100px;
min-width: 10px;
#second
background-color: red;
width: 390px;
height: 100px;
min-width: 10px;
<html>
<head>
<link rel="stylesheet" href="T10-Splitter.css">
<script src="T10-Splitter.js"></script>
</head>
<body onload="onload()">
<div class="splitter">
<div id="first"></div>
<div id="separator"></div>
<div id="second"></div>
</div>
</body>
</html>
【讨论】:
很好的解决方案!迄今为止最好的方法。这是在 Mozilla 和 Chrome 中都适用于我的第一个答案。我已根据您的回答发布了一个新答案,但包含两个小(但重要)的修复程序,以防止分隔符“卡在鼠标上”或由于负 div 宽度而与鼠标不同步。【参考方案5】:这是我使用 Flexbox 的轻量级原生 JavaScript 方法:
http://codepen.io/lingtalfi/pen/zoNeJp
在Google Chrome 54, Firefox 50, Safari 10 测试成功,其他浏览器不知道。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.rawgit.com/lingtalfi/simpledrag/master/simpledrag.js"></script>
<style type="text/css">
html, body
height: 100%;
.panes-container
display: flex;
width: 100%;
overflow: hidden;
.left-pane
width: 18%;
background: #ccc;
.panes-separator
width: 2%;
background: red;
position: relative;
cursor: col-resize;
.right-pane
flex: auto;
background: #eee;
.panes-container,
.panes-separator,
.left-pane,
.right-pane
margin: 0;
padding: 0;
height: 100%;
</style>
</head>
<body>
<div class="panes-container">
<div class="left-pane" id="left-pane">
<p>I'm the left pane</p>
<ul>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
</ul>
</div>
<div class="panes-separator" id="panes-separator"></div>
<div class="right-pane" id="right-pane">
<p>And I'm the right pane</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. A accusantium at cum cupiditate dolorum, eius eum
eveniet facilis illum maiores molestiae necessitatibus optio possimus sequi sunt, vel voluptate. Asperiores,
voluptate!
</p>
</div>
</div>
<script>
var leftPane = document.getElementById('left-pane');
var rightPane = document.getElementById('right-pane');
var paneSep = document.getElementById('panes-separator');
// The script below constrains the target to move horizontally between a left and a right virtual boundaries.
// - the left limit is positioned at 10% of the screen width
// - the right limit is positioned at 90% of the screen width
var leftLimit = 10;
var rightLimit = 90;
paneSep.sdrag(function (el, pageX, startX, pageY, startY, fix)
fix.skipX = true;
if (pageX < window.innerWidth * leftLimit / 100)
pageX = window.innerWidth * leftLimit / 100;
fix.pageX = pageX;
if (pageX > window.innerWidth * rightLimit / 100)
pageX = window.innerWidth * rightLimit / 100;
fix.pageX = pageX;
var cur = pageX / window.innerWidth * 100;
if (cur < 0)
cur = 0;
if (cur > window.innerWidth)
cur = window.innerWidth;
var right = (100-cur-2);
leftPane.style.width = cur + '%';
rightPane.style.width = right + '%';
, null, 'horizontal');
</script>
</body>
</html>
此 HTML 代码依赖于 simpledrag vanilla JavaScript 轻量级库(少于 60 行代码)。
【讨论】:
努力。但请注意,此解决方案使用固定百分比的装订线宽度,因此您会在窄屏幕或宽屏幕上出现意外行为。 我真的很喜欢这个解决方案,并添加了一些 ui 肉汁让它变得漂亮。除其他外,就像@nathancahill 指出的那样,我将排水沟设为绝对值。希望它可以帮助某人。 codepen.io/theHeadlessSourceMan/pen/MWpaKGB【参考方案6】:嗯,我在 CSS 3 中发现了这个属性。 这可能更容易使用。
CSS resize Property
【讨论】:
【参考方案7】:在过去,您会使用框架来实现这一点。这种方法不太好有几个原因。请参阅 Reece 对 Why are HTML frames bad? 的回复。另请参阅 Jakob Nielson 的 Why Frames Suck (Most of the Time)。
有点较新的方法是使用内联框架。这也有优点和缺点:Are iframes considered 'bad practice'?
更好的方法是使用固定定位。通过将导航内容(例如您的示例中的收藏夹链接)放置在块元素(如 div
)中,然后将 position:fixed
应用于该元素并设置 left、top 和 bottom 属性,如下所示:
#myNav
position: fixed;
left: 0px;
top: 0px;
bottom: 0px;
width: 200px;
...您将在页面左侧实现垂直列,当用户滚动页面时该列不会移动。
页面上的其余内容不会“感觉到”这个 nav 元素的存在,所以它必须考虑到它占用的 200px 空间。您可以通过将内容的其余部分放在另一个 div 中并设置 margin-left:200px;
来做到这一点。
【讨论】:
很好的彻底回答。 ...我记得在 1998 年读过 JN 的文章“为什么帧很烂”...很抱歉,我在最初的问题中没有指出我希望能够调整拆分的大小。【参考方案8】:您可以使用 jQuery UI 来实现,而无需其他 JavaScript 库。只需在.resizable
resize 事件中添加一个函数即可调整其他 div 的宽度。
$("#left_pane").resizable(
handles: 'e', // 'East' side of div draggable
resize: function()
$("#right_pane").outerWidth( $("#container").innerWidth() - $("#left_pane").outerWidth() );
);
这是完整的JSFiddle。
【讨论】:
【参考方案9】:一种完全不同的方法是将事物放入网格中,例如 ui-grid 或 Kendo 的网格,并让列调整大小。一个缺点是用户将无法调整行的大小,尽管可以通过编程方式设置行大小。
【讨论】:
【参考方案10】:许多人错过了 2015 年 2 月 27 日 Barguast 的这篇文章,其中展示了一个有趣的通用 flexbox 垂直和水平调整器。
看一看:Flexbox Resizing
Barguast 注意到“......它只处理使用 flex-grow 调整大小的项目。如果定义了 flex-shrink 或 flex-basis,那么计算根本不起作用。”,他正在寻找更好的解决方案,我也是。
这是他的代码供参考:
function manageResize(md, sizeProp, posProp)
var r = md.target;
var prev = r.previousElementSibling;
var next = r.nextElementSibling;
if (!prev || !next)
return;
md.preventDefault();
var prevSize = prev[sizeProp];
var nextSize = next[sizeProp];
var sumSize = prevSize + nextSize;
var prevGrow = Number(prev.style.flexGrow);
var nextGrow = Number(next.style.flexGrow);
var sumGrow = prevGrow + nextGrow;
var lastPos = md[posProp];
function onMouseMove(mm)
var pos = mm[posProp];
var d = pos - lastPos;
prevSize += d;
nextSize -= d;
if (prevSize < 0)
nextSize += prevSize;
pos -= prevSize;
prevSize = 0;
if (nextSize < 0)
prevSize += nextSize;
pos += nextSize;
nextSize = 0;
var prevGrowNew = sumGrow * (prevSize / sumSize);
var nextGrowNew = sumGrow * (nextSize / sumSize);
prev.style.flexGrow = prevGrowNew;
next.style.flexGrow = nextGrowNew;
lastPos = pos;
function onMouseUp(mu)
window.removeEventListener("mousemove", onMouseMove);
window.removeEventListener("mouseup", onMouseUp);
window.addEventListener("mousemove", onMouseMove);
window.addEventListener("mouseup", onMouseUp);
function setupResizerEvents()
document.body.addEventListener("mousedown", function (md)
var target = md.target;
if (target.nodeType !== 1 || target.tagName !== "FLEX-RESIZER")
return;
var parent = target.parentNode;
var h = parent.classList.contains("h");
var v = parent.classList.contains("v");
if (h && v)
return;
else if (h)
manageResize(md, "scrollWidth", "pageX");
else if (v)
manageResize(md, "scrollHeight", "pageY");
);
setupResizerEvents();
flex
display: flex;
flex-item > flex
position: absolute;
width: 100%;
height: 100%;
flex.h
-ms-flex-direction: row;
flex-direction: row;
flex.v
-ms-flex-direction: column;
flex-direction: column;
flex-item
display: flex;
position: relative;
overflow: hidden;
flex > flex-resizer
-ms-flex: 0 0 8px;
flex: 0 0 8px;
background: white;
flex.h > flex-resizer
cursor: ew-resize;
flex.v > flex-resizer
cursor: ns-resize;
<body>
<flex class="v" style="height: 500px">
<flex-item style="flex: 1; background: red">Flex 1</flex-item>
<flex-resizer></flex-resizer>
<flex-item style="flex: 1; background: blue">
<flex class="h">
<flex-item style="flex: 1">Flex 2</flex-item>
<flex-resizer></flex-resizer>
<flex-item style="flex: 2; background: green">
<flex class="v">
<flex-item style="flex: 1; background: pink;">Flex 3</flex-item>
<flex-resizer></flex-resizer>
<flex-item style="flex: 1">
<flex class="h">
<flex-item style="flex: 1">Flex 4</flex-item>
<flex-resizer></flex-resizer>
<flex-item style="flex: 2; background: yellow">Flex 5</flex-item>
<flex-item style="flex: 2; background: yellow">Flex 6</flex-item>
</flex>
</flex-item>
</flex>
</flex-item>
</flex>
</flex-item>
</flex>
</body>
这是我的改进版:
function manageResize(md, sizeProp, posProp)
var r = md.target;
var prev = r.previousElementSibling;
var next = r.nextElementSibling;
if (!prev || !next)
return;
md.preventDefault();
var prevSize = prev[sizeProp];
var nextSize = next[sizeProp];
var sumSize = prevSize + nextSize;
var prevGrow = Number(prev.style.flexGrow);
var nextGrow = Number(next.style.flexGrow);
var sumGrow = prevGrow + nextGrow;
var lastPos = md[posProp];
function onMouseMove(mm)
var pos = mm[posProp];
var d = pos - lastPos;
prevSize += d;
nextSize -= d;
if (prevSize < 0)
nextSize += prevSize;
pos -= prevSize;
prevSize = 0;
if (nextSize < 0)
prevSize += nextSize;
pos += nextSize;
nextSize = 0;
var prevGrowNew = sumGrow * (prevSize / sumSize);
var nextGrowNew = sumGrow * (nextSize / sumSize);
prev.style.flexGrow = prevGrowNew;
next.style.flexGrow = nextGrowNew;
lastPos = pos;
function onMouseUp(mu)
// Change cursor to signal a state's change: stop resizing.
const html = document.querySelector('html');
html.style.cursor = 'default';
if (posProp === 'pageX')
r.style.cursor = 'ew-resize';
else
r.style.cursor = 'ns-resize';
window.removeEventListener("mousemove", onMouseMove);
window.removeEventListener("mouseup", onMouseUp);
window.addEventListener("mousemove", onMouseMove);
window.addEventListener("mouseup", onMouseUp);
function setupResizerEvents()
document.body.addEventListener("mousedown", function (md)
// Used to avoid cursor's flickering
const html = document.querySelector('html');
var target = md.target;
if (target.nodeType !== 1 || target.tagName !== "FLEX-RESIZER")
return;
var parent = target.parentNode;
var h = parent.classList.contains("h");
var v = parent.classList.contains("v");
if (h && v)
return;
else if (h)
// Change cursor to signal a state's change: begin resizing on H.
target.style.cursor = 'col-resize';
html.style.cursor = 'col-resize'; // avoid cursor's flickering
// use offsetWidth versus scrollWidth (and clientWidth) to avoid splitter's jump on resize when a flex-item content overflow (overflow: auto).
manageResize(md, "offsetWidth", "pageX");
else if (v)
// Change cursor to signal a state's change: begin resizing on V.
target.style.cursor = 'row-resize';
html.style.cursor = 'row-resize'; // avoid cursor's flickering
manageResize(md, "offsetHeight", "pageY");
);
setupResizerEvents();
body
/* margin:0; */
border: 10px solid #aaa;
flex
display: flex;
overflow: hidden;
/* flex-item > flex
position: absolute;
width: 100%;
height: 100%;
*/
flex.h
flex-direction: row;
flex.v
flex-direction: column;
flex-item
/* display: flex; */
/* position: relative; */
/* overflow: hidden; */
overflow: auto;
flex > flex-resizer
flex: 0 0 10px;
/* background: white; */
background-color: #aaa;
background-repeat: no-repeat;
background-position: center;
flex.h > flex-resizer
cursor: ew-resize;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='30'><path d='M2 0 v30 M5 0 v30 M8 0 v30' fill='none' stroke='black'/></svg>");
flex.v > flex-resizer
cursor: ns-resize;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='30' height='10'><path d='M0 2 h30 M0 5 h30 M0 8 h30' fill='none' stroke='black'/></svg>");
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>flex-splitter</title>
<link rel="stylesheet" href="./src/styles.css">
<script src="./src/index.js" defer></script>
</head>
<body>
<flex class="v" style="flex: 1; height: 500px;">
<flex-item style="flex: 1;">Flex 1</flex-item>
<flex-resizer></flex-resizer>
<flex class="h" style="flex: 1;">
<flex-item style="flex: 1; background-color: aqua;">
<!--
The next section is an example to test the splitter when there is content inside a flex-item
-->
<section>
<div>
<label for="CursorCoor" style="display: block;">showCursorCoor: </label>
<textarea id="CursorCoor" rows="6" cols="50" wrap="soft" readonly></textarea>
</div>
<br />
<div>
<label for="boxInfo" style="display: block;">showBoxInfo: </label>
<textarea id="boxInfo" rows="6" cols="50" wrap="soft" readonly></textarea>
</div>
</section>
</flex-item>
<flex-resizer></flex-resizer>
<flex class="v" style="flex: 2; ">
<flex-item style="flex: 1; background: pink;">Flex 3</flex-item>
<flex-resizer></flex-resizer>
<flex class="h" style="flex: 1">
<flex-item style="flex: 1; background: green;">Flex 4</flex-item>
<flex-resizer></flex-resizer>
<flex-item style="flex: 2;">Flex 5</flex-item>
<!-- <flex-resizer></flex-resizer> -->
<flex-item style="flex: 3; background: darkorange;">Flex 6</flex-item>
</flex>
</flex>
</flex>
</flex>
</body>
</html>
或在 Codesandbox 上查看:
【讨论】:
【参考方案11】:您可以使用绝对定位的固定定位。例如,此 CSS 会将 2em-bar 停靠在页面左侧:
body
padding-left: 2.5em;
body > #bar
position:fixed;
top:0; left:0;
width: 2em;
height: 100%;
border-right: 2px solid #55F; background: #ddd;
(Demo at jsfiddle.net)
【讨论】:
【参考方案12】:没有第三方库的 Angular 版本(基于personal_cloud's answer):
import Component, Renderer2, ViewChild, ElementRef, AfterViewInit, OnDestroy from '@angular/core';
@Component(
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
)
export class AppComponent implements AfterViewInit, OnDestroy
@ViewChild('leftPanel', static: true)
leftPanelElement: ElementRef;
@ViewChild('rightPanel', static: true)
rightPanelElement: ElementRef;
@ViewChild('separator', static: true)
separatorElement: ElementRef;
private separatorMouseDownFunc: Function;
private documentMouseMoveFunc: Function;
private documentMouseUpFunc: Function;
private documentSelectStartFunc: Function;
private mouseDownInfo: any;
constructor(private renderer: Renderer2)
ngAfterViewInit()
// Init page separator
this.separatorMouseDownFunc = this.renderer.listen(this.separatorElement.nativeElement, 'mousedown', e =>
this.mouseDownInfo =
e: e,
offsetLeft: this.separatorElement.nativeElement.offsetLeft,
leftWidth: this.leftPanelElement.nativeElement.offsetWidth,
rightWidth: this.rightPanelElement.nativeElement.offsetWidth
;
this.documentMouseMoveFunc = this.renderer.listen('document', 'mousemove', e =>
let deltaX = e.clientX - this.mouseDownInfo.e.x;
// set min and max width for left panel here
const minLeftSize = 30;
const maxLeftSize = (this.mouseDownInfo.leftWidth + this.mouseDownInfo.rightWidth + 5) - 30;
deltaX = Math.min(Math.max(deltaX, minLeftSize - this.mouseDownInfo.leftWidth), maxLeftSize - this.mouseDownInfo.leftWidth);
this.leftPanelElement.nativeElement.style.width = this.mouseDownInfo.leftWidth + deltaX + 'px';
);
this.documentSelectStartFunc = this.renderer.listen('document', 'selectstart', e =>
e.preventDefault();
);
this.documentMouseUpFunc = this.renderer.listen('document', 'mouseup', e =>
this.documentMouseMoveFunc();
this.documentSelectStartFunc();
this.documentMouseUpFunc();
);
);
ngOnDestroy()
if (this.separatorMouseDownFunc)
this.separatorMouseDownFunc();
if (this.documentMouseMoveFunc)
this.documentMouseMoveFunc();
if (this.documentMouseUpFunc)
this.documentMouseUpFunc();
if (this.documentSelectStartFunc())
this.documentSelectStartFunc();
.main
display: flex;
height: 400px;
.left
width: calc(50% - 5px);
background-color: rgba(0, 0, 0, 0.1);
.right
flex: auto;
background-color: rgba(0, 0, 0, 0.2);
.separator
width: 5px;
background-color: red;
cursor: col-resize;
<div class="main">
<div class="left" #leftPanel></div>
<div class="separator" #separator></div>
<div class="right" #rightPanel></div>
</div>
Running example on Stackblitz
【讨论】:
【参考方案13】:我找到了一个工作拆分器http://www.dreamchain.com/split-pane/,它适用于 jQuery v1.9。请注意,我必须添加以下 CSS 代码才能使其与固定的 bootstrap
导航栏一起使用。
fixed-left
position: absolute !important; /* to override relative */
height: auto !important;
top: 55px; /* Fixed navbar height */
bottom: 0px;
【讨论】:
【参考方案14】:一个很好的库是 Shield UI - 您可以看看他们灵活的Splitter widget 以及框架提供的其他强大组件。
【讨论】:
以上是关于在 HTML 中进行拆分窗格的最佳方法 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章