Skip to content

Instantly share code, notes, and snippets.

@cpq
Last active November 20, 2021 17:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cpq/f6d4db8a2dc5cd6eeae4dacedea38a4f to your computer and use it in GitHub Desktop.
Save cpq/f6d4db8a2dc5cd6eeae4dacedea38a4f to your computer and use it in GitHub Desktop.
HTML split pane layout example
<html>
<head>
<style>
* { box-sizing: border-box; }
body, html { padding: 0; margin: 0; }
.main { height: 100vh; }
.content { padding: 1em; }
.split { display: flex; flex-grow: 1; flex-shrink: 1; width: 100%; height: 100%; box-sizing: border-box; }
.split>* { flex-grow: 1; flex-shrink: 1; width: 100%; height: 100%; overflow: auto; -webkit-overflow-scrolling: touch; }
.split-horizontal { flex-direction: row; }
.split-vertical { flex-direction: column; }
.split-divider { flex: 0 0 11px; overflow: hidden; user-select: none; -webkit-user-drag: none; -webkit-tap-horizontalighlight-color: transparent; }
.split-divider-horizontal { cursor: col-resize; touch-action: pan-y; }
.split-divider-vertical { cursor: row-resize; touch-action: pan-x; }
.split-divider { background: no-repeat center center; background-color: #eee; }
.split-divider-horizontal { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg=="); }
.split-divider-vertical { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFCAMAAABl/6zIAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAABRJREFUeAFjYGRkwIMJSeMHlBkOABP7AEGzSuPKAAAAAElFTkSuQmCC"); }
</style>
</head>
<body>
<div class="main">
<div class="split split-horizontal">
<div class="split split-vertical" style="flex-basis: 10%;">
<div style="flex-basis: 50px;" class="content">a</div>
<div class="split-divider split-divider-vertical"></div>
<div style="flex-basis: 153.333px;" class="content">b</div>
<div class="split-divider split-divider-vertical"></div>
<div style="flex-basis: 159.333px;" class="content">c</div>
</div>
<div class="split-divider split-divider-horizontal"> </div>
<div class="content" style="flex-basis: 25%;"> d</div>
<div class="split-divider split-divider-horizontal"></div>
<div class="split split-vertical" style="">
<div class="content">e</div>
<div class="split-divider split-divider-vertical"></div>
<div class="content">f</div>
</div>
</div>
</div>
</body>
</html>
<html>
<head>
<style>
* { box-sizing: border-box; }
body, html { padding: 0; margin: 0; }
.split { display: flex; width: 100%; height: 100%; box-sizing: border-box; }
.split>* { flex-shrink: 1; overflow: auto; -webkit-overflow-scrolling: touch; }
.split-horizontal { flex-direction: row; }
.split-vertical { flex-direction: column; }
.split-divider { flex: 0 0 11px; overflow: hidden; user-select: none; -webkit-user-drag: none; -webkit-tap-horizontalighlight-color: transparent; background: no-repeat center center; background-color: #eee; }
.split-horizontal > .split-divider { cursor: col-resize; touch-action: pan-y; background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg=="); }
.split-vertical > .split-divider { cursor: row-resize; touch-action: pan-x; background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFCAMAAABl/6zIAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAABRJREFUeAFjYGRkwIMJSeMHlBkOABP7AEGzSuPKAAAAAElFTkSuQmCC"); }
</style>
</head>
<body></body>
<script type="module">
import { h, html, render, useEffect, useState, useRef } from 'https://npm.reversehttp.com/preact,preact/hooks,htm/preact';
const Split = props => {
return html`<div class="split split-${props.split}">
${props.children.map(vnode => {
let style = {width: vnode.props.width, height: vnode.props.height};
if (!style.width && !style.height) style.flexGrow = 1;
if (vnode.props.foo) console.log(vnode.props);
return vnode.props.class == 'split-divider' ? vnode : h('div', {style}, vnode);
})}
</div>`;
};
const A = props => html`<div>A</div>`;
const B = props => html`<div>B</div>`;
const C = props => html`<div>C</div>`;
const D = props => html`<div style="background:#eff;height:100vh;">D</div>`;
const App = props => {
const [count, setCount] = useState(0);
useEffect(function() {
document.addEventListener('click', ev => setCount(count + 1));
}, []);
return html`
<${Split} split="horizontal">
<${A} width="50%" count=${count} foo=${1} />
<div class="split-divider" />
<${B} />
<div class="split-divider" />
<${Split} split="vertical" width="20%">
<${C} />
<div class="split-divider" />
<${D} height="25%" />
<//>
<//>`;
};
render(html`<${App} />`, document.body);
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment