it-swarm.com.de

Ändern Sie die Größe von Spalten im CSS-Rasterlayout mit der Maus dynamisch

Ich versuche, die Größe von CSS-Raster-Layoutfeldern dynamisch zu ändern, indem Sie die Spaltenteiler (oder Platzhalter ändern) mit der Maus ziehen.

Ich setze resize: horizontal; auf das nav-Element, um die Größe zu ändern. Die Größe wird geändert, wenn ich den kleinen Ziehpunkt in der rechten unteren Ecke des Elements ziehe. Die Breite der benachbarten Spalte wird jedoch nicht automatisch angepasst, was zu einer Überlappung führt. Hier ist ein defekter codepen .

HTML:

<main>
 <nav>#1</nav>
 <header>#2</header>
 <section>#3</section>
</main>

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

Ich habe erwartet, dass die CSS-Engine diesen Fall automatisch verarbeitet, aber anscheinend nicht.

Ich experimentierte mit jquery-ui resizable , aber es scheint nicht gut mit Css-Grids zu funktionieren.

Ich untersuche, wie es mit Jquery geht, indem ich das Grid-Attribut grid-template-columns/rows: auf einen dynamischen Wert setze, aber es ist nicht klar, wie die Ereignisse abgefangen werden sollen, indem das Element über die Größenänderungskennung geändert wird. Das Ereignis jquery resize wird nur für das Objekt window und nicht für dom-Elemente ausgelöst.

Wie können Sie dies tun, ohne Mausereignisse wie Dragstart/Dragend behandeln zu müssen?

5
ccpizza

Was Sie erreichen möchten, ist nur mit CSS möglich. Ich habe dein Beispiel geändert. Die wichtigsten Imbisse sind dies:

  1. Am wichtigsten ist, versuchen Sie, keinen Rohinhalt in Ihre semantischen Layout-Tags einzufügen. Verwenden Sie Header-, Absatz- und Listen-Tags anstelle von Text- und BR-Tags. Dies macht Ihren Code sowohl lesbarer als auch einfacher zu verstehen. Viele Ihrer Probleme sind darauf zurückzuführen, wie der Reflow in Netzbereichen gehandhabt wird.
  2. Verwenden Sie eine Rastervorlage, um Ihr Layout zu vereinfachen, da der Rückfluss von Haltepunkten später einfacher wird.
  3. Überlauf verwenden: auto; zusammen mit der Angabe der Größenänderung: vertikal/horizontal. Ohne Einstellung des Überlaufs schlägt die Größenänderung fehl.
  4. Verwenden Sie die Werte für die minimale/maximale Breite/Höhe, um Grenzen für die Größenänderung zu erstellen.

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

2
baetheus

Die Lösung besteht darin, nicht eine explizite feste Spaltengröße (grid-template-columns: 200px 1fr;) zu verwenden, stattdessen relative Spaltengrößen wie grid-template-columns: 0.2fr 1fr; zu verwenden. Die CSS-Engine des Rasters übernimmt dann die Größenanpassung benachbarter Boxen. Als nächstes müssen Sie verschachtelte Divs in die Gitterfelder einfügen, ihre Mindesthöhe breite auf 100% setzen und sie mit/- jqueryui in ihrer Größe verändern

Die feste jsfiddle .

/* Javscript */

$('.left_inner').resizable();
$('.right_top_inner').resizable();
$('.right_bottom_inner').resizable();
/* 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;
	}
<!-- 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>

❗️ Während dies im einfachsten möglichen Fall funktioniert, wird es in einem realen Anwendungsfall problematisch. Ich habe versucht, jquery-ui layout was etwas besser funktionierte (hier ist eine demo ), aber die lib ist veraltet und stört mit Frames, deshalb entschied ich mich schließlich für angle-split-pane (basierend auf Winkel 1), die gut funktioniert und kleiner ist.

3
ccpizza