Dynamically Resize Columns in CSS Grid Layout with Mouse

Dynamically resize columns in css grid layout with mouse

What you are looking to achieve is possible using only css. I've modified your example. The main takeaways are this:

  1. Most importantly, try not to insert raw content in your semantic layout tags. Use header, paragraph, and list tags rather than text and br tags. This makes your code both easier to read and easier to reason about. Many of your problems happened because of how reflow is handled in grid areas.
  2. Use grid-template to simplify your layout as it will make breakpoint reflow easier later on.
  3. Use overflow: auto; along with specifying resize: vertical/horizontal. Without setting overflow, resize will fail.
  4. Use min/max width/height values to create boundaries for resizing.

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>

CSS grid layout dynamic resizing

after a few testing, there's a problem. the grid-template-rows definition is tricky if you set 1fr 1f 1fr the first container dictates the height of both footer elements and their height resize won't affect the grid cell size. to answer your first problem, if you set it to auto 1fr 1fr the main container will resize independently and the grid will adjust, and the first footer dictates the second footer's height. the problem begins when you want to resize the 2nd footer and it gets a little buggy because the cells need to be in the same heigh. no straight forward solution but consider moving to flex-box or set all rows to auto.

CSS Grid resizable cell

You can't change nav width and expect that it only affect the element next to it - it affect the whole first column. You can try resizing the nav in the demo below (using grid-template-columns: auto 1fr 200px) along with sufficient min-width and max-width:

.App {  display: grid;  grid-template-columns: auto 1fr 200px; /* changed */  grid-template-rows: 50px 1fr 200px 30px;}
.App > div { border: 2px solid black;}
.nav { background: green; width: 100px; /* default width */ max-width: calc(100vw - 260px); /* do go beyond the third column */ min-width: 25px; /* min width of nav */ resize: horizontal; /* resize the div */ overflow: hidden; /* resize works if overflow not visible */}
<div class="App"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div class="nav">7</div><div>8</div><div>9</div><div>10</div><div>11</div><div>12</div></div>

grid layout with resize horizontal not resizing columns

minmax(100px, 200px) is as good as 200px if you want shrinking behavior change to minmax(100px, 1fr)

If you want the grid to responsed to the content rather than the available width of it's own parent change to display: inline-grid;

html,
body,
.main {
height: 100%;
margin: 0;
}

.main {
display:inline-grid;
grid-template-columns: minmax(100px, 1fr) 1fr;
grid-template-rows: 50px 1fr;
gap: 2px 2px;
grid-auto-flow: row;
grid-template-areas: "header-box header-box" "left-box main-box";
}

.header-box {
background-color: lightblue;
grid-area: header-box;
overflow: hidden;
}

.left-box {
background-color: lightgreen;
grid-area: left-box;
resize: horizontal;
overflow: auto;
}

.main-box {
background-color: lightpink;
grid-area: main-box;
overflow: auto;
}
<div class="main">
<div class="header-box">header box</div>
<div class="left-box">left box</div>
<div class="main-box">main box</div>
</div>

How can I make this CSS Grid-based Holy Grail layout with resizable header, footer, and sidebars?

You can use auto in the template and you will be able to provide a fixed width/height to the elements

.grid {
display: grid;
grid-template-columns: auto 1fr auto;
grid-template-rows: repeat(3, auto);
grid-gap: 1em;
}

header, footer {
overflow: auto;
resize: vertical
}

aside {
overflow: auto;
resize: horizontal;
width:100px;
}

header,aside,article,footer {
background: #eaeaea;
padding: 1em;
height:100px;
}

header, footer {
grid-column: 1 / -1;
}

/* Demo Specific Styles */
body {
margin: 0 auto;
max-width: 56em;
padding: 1em 0;
}

.grid > * {
display: flex;
align-items: center;
justify-content: center;
}
<div class="grid">
<header>
Header
</header>

<aside class="sidebar-left">
Left Sidebar
</aside>

<article>
Article
</article>

<aside class="sidebar-right">
Right Sidebar
</aside>

<footer>
Footer
</footer>
</div>

How to tell if column resize is done manually vs. automatically with onColumnResized()?

The ColumnEvent, from which the ColumnResizedEvent is derived has a "source" property that reads "sizeColumnsToFit" or "uiColumnDragged" and even "autosizeColumns" when a you double click the partition.

https://www.ag-grid.com/javascript-grid-events/#properties-and-hierarchy

You should be able to use the source to determine how the event was fired.

myEventHandler(ev: ColumnResizedEvent) {
if (ev.source === 'sizeColumnsToFit') {
do.this;
} else {
do.that;
}
}

resizable grid column with image next and prev

Here,

$('#prev').click(function(){  
$("#resizable").css({"width": $("#resizable").width()-10});
});
$('#next').click(function(){
$("#resizable").css({"width": $("#resizable").width()+10});
});

JSFIDDLE DEMO



Related Topics



Leave a reply



Submit