title: Draw clickable grid of 1 million squares
body: <p>I need to find a way to draw a 1000x1000 squares grid, each square is clickable and they must be independently color changeable. Like mines game. I can use HTML (pure or using Canvas or SVG), CSS and JavaScript for this.</p>
  
  <p>I know how to create one grid with these characteristics with JavaScript and CSS, it does well with 10x10 squares, with 100x100 the squares will turn into tall rectangles and 1000x1000 it loads, but the "squares" are soo much compressed that borders meet each other and renders a full gray page.</p>
  
  <p>I tried using HTML and JavaScript to draw SVG squares, the squares' size problem solves, but I don't know how to make they change color when clicked and when I set to load 1000x1000 squares it will freeze the browse and eventually crash the tab.</p>
  
  <p>Is this feasible in any way?</p>
  
  <h2>EDIT</h2>
  
  <p>Sorry if I wasn't clear, but yes, I need scroll bars in that. They are no problem for me.</p>
  
  <p>You can see the two trials I described here:</p>
  
  <p><strong>JavaScript and CSS</strong></p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var lastClicked;
  var grid = clickableGrid(100,100,function(el,row,col,i){
      console.log("You clicked on element:",el);
      console.log("You clicked on row:",row);
      console.log("You clicked on col:",col);
      console.log("You clicked on item #:",i);
  
      el.className='clicked';
      if (lastClicked) lastClicked.className='';
      lastClicked = el;
  });
  
  document.body.appendChild(grid);
       
  function clickableGrid( rows, cols, callback ){
      var i=0;
      var grid = document.createElement('table');
      grid.className = 'grid';
      for (var r=0;r&lt;rows;++r){
          var tr = grid.appendChild(document.createElement('tr'));
          for (var c=0;c&lt;cols;++c){
              var cell = tr.appendChild(document.createElement('td'));
              ++i;
              cell.addEventListener('click',(function(el,r,c,i){
                  return function(){
                      callback(el,r,c,i);
                  }
              })(cell,r,c,i),false);
          }
      }
      return grid;
  }</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>.grid { margin:1em auto; border-collapse:collapse }
  .grid td {
      cursor:pointer;
      width:30px; height:30px;
      border:1px solid #ccc;
  }
  .grid td.clicked {
      background-color:gray;
  }</code></pre>
  </div>
  </div>
  </p>
  
  <p><strong>JavaScript and HTML</strong></p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code> 
      document.createSvg = function(tagName) {
          var svgNS = "http://www.w3.org/2000/svg";
          return this.createElementNS(svgNS, tagName);
      };
      
      var numberPerSide = 20;
      var size = 10;
      var pixelsPerSide = 400;
      
      
      
      var grid = function(numberPerSide, size, pixelsPerSide, colors) {
          var svg = document.createSvg("svg");
          svg.setAttribute("width", pixelsPerSide);
          svg.setAttribute("height", pixelsPerSide);
          svg.setAttribute("viewBox", [0, 0, numberPerSide * size, numberPerSide * size].join(" "));
          
          for(var i = 0; i &lt; numberPerSide; i++) {
              for(var j = 0; j &lt; numberPerSide; j++) {
                var color1 = colors[(i+j) % colors.length];
                var color2 = colors[(i+j+1) % colors.length];  
                var g = document.createSvg("g");
                g.setAttribute("transform", ["translate(", i*size, ",", j*size, ")"].join(""));
                var number = numberPerSide * i + j;
                var box = document.createSvg("rect");
                box.setAttribute("width", size);
                box.setAttribute("height", size);
                box.setAttribute("fill", color1);
                box.setAttribute("id", "b" + number); 
                g.appendChild(box);
                svg.appendChild(g);
              }  
          }
          svg.addEventListener(
              "click",
              function(e){
                  var id = e.target.id;
                  if(id)
                      alert(id.substring(1));
              },
              false);
          return svg;
      };
      
      var container = document.getElementById("container");
      container.appendChild(grid(100, 10, 2000, ["gray", "white"]));
  
      </code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;div id="container"&gt;
      
  &lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>I will be trying implementing the given answers and ASAP I'll accept or update this question. Thanks.</p>
  
  <h2>SOLUTION</h2>
  
  <p>Just to record, I managed to do it using canvas to draw the grid and the clicked squares and added an event listener to know where the user clicks.</p>
  
  <p>Here is the code in JavaScript and HTML:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>function getSquare(canvas, evt) {
      var rect = canvas.getBoundingClientRect();
      return {
          x: 1 + (evt.clientX - rect.left) - (evt.clientX - rect.left)%10,
          y: 1 + (evt.clientY - rect.top) - (evt.clientY - rect.top)%10
      };
  }
  
  function drawGrid(context) {
      for (var x = 0.5; x &lt; 10001; x += 10) {
        context.moveTo(x, 0);
        context.lineTo(x, 10000);
      }
      
      for (var y = 0.5; y &lt; 10001; y += 10) {
        context.moveTo(0, y);
        context.lineTo(10000, y);
      }
      
      context.strokeStyle = "#ddd";
      context.stroke();
  }
  
  function fillSquare(context, x, y){
      context.fillStyle = "gray"
      context.fillRect(x,y,9,9);
  }
  
  var canvas = document.getElementById('myCanvas');
  var context = canvas.getContext('2d');
  
  drawGrid(context);
  
  canvas.addEventListener('click', function(evt) {
      var mousePos = getSquare(canvas, evt);
      fillSquare(context, mousePos.x, mousePos.y)
  }, false);</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;body&gt;
      &lt;canvas id="myCanvas" width="10000" height="10000"&gt;&lt;/canvas&gt;
  &lt;/body&gt;</code></pre>
  </div>
  </div>
  </p>