使用鼠标动态调整css网格布局中的列

ccp*_*zza 15 javascript css jquery resize css-grid

我试图通过使用鼠标拖动列分隔符(或调整占位符大小)来动态调整css网格布局框的大小.

resize: horizontal;nav元素上设置了调整大小,当我在元素的右下角拖动小调整大小手柄时它会被调整大小,但相邻列的宽度不会自动调整而导致重叠.这是一个破碎的codepen.

HTML:

<main>
 <nav>#1</nav>
 <header>#2</header>
 <section>#3</section>
</main>
Run Code Online (Sandbox Code Playgroud)

CSS:

main {
    display: grid;
    border: 3px dotted red;
    grid-gap: 3px;
    grid-template-columns: 200px 1fr;
    grid-template-rows: 100px 1fr;
    height: 100%;
}

nav {
    grid-column: 1;
    grid-row: 1;
    grid-row: 1 / span 2;
    resize: horizontal;
    overflow: scroll;
    border: 3px dotted blue;
}
Run Code Online (Sandbox Code Playgroud)

我希望css网格引擎自动处理这种情况,但显然它没有.

我尝试使用jquery-ui可调整大小,但它似乎不适用于css网格.

我正在研究如何通过将grid属性grid-template-columns/rows:设置为动态值来使用jquery来完成它,但是不清楚如何通过resize句柄调整元素大小来捕获抛出的事件.jquery resize事件仅在window对象上触发,而不是在dom元素上触发.

在不必处理像dragstart/dragend这样的低级鼠标事件的情况下,可能有什么办法呢?

ccp*_*zza 9

解决方案是使用显式固定列大小 ( grid-template-columns: 200px 1fr;) 而是使用相对列大小,例如grid-template-columns: 0.2fr 1fr;- 然后网格 CSS 引擎将处理相邻框的大小调整。接下来是在网格框内添加嵌套的 div,将它们的最小高度/宽度设置为 100% 并通过jqueryui resizable使它们可调整大小

固定的jsfiddle

/* Javscript */

$('.left_inner').resizable();
$('.right_top_inner').resizable();
$('.right_bottom_inner').resizable();
Run Code Online (Sandbox Code Playgroud)
/* CSS */

	.grid {
		display: grid;
		grid-template-columns: 0.2fr 1fr;
		grid-template-rows: 1fr 4fr;
        grid-gap: 3px;
		position: relative;
	}

	.left {
		grid-row: 1 / span 2;
	}

	.right_top {
		grid-column: 2;
		grid-row: 1;
	}

	.right_bottom {
		grid-column: 2;
		grid-row: 2;
	}

	.left_inner {
		background-color: #fedcd2;
		padding: 0;
		width: 100%;
		min-width: 100%;
		height: 100%;
		min-height: 100%;
		text-align: center;
	}

	.right_top_inner {
		background-color: #f9cf00;
		padding: 0;
		width: 100%;
		min-width: 100%;
		height: 100%;
		min-height: 100%;
		text-align: center;
	}

	.right_bottom_inner {
		background-color: #f8eee7;
		padding: 0;
		width: 100%;
		min-width: 100%;
		height: 100%;
		min-height: 100%;
		text-align: center;
	}
Run Code Online (Sandbox Code Playgroud)
<!-- HTML -->

<script src="//code.jquery.com/jquery-2.1.3.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.0/css/smoothness/jquery-ui-1.10.0.custom.min.css" />
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.0/jquery-ui.js"></script>

	<main class="grid">
	 <aside class='left'>
	  <div class="left_inner">
		drag the bottom right handle to resize
	  </div>
	 </aside>
	 <section class="right_top">
	  <div class="right_top_inner">right_top_inner</div>
	 </section>
	 <section class="right_bottom">
	  <div class="right_bottom_inner">right_bottom_inner</div>
	 </section>
	</main>
Run Code Online (Sandbox Code Playgroud)

?? 虽然这适用于最简单的场景,但在现实生活用例中会出现问题。我尝试了jquery-ui 布局,它工作得更好(这里是一个演示),但是库已经过时并且框架有问题,所以我使用了angular-split-pane(基于 angular 1),它工作正常,并且在尺寸。(更新:该项目目前似乎已被放弃,因此可能不是最佳选择)


小智 9

您希望使用CSS来实现的目标。我已经修改了您的示例。主要要点是:

  1. 最重要的是,请尽量不要在语义布局标签中插入原始内容。使用标头,段落和列表标签,而不是text和br标签。这使您的代码更易于阅读和推理。由于网格区域中如何处理回流,您发生了许多问题。
  2. 使用网格模板可以简化布局,因为这将使以后的断点重排更加容易。
  3. 使用溢出:自动;以及指定调整大小:垂直/水平。如果不设置溢出,则调整大小将失败。
  4. 使用最小/最大宽度/高度值创建边界以调整大小。

body {
    margin: 10px;
    height: 100%;
}

main {
    display: grid;
    border: 3px dotted red;
    padding: 3px;
    grid-gap: 3px;
    
    grid-template: 
    "nav head" min-content
    "nav main" 1fr
        / min-content 1fr;
}

nav {
    grid-area: nav;
    border: 3px dotted blue;
    overflow: auto;
    resize: horizontal;
    
    min-width: 120px;
    max-width: 50vw;
}

header {
    grid-area: head;
    border: 3px dotted orange;
    overflow: auto;
    resize: vertical;
    
    min-height: min-content;
    max-height: 200px;
}

section {
    grid-area: main;
    border: 3px dotted gray;
}
Run Code Online (Sandbox Code Playgroud)
<main>
  <nav>
    <ul>
      <li>Nav Item</li>
      <li>Nav Item</li>
      <li>Nav Item</li>
      <li>Nav Item</li>
      <li>Nav Item</li>
      <li>Nav Item</li>
    </ul>
  </nav>

  <header>
    <h1>Header Title</h1>
    <small>Header Subtitle</small>
  </header>

  <section>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  </section>
</main>
Run Code Online (Sandbox Code Playgroud)

  • 现在是 2022 年,CS​​S 不提供像这样的边框调整大小语法:“border-left: 2pxsolid #ccc ressized”,但我们可以在 3D 空间中旋转元素,甚至改变视角。这就是网络上的事物有多么神奇。 (3认同)
  • 是否可以拖动整个边框,而不是仅拖动右下角? (2认同)
  • @AlanTygel 由于这个答案是纯 CSS,因此令人沮丧的是,您为拖动边框问题找到的解决方案涉及 jQuery。我仍在寻找正确的方法来执行此操作(网格布局+完整边框调整大小处理程序),并且最少或没有额外的标记,并且如果可能的话没有依赖性...... (2认同)
  • @ErkkaMutanen 行 `"nav main" 1fr` 将包含主元素的行设置为 `1fr` 高(即使用剩余高度)。‘/min-content 1fr’行设置两个元素的宽度(即,‘nav’元素宽度设置为‘min-content’,‘head’和‘main’宽度设置为‘1fr’。 (2认同)