在 HTML 中实现拆分窗格的最佳方法

有没有一个好的技术,使一个可调整大小的分割窗格在 HTML?

是否可以使用 CSS/jQuery/JavaScript 来完成,或者是否有一个很好的 JavaScript 库已经被使用?

(分割窗格的一个例子是 Internet Explorer中的收藏栏,它可能停靠在主浏览器窗口的左侧。)

163435 次浏览

可以使用绝对定位。这个 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;
}

(在 jsfiddle.net 上演示)

在过去,您可以使用框架来实现这一点。有几个原因可以解释为什么这种方法不那么好。看看里斯对 为什么 HTML 框架不好的反应。参见 Jakob Nielson 的 为什么框架很烂(大多数时候)

一种较新的方法是使用内联帧。这也有优点和缺点: Iframes 是否被认为是不良实践

更好的方法是使用 固定定位。通过将导航内容(例如示例中的收藏链接)放在块元素(如 div)中,然后将 position:fixed应用于该元素,并像下面这样设置左、上和底部属性:

#myNav {
position: fixed;
left: 0px;
top: 0px;
bottom: 0px;
width: 200px;
}

... 你会在页面左边形成一个垂直的列,当用户滚动页面时它不会移动。

页面上的其他内容不会“感觉”到这个导航元素的存在,因此它必须考虑到它所占用的200px 的空间。可以通过将内容的其余部分放置在另一个 div 中并设置 margin-left:200px;来实现这一点。

我找到了一个可以工作的分离器 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;
}

我想要一个普通的、轻量级的(JQuery 用户界面布局重量为185 KB) ,没有依赖性选项(所有现有的库都需要 jQuery) ,所以我编写了 分开

它的权重小于2KB,不需要任何特殊标记。它支持旧的浏览器回到 Internet Explorer 9(或填充 Internet Explorer 8)。对于现代浏览器,您可以将其与 Flexbox网格布局一起使用。

一个完全不同的方法是把东西放在一个网格中,比如 ui-grid 或 Kendo 的网格,并让列可以调整大小。缺点是用户无法调整行的大小,尽管可以通过编程方式设置行的大小。

一个很好的库是神盾用户界面-你可以看看他们灵活的 分离器小部件和其他强大的组件框架提供。

下面是我的轻量级 JavaScript 方法,使用 Flexbox:

Http://codepen.io/lingtalfi/pen/zonejp

它在谷歌 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 代码依赖于 简单的拖拽普通的 JavaScript 轻量级库(少于60行代码)。

您可以在不使用其他 JavaScript 库的情况下使用 jQueryUI 完成此操作。只需在 .resizable调整事件中添加一个函数,就可以调整其他 div 的宽度。

$("#left_pane").resizable({
handles: 'e', // 'East' side of div draggable
resize: function() {
$("#right_pane").outerWidth( $("#container").innerWidth() - $("#left_pane").outerWidth() );
}
});

这是完整的 JSFiddle

我在 CSS3中看到了这个属性。 这个可能更好用。

CSS 调整大小属性

我为它编写了没有任何第三方库的简单代码。此代码仅用于水平拆分器(垂直拆分器也是如此)。

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>

最简单的 HTML + CSS 手风琴,只有 CSS 调整大小

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>
<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>


最简单的 HTML 全屏模式弹出窗口

.popup > p {
padding: 1rem;
margin: 0;
display: flex;
flex-direction: column;
width: 25vw
}
.popup summary {
padding: 1rem 0.5rem;
cursor: pointer;
max-height: 90vh;
overflow: auto
}
.popup[open] summary {
background: black;
color: white;
padding: 0.5rem;
}


.popup[open] {
position: fixed;
/* top: calc(50% - 25vw); */
left: calc(50% - 15vw);
outline: 5000px #00000090 solid;
border: 5px red solid;
border-radius: 0.5rem;
z-index: 1;
max-height: 90vh;
overflow-y: auto;
overflow-x: hidden
}


.popup[open] summary::after {
content: '❌';
float: right;
}
<details class="popup">
<summary>HTML popup</summary>
<p>
<span>Name</span>
<input value="HTML" />
<br>
<span>Difficulty</span>
<input type="number" value="3" />
<br>
<span>Coolness</span>
<input type="number" value="100" />
<br>
<p><span>Powered by HTML</span></p>
</p>
</details>


使用 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">&nbsp;</div>
<div id="pan2">BODY</div>
</div>

改进 雷扎的回答:

  • 防止浏览器干扰拖动
  • 防止将元素设置为负大小
  • 防止由于增量增量 δ 与元素宽度饱和的相互作用而使拖动与鼠标失去同步

<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>

无第三方库的 Angular 版本(基于 个人云计算的答案) :

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>

在 Stackblitz 上运行示例

许多人错过了这个职位从 巴格斯特在2月27’15日,其中显示了一个有趣的通用柔性盒垂直和水平调整器。

看一下: 柔性盒调整尺寸

Barguast 指出,“ ... ... 它只处理伸缩增长(flex-growth)尺寸的产品。如果定义了弹性收缩或弹性基础,那么计算根本就不起作用。”,他正在寻找一个更好的解决方案,我也是。

以下是他的代码作为参考:

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 上看到:

Edit sad-butterfly-1fwo4