Home > Mobile >  Optimized solution for filling entire page with DIVs
Optimized solution for filling entire page with DIVs

Time:07-20

I want to have a webpage whose entire viewable area is filled with divs. I am currently using the following code:

var wh= window.innerHeight;
var ww= window.innerWidth;
var area= wh * ww;
i= 1;
while(area > 0) {
document.getElementById("map").innerHTML = "<div class='map-box' id='box"   i   "'></div>";
area-= 20 * 20;
i =1; 
}
.map-box {width: 20px; height: 20px; border-color: grey; border-width: 1px; border-style: solid; display: inline-block; margin: 0; padding: 0;}
<body>
<div id='map'></div>
</body>

If you try to use this code is your browser, you will see that there are two flaws in this:

  • First, it creates too many extra divs which go outside the viewable screen.
  • Second, this code is also somewhat slow.

Can someone here help me address both of these flaws and also optimize this code for faster performance?

CodePudding user response:

1.) That <div> is not 20x20, because of the border:

let d = document.getElementById("test");
console.log(d.offsetWidth, d.offsetHeight);
.map-box {
  width: 20px;
  height: 20px;
  border-color: grey;
  border-width: 1px;
  border-style: solid;
  display: inline-block;
  margin: 0;
  padding: 0;
}
<div id="test" ></div>

2.) There's still the default border around the entire thing, and also some spacing between the lines:

var wh = window.innerHeight;
var ww = window.innerWidth;
var area = wh * ww;
i = 1;
while (area > 0) {
  document.getElementById("map").innerHTML  = "<div class='map-box' id='box"   i   "'></div>";
  area -= 22 * 22; // hardcoding is not that nice
  i  = 1;
}
.map-box {
  width: 20px;
  height: 20px;
  border-color: grey;
  border-width: 1px;
  border-style: solid;
  display: inline-block;
  margin: 0;
  padding: 0;
}

#map {
  background: blue;
}

body {
  background: red;
}
<div id='map'></div>

3.) Half cells are evil, so the width/height should be rounded downwards to a multiple of 22. Suddenly the grid is becoming an actual rectangle, at least in Chrome/Edge. The between-spacing is still a problem:

var wh = Math.floor(window.innerHeight / 22) * 22; // <--!!
var ww = Math.floor(window.innerWidth / 22) * 22;  // <--!!
var area = wh * ww;
i = 1;
while (area > 0) {
  document.getElementById("map").innerHTML  = "<div class='map-box' id='box"   i   "'></div>";
  area -= 22 * 22;
  i  = 1;
}
.map-box {
  width: 20px;
  height: 20px;
  border-color: grey;
  border-width: 1px;
  border-style: solid;
  display: inline-block;
  margin: 0;
  padding: 0;
}

#map {
  background: blue;
}

body {
  background: red;
  margin: 0; // <--!!
  padding: 0; // <--!!
}
<div id='map'></div>

  1. I don't actually know how to use line-height properly, this one works on my machine with my scaling/DPI, in Chrome/Edge, but that's all I can say about it. The 22-s are cut back, area now simply stores the number of <div>s to generate.

var wh = Math.floor(window.innerHeight / 22);
var ww = Math.floor(window.innerWidth / 22);
var area = wh * ww;
i = 1;
while (area > 0) {
  document.getElementById("map").innerHTML  = "<div class='map-box' id='box"   i   "'></div>";
  area--;
  i  = 1;
}
.map-box {
  width: 20px;
  height: 20px;
  border-color: grey;
  border-width: 1px;
  border-style: solid;
  display: inline-block;
  margin: 0;
  padding: 0;
}

#map {
  line-height: 0.6;
}

body {
  margin: 0;
  padding: 0;
}
<div id='map'></div>

CodePudding user response:

Instead of accessing dom element's inner html on each loop iteration - do it once after the loop with "prepared" data to set there

  const wh = window.innerHeight;
  const ww = window.innerWidth;
  let area = wh * ww;
  i = 1;
  const ms = Date.now();
  const divs = [];
  while (area > 0) {
    divs.push("<div class='map-box' id='box"   i   "'></div>");
    area -= 20 * 20;
    i  = 1;
  }
  document.getElementById("map").innerHTML = divs.join("");
  console.log("done fast", Date.now() - ms);

js fiddle with comparison https://jsfiddle.net/aL7zqwy9/

The final solution, not ideal but

<html>

<body>
  <div id='map'></div>
</body>

<style>
  body {
    margin: 0;
    padding: 0;
    /* Overflow appears when last row is added and shrinks the "width" */
    overflow-y: hidden;
  }

  #map {
    /* To exclude space between rows */
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
  }

  .map-box {
    width: 20px;
    height: 20px;
    border: 1px solid grey;
    display: block;
    margin: 0;
    padding: 0;
    /* So border thickness will not affect element size */
    box-sizing: border-box;
  }
</style>

<script>
  const cellSize = 20; // px
  const wh = window.innerHeight;
  const ww = window.innerWidth;
  
  // not always divisible by cell size without a remainder
  const columnsCount = Math.floor(ww / cellSize);
  const rowsCount = Math.floor(wh / cellSize);

  const cellsCount = columnsCount * rowsCount;
  console.log(`wh: ${wh}, ww: ${ww}, cols: ${columnsCount}, rows: ${rowsCount}`);
  const divs = [];
  for (let i = 0; i < cellsCount; i  ) {
    divs.push(`<div class='map-box' id='box${i}'></div>`);
  }

  document.getElementById("map").innerHTML = divs.join("");
</script>

</html>
  • Related