0

I am working on a dynamic image grid, and I cannot get the grid to stay in a container. The idea is rather simple, add as many boxes to the container as I like, using jQuery, and as they are added, shrink them to fit the container without adding scroll bars, or running off the screen. This is working with adding columns but when adding rows it just keep running off the bottom of the screen.

How do I fix the container div so as rows are added, the image shrinks instead of adding rows with scrollbars?

function GenerateGrid(rows, cols) {

  // Get the available space of the container.
  var gridContainerH = $('#container').height();
  var gridContainerW = $('#container').width();

  // Adjust the image size to fit in the available space.
  var imageWidth = gridContainerW / cols;
  var imageHeight = gridContainerH / rows;

  const container = document.getElementById("container");
  var img = document.createElement("img");
  img.src = "panel.jpg";

  container.style.setProperty('--grid-rows', rows);
  container.style.setProperty('--grid-cols', cols);
  for (i = 0; i < (rows * cols); i++) {
    let cell = document.createElement("div");
    cell.innerHTML = '<img src=box.jpg width=' + imageWidth + ' height=' + imageHeight + '>';
    container.appendChild(cell).className = "grid-item";
  };

  // Recalculate height
  var panelHeight = imageWidth * rows;
  $('#container').height(panelHeight);
  $('#gridContainer').height(panelHeight);

};

// Start with a 5x7 grid
$(window).on("load", function() {
  GenerateGrid(5, 7);
})

// If the column amount changes, rebuild the grid.
$('#columns').change(function() {
  var columns = $("#columns").val();
  var rows = $("#rows").val();
  $('#container').empty();
  GenerateGrid(rows, columns);
});

// If the row amount changes, rebuild the grid.
$('#rows').change(function() {
  var columns = $("#columns").val();
  var rows = $("#rows").val();
  $('#container').empty();
  GenerateGrid(rows, columns);
});
:root {
  --grid-cols: 1;
  --grid-rows: 1;
}

#container {
  display: grid;
  grid-gap: 0em;
  grid-template-rows: repeat(var(--grid-rows), 0fr);
  grid-template-columns: repeat(var(--grid-cols), 0fr);
}

#gridContainer {
  width: 768px;
  height: 600px;
  max-height: 600px;
}

#staticContainer {
  width: 768px;
  height: 600px;
  max-height: 600px;
}

.grid-item {
  padding: 0em;
  text-align: center;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container-fluid">
  <div class="row">
    <div class="col-lg-2">
      <form>
        <label for="columns">Columns</label>
        <input type="number" id="columns" name="columns" value="7">
        <label for="rows">Rows</label>
        <input type="number" id="rows" name="rows" value="5">
      </form>

    </div>
    <div class="col-lg-10">

      <div class="container" id="gridContainer">
        <div class="row">
          <div class="col-lg-8  text-center">
            Horizontal label
          </div>
        </div>
        <div class="row h-100">
          <div class="col-lg-1 my-auto">
            Vertical label
          </div>
          <div class="col-lg-7 staticContainer">
            <div id="container"></div>
          </div>
          <div class="col-lg-4 mt-auto">
            Right Side
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

What is involved with creating a Div container for the grid that will not grow beyond defined width and height?

Edit: Please see the images as an example.

5x7 grid 9x10 1x1

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Mike
  • 57
  • 9

1 Answers1

1

to avoid a link in a comment : . is this what you try to do ? :

(structure modified + bs4 class added )

function GenerateGrid(rows, cols) {

  // Get the available space of the container.
  var gridContainerH = $('#container').height();
  var gridContainerW = $('#container').width();

  // Adjust the image size to fit in the available space.
  var imageWidth = gridContainerW / cols;
  var imageHeight = gridContainerH / rows;

  const container = document.getElementById("container");
  var img = document.createElement("img");
  img.src = "panel.jpg";

  container.style.setProperty('--grid-rows', rows);
  container.style.setProperty('--grid-cols', cols);
  for (i = 0; i < (rows * cols); i++) {
    let cell = document.createElement("div");
    cell.innerHTML = '<img src=box.jpg width=' + imageWidth + ' height=' + imageHeight + '>';
    container.appendChild(cell).className = "grid-item";
  };

  // Recalculate height
  var panelHeight = imageWidth * rows;
  $('#container').height(panelHeight);
  $('#gridContainer').height(panelHeight);

};

// Start with a 5x7 grid
$(window).on("load", function() {
  GenerateGrid(5, 7);
})

// If the column amount changes, rebuild the grid.
$('#columns').change(function() {
  var columns = $("#columns").val();
  var rows = $("#rows").val();
  $('#container').empty();
  GenerateGrid(rows, columns);
});

// If the row amount changes, rebuild the grid.
$('#rows').change(function() {
  var columns = $("#columns").val();
  var rows = $("#rows").val();
  $('#container').empty();
  GenerateGrid(rows, columns);
});
:root {
  --grid-cols: 1;
  --grid-rows: 1;
}

#container {
  flex:1;
  display: grid;
  grid-gap: 0em;
  grid-template-rows: repeat(var(--grid-rows), 0fr);
  grid-template-columns: repeat(var(--grid-cols), 0fr);
}


#staticContainer {/* width sizing ? while col-lg-7 ? 
Added to parent  flex-shrink-0 flex-wrap classes but unsure of what you really want */ 
  width: 768px;
  height: 600px;
  text-align:center;
}

.grid-item {
  padding: 0em;
  text-align: center;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container-fluid">
  <div class="row">
    <div class="col-lg-2">
      <form>
        <label for="columns">Columns</label>
        <input type="number" id="columns" name="columns" value="7">
        <label for="rows">Rows</label>
        <input type="number" id="rows" name="rows" value="5">
      </form>

    </div>
    <div   class="col-lg-10 d-flex align-items-center flex-shrink-0 flex-wrap">
      <div class="col-lg-1">Vertical label</div>

      <div class="col-lg-7 d-flex flex-column" id="staticContainer">
        <div>Horizontal label</div>
        <div id="container"></div>
      </div>
      <div class="col-lg-4">
        Right Side
      </div>
    </div>
  </div>
</div>

using classes with a break point and fixed size else where makes the expected render really confusing ... Could you clarify expected size and behavior ?


would object-fit be a hint too ?

function GenerateGrid(rows, cols) {

  // Get the available space of the container.
  var gridContainerH = $('#container').height();
  var gridContainerW = $('#container').width();

  // Adjust the image size to fit in the available space.
  var imageWidth = gridContainerW / cols;
  var imageHeight = gridContainerH / rows;

  const container = document.getElementById("container");
  var img = document.createElement("img");
  img.src = "http://dummyimage.com/100x200&text=panel.jpg";

  container.style.setProperty('--grid-rows', rows);
  container.style.setProperty('--grid-cols', cols);
  for (i = 0; i < (rows * cols); i++) {
    let cell = document.createElement("div");
    cell.innerHTML = '<img src="http://dummyimage.com/100x200&text=box.jpg" width=' + imageWidth + ' height=' + imageHeight + '>';
    container.appendChild(cell).className = "grid-item";
  };

  // Recalculate height
  var panelHeight = imageWidth * rows;
  $('#container').height(panelHeight);
  $('#gridContainer').height(panelHeight);

};

// Start with a 5x7 grid
$(window).on("load", function() {
  GenerateGrid(5, 7);
})

// If the column amount changes, rebuild the grid.
$('#columns').change(function() {
  var columns = $("#columns").val();
  var rows = $("#rows").val();
  $('#container').empty();
  GenerateGrid(rows, columns);
});

// If the row amount changes, rebuild the grid.
$('#rows').change(function() {
  var columns = $("#columns").val();
  var rows = $("#rows").val();
  $('#container').empty();
  GenerateGrid(rows, columns);
});
:root {
  --grid-cols: 1;
  --grid-rows: 1;
}

#container {
  flex:1;
  display: grid;
  grid-gap: 0em;
  grid-template-rows: repeat(var(--grid-rows), 0fr);
  grid-template-columns: repeat(var(--grid-cols), 0fr);
}


#staticContainer {/* width sizing ? while col-lg-7 ? 
Added to parent  flex-shrink-0 flex-wrap classes but unsure of what you really want */ 
  width: 768px;
  height: 600px;
  text-align:center;
}

.grid-item {
  padding: 0em;
  text-align: center;
}
.grid-item img {object-fit:cover;display:block}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container-fluid">
  <div class="row">
    <div class="col-lg-2">
      <form>
        <label for="columns">Columns</label>
        <input type="number" id="columns" name="columns" value="7">
        <label for="rows">Rows</label>
        <input type="number" id="rows" name="rows" value="5">
      </form>

    </div>
    <div   class="col-lg-10 d-flex align-items-center flex-shrink-0 flex-wrap">
      <div class="col-lg-1">Vertical label</div>

      <div class="col-lg-7 d-flex flex-column" id="staticContainer">
        <div>Horizontal label</div>
        <div id="container"></div>
      </div>
      <div class="col-lg-4">
        Right Side
      </div>
    </div>
  </div>
</div>
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
  • The expected render would be as rows are added, the width would shrink so the aspect remains the same. As columns are added the row may height may need to shrink to maintain the proper aspect. The above is almost perfect, but selecting 4 columns by 9 rows for example, stretches the image now, but does maintain the container, For example, given the div of 768 x 600, and an image of 100x100, the first image placed on a 1x1 grid should be a 100x100 image. As more images are added, the image should shrink both vertical and horizontal to maintain aspect, and still fit in the 768 x 600 div. – Mike Aug 26 '20 at 17:30
  • 1
    @Mike i added a snippet with object-fit, image won't shrink nor be clipped with the value : contains . see options here : https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit – G-Cyrillus Aug 26 '20 at 18:18
  • Thanks. How do I remove the white space when the aspect if not linear? For example, 5x5 is perfect, but 6x5 adds white space because the container is fixed. Can the container shrink to reduct the whitespace, but still not exceed the static container? I have tried to change the size of the container using jQuery $('#staticContainer').width(newHeight); but it did not work. – Mike Aug 28 '20 at 15:42
  • 1
    Reset display to block for img. It should remove that white space i believe. @Mike unless you did not use`cover` but `contain`;) – G-Cyrillus Aug 28 '20 at 15:58
  • 1
    Thank you. It worked. Thanks for saving me time working on a path that was not correct. – Mike Aug 28 '20 at 16:03