求推荐有上下左右的布局,
我查看antv的layout,只有上下左、上下右的布局,请问是否有上下左右的布局推荐呢?
想要的效果:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>纯Tailwind CSS文件浏览器与设计区布局</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/js/all.min.js"></script>
</head>
<body class="flex flex-col h-screen overflow-hidden bg-gray-50">
<!-- 顶部区域 -->
<div class="bg-white border-b border-gray-200 shadow-sm">
<!-- 菜单栏 -->
<div class="flex items-center px-4 h-10 border-b border-gray-200 text-sm">
<div class="flex space-x-4">
<div class="font-medium hover:bg-gray-100 px-2 py-1 rounded cursor-pointer">文件</div>
<div class="font-medium hover:bg-gray-100 px-2 py-1 rounded cursor-pointer">编辑</div>
<div class="font-medium hover:bg-gray-100 px-2 py-1 rounded cursor-pointer">视图</div>
<div class="font-medium hover:bg-gray-100 px-2 py-1 rounded cursor-pointer">工具</div>
<div class="font-medium hover:bg-gray-100 px-2 py-1 rounded cursor-pointer">帮助</div>
</div>
</div>
<!-- 工具栏 -->
<div class="flex items-center px-4 h-12 border-b border-gray-200">
<div class="flex space-x-2">
<button class="p-1.5 rounded hover:bg-gray-100" title="新建文件">
<i class="fas fa-file text-blue-600"></i>
</button>
<button class="p-1.5 rounded hover:bg-gray-100" title="保存">
<i class="fas fa-save text-blue-600"></i>
</button>
<button class="p-1.5 rounded hover:bg-gray-100" title="撤销">
<i class="fas fa-undo text-blue-600"></i>
</button>
<button class="p-1.5 rounded hover:bg-gray-100" title="重做">
<i class="fas fa-redo text-blue-600"></i>
</button>
<div class="border-r border-gray-300 h-6 mx-1"></div>
<button class="p-1.5 rounded hover:bg-gray-100" title="预览">
<i class="fas fa-eye text-blue-600"></i>
</button>
<button class="p-1.5 rounded hover:bg-gray-100" title="发布">
<i class="fas fa-upload text-blue-600"></i>
</button>
</div>
</div>
</div>
<!-- 中间内容区域 -->
<div class="flex flex-1 overflow-hidden">
<!-- 左侧文件列表区 -->
<div id="leftPanel" class="w-64 bg-white border-r border-gray-200 flex flex-col shadow-sm overflow-hidden relative">
<div id="leftResizer" class="absolute right-0 top-0 h-full w-1 bg-transparent hover:bg-blue-300 cursor-col-resize"></div>
<div class="flex items-center justify-between p-2 border-b border-gray-200">
<h2 class="font-medium text-gray-700">资源管理器</h2>
<div class="flex">
<button class="p-1 rounded hover:bg-gray-100" title="新建文件夹">
<i class="fas fa-folder-plus text-gray-600 text-sm"></i>
</button>
<button class="p-1 rounded hover:bg-gray-100" title="刷新">
<i class="fas fa-sync text-gray-600 text-sm"></i>
</button>
<button class="p-1 rounded hover:bg-gray-100" title="折叠所有">
<i class="fas fa-compress-alt text-gray-600 text-sm"></i>
</button>
</div>
</div>
<!-- 搜索框 -->
<div class="p-2 border-b border-gray-200">
<div class="relative">
<input type="text" class="w-full p-1.5 pl-7 rounded border border-gray-300 bg-white text-sm focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500" placeholder="搜索文件...">
<i class="fas fa-search text-gray-400 absolute left-2.5 top-2.5 text-sm"></i>
</div>
</div>
<!-- 文件树结构 -->
<div class="overflow-y-auto flex-1">
<div class="p-1.5 text-sm">
<div class="flex items-center py-1 px-2 hover:bg-blue-50 rounded cursor-pointer">
<i class="fas fa-chevron-down text-gray-500 text-xs mr-1.5"></i>
<i class="fas fa-folder text-yellow-500 mr-1.5"></i>
<span>aaa</span>
</div>
<div class="pl-5">
<div class="flex items-center py-1 px-2 bg-blue-50 rounded cursor-pointer">
<i class="fas fa-chevron-down text-gray-500 text-xs mr-1.5"></i>
<i class="fas fa-folder-open text-yellow-500 mr-1.5"></i>
<span>bbb</span>
</div>
<div class="pl-5">
<div class="flex items-center py-1 px-2 hover:bg-blue-50 rounded cursor-pointer">
<i class="fas fa-file-code text-blue-500 mr-1.5"></i>
<span>bbb.ts</span>
</div>
<div class="flex items-center py-1 px-2 bg-blue-50 rounded cursor-pointer">
<i class="fas fa-file-alt text-blue-500 mr-1.5"></i>
<span>bbb.test.ts</span>
</div>
<div class="flex items-center py-1 px-2 hover:bg-blue-50 rounded cursor-pointer">
<i class="fas fa-file-code text-blue-500 mr-1.5"></i>
<span>bbb.flow.json</span>
</div>
</div>
</div>
<div class="flex items-center py-1 px-2 hover:bg-blue-50 rounded cursor-pointer">
<i class="fas fa-chevron-right text-gray-500 text-xs mr-1.5"></i>
<i class="fas fa-folder text-yellow-500 mr-1.5"></i>
<span>ccc</span>
</div>
<div class="flex items-center py-1 px-2 hover:bg-blue-50 rounded cursor-pointer">
<i class="fas fa-chevron-right text-gray-500 text-xs mr-1.5"></i>
<i class="fas fa-folder text-yellow-500 mr-1.5"></i>
<span>ddd</span>
</div>
</div>
</div>
</div>
<!-- 中间设计区 -->
<div class="flex-1 flex flex-col bg-white border-r border-gray-200 overflow-hidden">
<!-- 选项卡 -->
<div class="flex h-9 bg-gray-50 border-b border-gray-200 overflow-x-auto whitespace-nowrap">
<div class="flex items-center px-3 bg-white border-r border-gray-200 text-sm">
<i class="fas fa-file-code text-blue-500 mr-2 text-xs"></i>
<span class="truncate">bbb.test.ts</span>
<button class="ml-2 p-1 rounded-full hover:bg-gray-200 focus:outline-none">
<i class="fas fa-times text-gray-500 text-xs"></i>
</button>
</div>
<div class="flex items-center px-3 bg-gray-50 border-r border-gray-200 text-sm">
<i class="fas fa-file-code text-blue-500 mr-2 text-xs"></i>
<span class="truncate">bbb.flow.json</span>
<button class="ml-2 p-1 rounded-full hover:bg-gray-200 focus:outline-none">
<i class="fas fa-times text-gray-500 text-xs"></i>
</button>
</div>
</div>
<!-- 工作区域 -->
<div class="flex-1 p-4 overflow-auto bg-white bg-opacity-75 bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImdyaWQiIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTSAwIDEgTCAyMCAxIE0gMSAwIEwgMSAyMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2JhKDIyMCwgMjIwLCAyMjAsIDAuNSkiIHN0cm9rZS13aWR0aD0iMSIvPjwvcGF0dGVybj48L2RlZnM+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmlkKSIvPjwvc3ZnPg==')]">
<!-- 示例设计元素 -->
<div class="bg-white border border-gray-300 rounded shadow-sm p-3 mb-4 w-64 cursor-move">
<div class="font-medium mb-2">组件A</div>
<div class="bg-blue-50 border border-blue-200 rounded p-2 text-sm">
<p>单击编辑此组件内容</p>
</div>
</div>
<div class="bg-white border border-gray-300 rounded shadow-sm p-3 ml-20 w-72 cursor-move">
<div class="font-medium mb-2">组件B</div>
<div class="bg-green-50 border border-green-200 rounded p-2 text-sm">
<p>在这里添加你的设计内容</p>
</div>
</div>
</div>
</div>
<!-- 右侧属性/预览区 -->
<div id="rightPanel" class="w-72 bg-white border-r border-gray-200 flex flex-col shadow-sm overflow-hidden relative">
<div id="rightResizer" class="absolute left-0 top-0 h-full w-1 bg-transparent hover:bg-blue-300 cursor-col-resize"></div>
<div class="flex items-center justify-between p-2 border-b border-gray-200">
<h2 class="font-medium text-gray-700">属性面板</h2>
<button class="p-1 rounded hover:bg-gray-100" title="关闭">
<i class="fas fa-times text-gray-600 text-sm"></i>
</button>
</div>
<!-- 属性内容 -->
<div class="overflow-y-auto flex-1 p-3">
<div class="mb-4">
<div class="flex items-center mb-2">
<i class="fas fa-cog text-gray-500 mr-2"></i>
<span class="font-medium text-gray-700">常规</span>
</div>
<div class="pl-6 space-y-2">
<div class="flex justify-between">
<span class="font-medium text-gray-600">名称</span>
<span class="text-blue-800">组件B</span>
</div>
<div class="flex justify-between">
<span class="font-medium text-gray-600">类型</span>
<span class="text-blue-800">Container</span>
</div>
<div class="flex justify-between">
<span class="font-medium text-gray-600">可见性</span>
<div>
<label class="inline-flex items-center">
<input type="checkbox" class="rounded text-blue-600 focus:ring-blue-500" checked>
</label>
</div>
</div>
</div>
</div>
<div class="mb-4">
<div class="flex items-center mb-2">
<i class="fas fa-palette text-gray-500 mr-2"></i>
<span class="font-medium text-gray-700">样式</span>
</div>
<div class="pl-6 space-y-2">
<div>
<span class="font-medium text-gray-600 block mb-1">背景色</span>
<div class="flex items-center">
<div class="w-6 h-6 bg-green-50 border border-gray-300 rounded mr-2"></div>
<span class="text-sm">#f0fdf4</span>
</div>
</div>
<div>
<span class="font-medium text-gray-600 block mb-1">边框</span>
<select class="block w-full text-sm border border-gray-300 rounded p-1.5">
<option>细线</option>
<option>虚线</option>
<option>无</option>
</select>
</div>
<div>
<span class="font-medium text-gray-600 block mb-1">圆角</span>
<input type="range" class="w-full" min="0" max="20" value="4">
</div>
</div>
</div>
<div>
<div class="flex items-center mb-2">
<i class="fas fa-code text-gray-500 mr-2"></i>
<span class="font-medium text-gray-700">事件</span>
</div>
<div class="pl-6">
<select class="block w-full text-sm border border-gray-300 rounded p-1.5 mb-2">
<option>点击事件</option>
<option>悬停事件</option>
<option>拖拽事件</option>
</select>
<div class="bg-gray-50 border border-gray-200 rounded p-2 text-sm font-mono">
function onClick() {<br>
// 处理点击事件<br>
}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 底部区域 -->
<div class="h-20 bg-gray-50 border-t border-gray-200 flex flex-col">
<!-- 选项卡栏 -->
<div class="flex h-8 border-b border-gray-200 bg-gray-100">
<div class="flex items-center px-4 bg-white border-r border-gray-200 text-sm font-medium">
<span>控制台</span>
</div>
<div class="flex items-center px-4 text-sm">
<span>问题</span>
</div>
<div class="flex items-center px-4 text-sm">
<span>输出</span>
</div>
<div class="flex items-center px-4 text-sm">
<span>调试控制台</span>
</div>
</div>
<!-- 控制台内容 -->
<div class="flex-1 bg-white p-2 font-mono text-sm overflow-y-auto">
<div class="text-gray-500">> 正在编译 bbb.test.ts...</div>
<div class="text-green-600">> 编译成功,无错误。</div>
<div class="text-gray-500">> 正在执行测试...</div>
<div class="text-green-600">> 所有测试通过 (3 tests, 12 assertions)</div>
<div class="flex items-center">
<span class="text-gray-400">></span>
<div class="ml-1 w-2 h-4 bg-gray-500 animate-pulse"></div>
</div>
</div>
</div>
<!-- 简单交互脚本 -->
<script>
// 文件夹点击事件
document.querySelectorAll('.fa-folder, .fa-folder-open, .fa-chevron-down, .fa-chevron-right').forEach(icon => {
icon.parentElement.addEventListener('click', function(e) {
// 仅当点击的是图标的父元素时执行
if (e.target === this || e.target.tagName === 'I' || e.target.tagName === 'SPAN') {
const chevron = this.querySelector('.fa-chevron-down, .fa-chevron-right');
const folder = this.querySelector('.fa-folder, .fa-folder-open');
if (chevron) {
if (chevron.classList.contains('fa-chevron-down')) {
chevron.classList.remove('fa-chevron-down');
chevron.classList.add('fa-chevron-right');
} else {
chevron.classList.remove('fa-chevron-right');
chevron.classList.add('fa-chevron-down');
}
}
if (folder) {
if (folder.classList.contains('fa-folder')) {
folder.classList.remove('fa-folder');
folder.classList.add('fa-folder-open');
} else {
folder.classList.remove('fa-folder-open');
folder.classList.add('fa-folder');
}
}
// 切换下一个兄弟元素的可见性
const sibling = this.nextElementSibling;
if (sibling && sibling.classList.contains('pl-5')) {
sibling.style.display = sibling.style.display === 'none' ? '' : 'none';
}
}
});
});
// 左侧面板调整大小
document.getElementById('leftResizer').addEventListener('mousedown', function(e) {
e.preventDefault();
const leftPanel = document.getElementById('leftPanel');
const startX = e.clientX;
const startWidth = parseInt(window.getComputedStyle(leftPanel).width, 10);
function onMouseMove(e) {
const newWidth = startWidth + e.clientX - startX;
leftPanel.style.width = `${newWidth}px`;
}
function onMouseUp() {
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
// 右侧面板调整大小
document.getElementById('rightResizer').addEventListener('mousedown', function(e) {
e.preventDefault();
const rightPanel = document.getElementById('rightPanel');
const startX = e.clientX;
const startWidth = parseInt(window.getComputedStyle(rightPanel).width, 10);
function onMouseMove(e) {
const newWidth = startWidth - e.clientX + startX;
rightPanel.style.width = `${newWidth}px`;
}
function onMouseUp() {
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
</script>
</body>
</html>
更多示例可以参考 https://pageforge.devlive.org 该站点就是类似这种布局,使用纯 Tailwind CSS 实现
10 回答11.7k 阅读
2 回答3.2k 阅读✓ 已解决
2 回答4.3k 阅读✓ 已解决
3 回答1.9k 阅读✓ 已解决
2 回答1.7k 阅读✓ 已解决
4 回答2.5k 阅读✓ 已解决
5 回答3.8k 阅读
其实这种布局就是上中下的页面布局,然后中间再分成左中右三栏。
对于这样的布局,能实现的方式有很多,不过具体的方案必然是根据具体的情况来分析的。
对于现在的浏览器兼容情况来说,其实很简单,flex 分分钟搞定,再不行就用 grid 来实现。


代码就不抠了,抠代码太累了,直接发 url 吧。 https://linxz.github.io/tianyizone/free-flex.html