Size div height dynamically based on number of divs

1.9k views Asked by At

I am making a grid of square divs that begins as 16x16. However, this grid can be resized to be larger or smaller (40x40, 10x10, 60x60 etc.) by clicking the button on the page and filling in the prompt.

When a user resizes the grid, I would like the new grid to take up the same space that the original 16x16 grid takes up. I am using 'vw' to size the width of the divs, which seems to be working properly (they dynamically respond to fit the original size of the grid). However, the height of each div doesn't seem to be responding properly when I use 'vh' and the divs extend beyond the container div.

Here's the HTML:

<! DOCTYPE html>
<html>

<head>
    <script src="jquery.js" type="text/javascript"></script>
    <script src="grid.js" type="text/javascript"></script>
    <link rel="stylesheet" type="text/css" href="grid.css">
    <title>The Grid</title>
</head>

<body>

    <button type="button">Click Me!</button>

    <div class="grid">

    </div>


</body>


</html>

Here's the CSS:

body {
background: #000;
}

.square {
background-color: white;
display: table-cell;
border: 1px solid black;
width: 100vw;
height: 7.75vh;
}

.highlighted {
background-color: #0000FF;
}

Here's the JavaScript:

$(document).ready(function () {
var $grid = $('.grid');
for (var i = 0; i < 16; i++) {

    var row = '<div>';

    for (var j = 0; j < 16; j++)
        row += '<div class = "square"></div>';

    row += '</div>';

    $grid.append(row);

}


$('button').on('click', function () {
    $('.square').detach();
    var gridPrompt = prompt('How many squares per side would you like to make the current grid?');

    var $grid = $('.grid');
    for (var i = 0; i < gridPrompt; i++) {

    var row = '<div>';

    for (var j = 0; j < gridPrompt; j++)
        row += '<div class = "square"></div>';

    row += '</div>';

    $grid.append(row);
    console.log(gridPrompt);
}

var newColor = ('#'+Math.floor(Math.random()*16777215).toString(16));
$('.square').on('mouseenter', function () {
    $(this).css({'background-color': newColor});

});

});

var newColor = ('#'+Math.floor(Math.random()*16777215).toString(16));
$('.square').on('mouseenter', function () {
    $(this).css({'background-color': newColor});

});

});

Here's the JSFiddle

2

There are 2 answers

0
0dyss3us On BEST ANSWER

The squares are responding correctly because they are being displayed as a table-cell, not because you have explicitly set the width to be 100vw. If these were displayed as block style elements, then the 100vw would mean a single block would span the entire viewport.

I think a better way to do this would be to display the squares as inline-block elements and calculate the explicit width and height based on the user's input.

edit: here's your updated fiddle with my changes following the comments http://jsfiddle.net/2xh2maya/2/

0
jaunt On

This can be achieved using flex. However, flex has some compatability issues. Take a look here for more information. So, this is my solution:

function LoadBlocks(){ 
  var grid = document.getElementById('container'),
      size = prompt('How many squares per side would you like to make the current grid?'),
      newColor = ('#'+Math.floor(Math.random()*16777215).toString(16));
  while (grid.hasChildNodes()){grid.removeChild(grid.lastChild);}
  for (y=0;y<size;y++){
    var row = document.createElement('div');
    row.className = "row";
    for (x=0;x<size;x++){
      var block = document.createElement('div');
      block.className = "object";
      row.appendChild(block);
    }
    grid.appendChild(row);
  }
  $("div.object").hover(function(){$(this).css("background-color", newColor);});
}
#container{
  width:500px;
  height:500px;
  position:absolute;
  top:50%;
  left:50%;
  transform:translate(-50%,-50%);
  display:flex;
  flex-direction: column;
}
.row{
  flex:1;
  display:flex;
}
.object{
  flex:1;
  background-color: wheat;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container"></div>
<input type="button" onclick="LoadBlocks()" value="Generate"/>

Side note: you may want to add an upper limit to the size the user can enter. I just tried 600 and that was soooo laggy.